Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion. Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules. |
12th September 2015, 22:22 | #1 | Link |
Formerly davidh*****
Join Date: Jan 2004
Posts: 2,492
|
rgba_rpn/y8_rpn - RPN pixel manipulation
My new filter, rgba_rpn/y8_rpn, allows the arbitrary manipulation of pixel values from multiple clips, and can... well, it can do a lot.
Download: rgba_rpn0.1.zip Anti-virus software: it's possible that your anti-virus software may find the DLL suspicious, because it generates executable code on the fly. You'll just have to trust me Using strings in reverse Polish notation, pixel values can have all kinds of mathematical operations performed on them. It can use YUV as well as RGB clips as input (although only the Y channel of YUV clips is available), and has several different dithering modes (basically: none, ordered, or random). Please refer to the documentation and RPN guide, which are probably required reading if you want to understand the following examples. So what can it do? This is a hard question to answer, because it can do so much. You can use it to draw an anti-aliased circle: Code:
blankclip.y8_rpn("255 x w 0.5 * - dup * y h 0.5 * - dup * + sqrt 128 - 255 * -") Or a rotating (animated) anti-aliased square: Code:
blankclip.y8_rpn(" x w 0.5 * - @X^ y h 0.5 * - @Y^ 0.01 n * sincos @S^ @C^ X S * Y C * + @A^ X C * Y S * - @B^ 255 A abs 150 + B abs 150 + max - 255 * ") A more practical example - this call will desaturate any green pixels (those which have a green value greater than both red and blue): Code:
clip.rgba_rpn("[r0] 0.3 * [g0] 0.59 * [b0] 0.11 * + + [c0] [g0] [r0] [b0] max > ?") It animated-wipes (this one complete with gamma awareness and dithering): Code:
a=colorbars b=version.pointresize(a.width,a.height).trim(0,50) a=a.reduceby2 b=b.reduceby2 rgba_rpn("64 @W x W + w W + t * - \ 1 zmax pi * cos 1 + 0.5 * @A [c0] dup * * 1 A - [c1] dup * * + sqrt", 1, b, a) It sharpens (code omitted for space): It blurs: It weird blurs: And to really demonstrate the flexibility of rgba_rpn, the following example (with the help of some basic Avisynth functions) implements the w3fdif deinterlacer (discussed recently here), which was the basis for kerneldeint: Code:
mpeg2source("test.d2v") # interlaced source converttorgb24(interlaced=true) sep = separatefields odd = sep.selectodd even = sep.selecteven x = odd.blankclip(length=1) + odd.trim(0,framecount-2) y = even.trim(1,0) + even.blankclip(length=1) woven = interleave(x,y).weave rgba_rpn(" [c0] [c1] + 0.170 * [c0(0,-1)] [c0(0,1)] + 0.526 * [c0(0,-2)] [c0(0,2)] [c1(0,-2)] [c1(0,2)] + + + -0.116 * [c0(0,-3)] [c0(0,3)] + -0.026 * [c0(0,-4)] [c0(0,4)] [c1(0,-4)] [c1(0,4)] + + + 0.031 * + + + + ", last, woven,0,1) separatefields selectevery(2,1,0) interleave(last,sep) weave assumeframebased I appreciate these may be hard to understand; using RPN doesn't help when it comes to clarity! I will go through some examples in more depth in subsequent posts, if anybody wants to see them. Alternatively, I'll be happy to answer questions of the form "How would I..." Last edited by wonkey_monkey; 12th September 2015 at 22:40. |
12th September 2015, 22:42 | #2 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
My word you've done it again, you truly are the Doctor
Love the 'dup' rpn shortcut (duplicate top of stack), pity masktools never implemented this [I think it was requested, perhaps by you]. EDIT: 'Swap' too, Perhaps I steal your rpn code one day
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 12th September 2015 at 22:46. |
12th September 2015, 23:00 | #4 | Link |
47.952fps@71.928Hz
Join Date: Mar 2011
Posts: 940
|
This looks intriguing!
This will get used to recognizing RPN. In the mean time, I definitely look forward to seeing more examples of anything fun.
__________________
Win10 (x64) build 19041 NVIDIA GeForce GTX 1060 3GB (GP106) 3071MB/GDDR5 | (r435_95-4) NTSC | DVD: R1 | BD: A AMD Ryzen 5 2600 @3.4GHz (6c/12th, I'm on AVX2 now!)
|
13th September 2015, 00:32 | #6 | Link |
Formerly davidh*****
Join Date: Jan 2004
Posts: 2,492
|
The shapes were just to demonstrate the wide variety of things it can do. There's not much point asking me what you can do with it, because there are too many things you can do with it.
For example, calculating the Mandelbrot set: Code:
blankclip(width=960,height=640).y8_rpn(" 0 255 a 3 * 2 - @A @X^ b 2 * 1 - @B @Y^ X dup * Y dup * - A + @T^ X Y 2 * * B + @Y^ T @X^ X dup * Y dup * - A + @T^ X Y 2 * * B + @Y^ T @X^ X dup * Y dup * - A + @T^ X Y 2 * * B + @Y^ T @X^ X dup * Y dup * - A + @T^ X Y 2 * * B + @Y^ T @X^ X dup * Y dup * - A + @T^ X Y 2 * * B + @Y^ T @X^ X dup * Y dup * - A + @T^ X Y 2 * * B + @Y^ T @X^ X dup * Y dup * - A + @T^ X Y 2 * * B + @Y^ T @X^ X dup * Y dup * - A + @T^ X Y 2 * * B + @Y^ T @X^ X dup * Y dup * - A + @T^ X Y 2 * * B + @Y^ T @X^ X dup * Y dup * - A + @T^ X Y 2 * * B + @Y^ T @X^ X dup * Y dup * - A + @T^ X Y 2 * * B + @Y^ T @X^ X dup * Y dup * - A + @T^ X Y 2 * * B + @Y^ T @X^ X dup * Y dup * - A + @T^ X Y 2 * * B + @Y^ T @X^ X dup * Y dup * + 4 < ? ",-1,2) The moiré patterning is, I think, due to FPU overflow exceptions, and is also why the frame rate is so low. I'm working on it, but I thought it was interesting enough by itself to leave in on the screenshot. Add more repetitions (NB: more than 29 reps results in an access violation, probably because the code becomes too large for the allocated buffer, or because I haven't been generous enough with one of my arrays - I will look into this) of the repeated line for greater accuracy: A filter which can do things as diverse as desaturating green pixels, compositing chroma key clips, and calculating the Mandelbrot set. Hopefully you can see why asking someone else "what can I do with it" is not a very meaningful question in this situation. |
13th September 2015, 01:02 | #7 | Link |
Formerly davidh*****
Join Date: Jan 2004
Posts: 2,492
|
Animated zoom into the Mandelbrot set (no more moiré, 25fps on a 2.2GHz quad core i7):
Code:
a="X dup * Y dup * - A + @T^ X Y 2 * * B + 2 min @Y^ T 2 min @X^ " b=a+a c=b+b blankclip(width=960,height=640,length=1600).y8_rpn(" 0 255 a 3 * 2 - -1.2947627 - 1.01 n ^ / -1.2947627 + @A @X^ b 2 * 1 - 0.4399695 - 1.01 n ^ / 0.4399695 + @B @Y^ "+c+c+c+c+c+b+a+" X dup * Y dup * + 4 < ? ",-1,2) (this really wasn't what the filter was intended for!) David |
13th September 2015, 10:44 | #9 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,867
|
Very nice! Would've loved this a few years ago. The only thing I'm missing is, a shift operator, and support for stacked 16 bit format built-in. Defining some kind of macros/functions would make it much easier to use, especially as they can be shared as a library and then built upon. Also the rpn converter of masktools could be used. How are virtual pixels handled? How would you average all pixels on a line? In squares? Finally, some kind of "loops" would be very nice, for example n REP to repeat the last string of operations n times. But how to mark the string? Maybe a new kind of variable, and maybe enclose the macro in [] ? Like [* dup] #SQ x #^SQ do a squaring x^2
[2 *] #SHIFT x #^SHIFT n REP #x<<n shift up n times the x or better [2 *] REP #SHIFTn x n #^SHIFTN #shift x n times left Then you could have a library and just pre-pend that to your string, and all these new functions are defined for you. I'd write some. Last edited by jmac698; 13th September 2015 at 11:02. |
13th September 2015, 10:52 | #10 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,867
|
There's also my Mandelbrot plugin
http://forum.doom9.org/showthread.ph...42#post1582742 Also an 8-bit Mandelbrot with masktools http://forum.doom9.org/showthread.ph...09#post1539509 I should rewrite it with yours so I can use floats Yes, I'd be interested in you fixing the bugs to make a nice Mandelbrot possible. |
13th September 2015, 11:06 | #12 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,867
|
Btw, a nice trick for a fill function is xor with the last byte, I'm leaving out some details but it's like the Amiga does in hardware, draw some borders and they get filled in horizontally, would be neat to try to write that.
@feisty yes exactly! That's why I loved masktools and asked for some mods to it. a48 was a lot inspired by my requests. Also I like that it's in script, and easily exposes the algorithm, so nothing is ever lost by being closed source. Last edited by jmac698; 13th September 2015 at 11:09. |
13th September 2015, 12:42 | #13 | Link | |||
Formerly davidh*****
Join Date: Jan 2004
Posts: 2,492
|
It's called "multiply" And it might be quicker than implenting a real shift, which would involve a conversion from double to int to double.
Quote:
Quote:
Quote:
I'm thinking about loops and jumps and forward ifs, but they all need careful consideration. If you conditionally jump from one point to another, you have to ensure (and the compiler would have to enforce) that the stack will be in exactly the same condition (which is not just a matter of how many items are on the stack, but also which are on the FPU stack and which are on the "overflow" stack) at the end of both branches. And that's easier said than done. Last edited by wonkey_monkey; 13th September 2015 at 12:49. |
|||
14th September 2015, 18:01 | #14 | Link |
Formerly davidh*****
Join Date: Jan 2004
Posts: 2,492
|
Here's an example explained in detail. It simulates the "zebra stripes" that some cameras show in the viewfinder to show out-of-range white values.
Code:
avisource("...") levels(0,1,200,0,255,coring=false) # make some white values illegal for testing purposes striped=last.y8_rpn(" x y + n + 128 * 1024 % [y0] dup 255 > ?") mergechroma(striped.converttoyv12, last) Next comes the RPN call. First, there's this line: Code:
x y + n + 128 * 1024 % Code:
[y0] Next: Code:
dup 255 > Next: Code:
? Finally a call to mergechroma restores the colour to the clip (rgba_rpn/y8_rpn ignore UV channels completely). By this method, pixels which have an illegal luma value are replaced with the stripey pattern: NB: because y8_rpn clamps output values to the legal range, by default, the output will no longer have any out-of-range luma pixels. I'm not sure this is the best way to behave, but it's always been a minefield. Coming soon: loops and commenting. |
14th September 2015, 19:07 | #16 | Link |
Formerly davidh*****
Join Date: Jan 2004
Posts: 2,492
|
Easier for a human because it's familiar, sure, though I'm not sure it's fundamentally easier. We should all be using RPN! And writing dates in YYYY-mm-dd format...
The reason for using RPN is because it's much, much easier for a computer to parse and therefore to program for. An infix-to-RPN converter, such as masktools has, would be the answer, but it's not a big priority for me. Last edited by wonkey_monkey; 14th September 2015 at 19:10. |
14th September 2015, 19:34 | #17 | Link | |
Registered User
Join Date: Mar 2012
Location: Texas
Posts: 1,664
|
Quote:
--- I understand the concept behind RPN, the thing I don't understand is how does one come up with the numbers to do what you wanted it to do (I know is not but to me it just seems arbitrary). Is there any reference material that teaches video processing and RPN? I've looked but have not found anything, in this MaskTools guide tp7 mentioned that this type processing is called a “point operation” in all image processing books. Is this true for rgba_rpn/y8_rpn also? Last edited by Reel.Deel; 14th September 2015 at 19:59. Reason: update link |
|
14th September 2015, 19:47 | #18 | Link | ||
Formerly davidh*****
Join Date: Jan 2004
Posts: 2,492
|
Quote:
Quote:
Give me an example of something you might want to do (even if it's just a silly example) and I can try to take you through how to do it. |
||
14th September 2015, 20:12 | #19 | Link | |
Registered User
Join Date: Mar 2012
Location: Texas
Posts: 1,664
|
Quote:
I've been playing around with PhotoDemon's distort filters, it would be nice to able to do such things in AviSynth (especially animated). I like the 'Poke' effect, might be more suitable for xyremap though. Last edited by Reel.Deel; 14th September 2015 at 20:22. Reason: typo |
|
14th September 2015, 20:15 | #20 | Link |
Formerly davidh*****
Join Date: Jan 2004
Posts: 2,492
|
It depends on the exact effect you want to replicate. xyremap can do a polar remap (first example on that page), but it can't do a zoom blur by itself (and nor can rgba_rpn). Put the two together and you could just about manage it, but it wouldn't be very efficient.
|
Thread Tools | Search this Thread |
Display Modes | |
|
|