View Full Version : Partially debugged version of the MaskTools : 1.5.6


Manao
21st December 2003, 20:04
I corrected the issue with functions Inpand / Expand ( and normally also Inflate / Deflate, but I didn't check these ones ).

There were in fact several issues, one of them being the MMX version of these functions, so for the moment, you can't have these 4 functions mmxed.

Please report any bugs / slowdown you may encounter with this version. Especially slowdown in fact, since I'm clearly no expert with VC++ ( first time I used it ). I only checked speed with Binarize, it was as fast as with the former version ( 1.4.1 ), so I hope it'll the same with other functions.

Finally, I didn't ask Kurosu the permission to do that ( no mail adress in his readme ), so I hope he won't mind.

You'll find the new version here (http://manao4.free.fr/)

Edit : Inflate and deflate work too.

Chainmax
21st December 2003, 21:41
Would it be possible to add YUY2 support?

K-Dash
21st December 2003, 22:03
Link broken.

Manao
21st December 2003, 22:19
Chainmax : it would be possible, with a lot of time. But I don't really think it's useful, since most of the filters are working in YV12 ( except Dust ). So it's not one of my priorities yet. For what purpose would you have the use of an YUY2 version ?

K-Dash : link is working, I'll make myself clearer : right click on the link, do 'copy adress', paste it in your adress bar, it'll work ( at least it's working for me ). I emphasised that sentence in my first post.

@all : I'll be away from my computer for 2 weeks soon, so I'll cope with the most obvious bugs first ( and there are plenty ). Another version should be up for tomorrow, correcting the multiple use of a same function with different mode. ( right now, except for expand / inpand / deflate / inflate, using more than once a function with a different mode always applies the function with the same mode ).

Edit : oups, my bad, only the 4 I corrected were subject to this bug. I should have read the changelog :rolleyes:

K-Dash
22nd December 2003, 02:33
It works, my bad :rolleyes:

Chainmax
23rd December 2003, 18:39
Originally posted by Manao:
Chainmax : it would be possible, with a lot of time. But I don't really think it's useful, since most of the filters are working in YV12 ( except Dust ). So it's not one of my priorities yet. For what purpose would you have the use of an YUY2 version ?
Well, one of the best de-rainbowers out there (sh0dan's script) uses MaskTools. It would be awesome to be able to use it on TV captures without having to make an extra colorspace conversion. I don't know what MaskTools functions it uses, though.

mf
23rd December 2003, 18:43
Just use AVISynth's plane exchanging functions and process as Y.

Chainmax
24th December 2003, 00:28
Huh?

sh0dan
24th December 2003, 09:21
Originally posted by Chainmax
Well, one of the best de-rainbowers out there (sh0dan's script) uses MaskTools. It would be awesome to be able to use it on TV captures without having to make an extra colorspace conversion. I don't know what MaskTools functions it uses, though.

I wrote a YUY2 version, that doesn't subsample chroma, so you don't loose anything but a bit of speed.

mf
24th December 2003, 13:08
Originally posted by Chainmax
Huh?
http://www.avisynth.org/index.php?page=Swap

Chainmax
24th December 2003, 17:47
sh0dan: does that version perform as good as the "30% faster" YV12 one? I don't mind a little less speed if the results regarding IQ are the same.

mf: thanks for the link, but I don't understand how that can help me use a YV12 filter on a YUY2 source without having to make a colorspace conversion.

mf
24th December 2003, 21:45
Originally posted by Chainmax
mf: thanks for the link, but I don't understand how that can help me use a YV12 filter on a YUY2 source without having to make a colorspace conversion.
Not without conversion, but without loss of image anyway.
input = last
input.Greyscale().ConvertToYV12()
y = last
input.UToY().ConvertToYV12()
u = last
input.VToY().ConvertToYV12()
v = last

y.Sh0dansl33tscript().ConvertToYUY2()
yprocessed = last
u.Sh0dansl33tscript().ConvertToYUY2()
uprocessed = last
v.Sh0dansl33tscript().ConvertToYUY2()
vprocessed = last

YToUV(uprocessed, vprocessed, yprocessed)

Seeing what you want is rainbow removal, you can probably leave out the processing of the luma channel (y).

sh0dan
25th December 2003, 00:15
Exactly. However the rainbow tool requires luma and chroma to be reliable as they are interdependant. The YUY2 script in this thread (http://forum.doom9.org/showthread.php?s=&threadid=64432&highlight=rainbow) does however account for this and it filters YUY2 chroma without affecting chroma resolution, by using an approach like mf's suggestion.

I don't think the speed is much lower than YV12 anyway.

Manao
4th January 2004, 16:52
New version, correcting some bugs ( 3DNow intructions should have been removed, some optimizations have been disabled because they gave a different output than the non optimized one ), and optimizing Binarize and Invert ( they were the simplest ).

Get it here (http://www.geocities.com/manao47/Filters/masktools-v1.4.3.zip) ( copy & paste, as usual )

There should be bugs, so I'm waiting the bug report.

Manao
5th January 2004, 18:46
mf, kurosu and the others : since AviSynth 2.54 alpha, there is an 'overlay' filter inside AviSynth which works in YV12 and do the job of MaskedMerge, YV12Layer and YV12Substract ( and more )

I'm wondering whether to let these filters in the next release, as soon as AviSynth 2.54 is out.

What do you think of it ?

mf
5th January 2004, 19:53
Well, as long as Overlay is C only I'm not using it. I was already relieved the change to YV12 gave a speed boost (although not on my PC - the same old 3fps), and I'm not going to make it slow just to keep it to internal AVS filters.

Manao
5th January 2004, 21:07
I looked more closely to the source code, Overlay do use MMX optimizations. However, I didn't see Overlay was converting YV12 to YUY2, so using it is not an option yet. So I'll let these functions inside the MaskTools.

I tested MMX optimizations in MaskedMerge ( they are currently disabled ), there are not very effective, at least for me. So I'll try to improve them ( though I'm not sure I'll succeed ).

Edited : Damn, I was wrong one more time. Optimizations _are _ effective with MaskedMerge, I did forget to enable them :rolleyes:

I'll test them and make another build available soon.

Edited 2 : Build available, with optimizations back for MaskedMerge. The optimized filters are : MaskedMerge, YV12Layer, YV12Subtract, Binarize, Invert, EdgeMask ( Robert, Special, Sobel, Cartoon only ) and FastFitPlane. I modified optimizations for Binarize only, and there will be problems if these optimizations are used with an offset, so I added a usemmx parameter, defaulted to true, which allows to disable mmx for Binarize. Unless there are bugs report, there should not be any other version for a moment, at least from me.

Manao
10th January 2004, 12:48
OK, new version, with a new filter : MotionDetection. It builds the mask of the moving pixels.

Here is the changelog :

1.4.5
- Added MotionDetection filter, no MMX / assembler optimizations for it yet. It takes the idea of Sansgrip's filter (NoMoSmooth) and outputs the motion mask directly in the correct colorspace for the MaskTools.

So basically it's an adaptation of NoMoSmooth to YV12 with giving the choice to the user of the spatial filter he wants to use. But since I only took the algorithm of SansGrip, not his code, bugs are waiting to be discovered.

Optimizations will come later.

I updated the link on the first page.

sh0dan
10th January 2004, 12:56
Great work Manano - should I move this to Usage?

Manao
10th January 2004, 13:15
Yes, thank you.

sh0dan
10th January 2004, 13:25
(I also changed the subject to 1.4.5 if you don't mind).

This and msharpen are the only filters capable of producing non-greyscale masks for Overlay, btw.

Manao
10th January 2004, 23:39
New version, with optimizations for the MotionDetection filter.

Changelog :

1.4.6
- Made the scenechange detection in MotionDetection iSSE optimized ( meaning you need an Athlon XP / Pentium IV ). It works with an Athlon XP, it is not tested with an Pentium IV, it is possible to disable it by using usemmx = false in the paremeters of the filter.
- Optimized the calculation of the motion, without using MMX ( just by avoiding to do 3 times the same calculations... ). So the filter should be more or less three times faster.

As usual, please report the bugs.

gamr
11th January 2004, 16:36
heeeeeeeeeeeeeeeeeeeeeeeelp! *grin*

i tested motiondetection() with a high threshold 2d cleaner to see what it worked like during high motion scenes and that went well, then i realized that this would be perfect to use to replace my old YDifferenceFromPrevious() conditional filter for antiblink to cut it out in high motion scenes (in some scenes it still ghosted and made a mess, this in theory should fix it). the idea is once motion is beyond x to use the original instead of the antiblink'd clip but im clueless how to do that here

function new_fix_rainbows(clip)
{
mask=clip.motiondetection()
norainbow=clip.antiblink(1,35,true)
return stackvertical(maskedmerge(clip,norainbow,mask,Y=1,U=3,V=3),mask)
}

iv maxed out antiblink so as i know what areas its affecting, generally its set to 5,35,false, any suggestions on how to get this to work how i want it to?

Manao
11th January 2004, 18:59
motionmask = clip.motiondetection(thY1 = 30, thY2 = 30, thSD = 10,y=3,u=1,v=1)
motionmask = motionmask.invert(y=3,u=1,v=1).fastfity2uv()
derainbowedclip = clip.antiblink(1,35,true)
return clip.maskedmerge(derainbowedclip, motionmask,y=2,u=3,v=3)That's at least the theory. But I just found that fastfity2uv is buggy, so use fity2uv() instead. Choose the scene detection threshold in order only to detect scenechanges ( so I would raise it to 30 or 40 ).

If maskedmerge wasn't buggy, you wouldn't need the invert, and you would then invert clip and derainbowedclip in the last line, but it doesn't work on my computer ( I'll investigate ).

Hope this'll help

mf
11th January 2004, 19:19
Originally posted by gamr
i tested motiondetection() with a high threshold 2d cleaner to see what it worked like during high motion scenes and that went well, then i realized that this would be perfect to use to replace my old YDifferenceFromPrevious() conditional filter for antiblink to cut it out in high motion scenes (in some scenes it still ghosted and made a mess, this in theory should fix it). the idea is once motion is beyond x to use the original instead of the antiblink'd clip but im clueless how to do that here
Actually, you've just given me a wonderful idea for mfRainbow (though not in the way you do, I want to detect motion in U/V and purposely have my filter work there). Thank you!

Manao
11th January 2004, 20:30
I forgot to check that the width is mod8 in MotionDetection, so if the width isn't mod8, add "usemmx = false" in order to avoid errors.

It will be corrected in the next version.

Kurosu
11th January 2004, 23:27
I'll try to summarize my comments:
1) maskedmerge bugged? To me:
maskedmerge(clip1, clip2, mask1)
is approximately equivalent to:
maskedmerge(clip2, clip1, mask1.Invert())
Sure it isn't really, because I use the weight (255-x) instead of (256-x). But 256 doesn't fit into a byte.

2) antiblink
Whatever version, it is my oldest filter. There is probably a lot to optimize. Here's how it works:
- check for chroma oscillations (the oscillation is the rainbow) over 4 frames; mf, beware that those very oscillations can falsely be interpreted as motion on chroma
- check for luma variation for the current chroma value: if under a threshold (ie, we consider the luma change not to be due to motion), don't filter (in fact some heavy smooth would be better, but the rainbow criterion based on chroma oscilation is insufficient). That's what do real 3D comb filter (see on some broadcast how the first frame after a scene change has rainbow and how it gets eliminated afterwards) besides temporal filtering.
Using 2 masks, one for motion (taking the difference between the 3x3 average?) and one for edges together with maskedmerge is a possibility, but I never got something satisfying

3) MMX in motiondetection
a) Manao, you declare it being iSSE - I only see MMX code
b) usemmx: is the CPU check in the constructor insufficient? It sure lacks width checks

4) Some useless filter:
- LUT - never finished it would require arrays to be passed, and functions to fill arrays - unsatisfying, I'm afraid
- Logic: who has ever used it? me, but that doesn't count

5) binarize
You should just make the threshold into a char by removing 127, and use pcmpgtb, bypassing the substraction

6) speed-up
iSSE optimization would be mostly about adding prefetch around and unrolling loops. Cheap optimization, good performance gains for binarize for instance. nasm is sure a winner to help avoiding ugly VC++ macros.

7) Code size
- Build target matters
- VC7 is surely better at optimizing and unrolling loops
- UPX is your friend

8) Suggested additions (I've added some myself, but the framework isn't compatable anymore and I have no time for commenting it):
- generalconvolution (MMXing was a pain to cope with the signedness of most WORD operations)
- Combmask (hint: Decomb provides a neat detector)
- a real LUT filter, generalizing levels (for instance, sinus, exponential, square root, invert, ...)
- add some real edge detectors. The ones in edgemask are really primitive, not enough the full ones. Laplacian/Derivative of Gaussian with a zero-cross detection gave me better results but are really the slower one can afford (except mf maybe). Thresholding here is as optimizable as in Binarize
Note: always use coring=false with levels. We want our 0 ad 255 in our masks. Compatibility with standards and old materials is sure a good think, but such example shows the limit of it (who said NTSC?)

[last EDIT]Tried to make sense[/EDIT]

Manao
12th January 2004, 00:14
Thanks a lot Kurosu for your comments !

When I said maskedmerge was buggy, I precised 'on my computer' later. When I tested it with the following script :source = MPEG2Source("R:\hours.d2v",cpu2="oooooo")
motionmask = source.motiondetection(thY1 = 30, thY2 = 30, thSD = 10,y=3,u=1,v=1)
motionmask2 = motionmask.fity2uv()
derainbowedclip = source.blankclip(color = $FF00FF).mergeluma(source,1)
return derainbowedclip.maskedmerge(source , motionmask2,y=2,u=3,v=3)It gaves me vertical black lines espaced by 4 pixels ( whereas, using invert, and inverting the place of the source and the derainbowedclip the result was normal ). Now, I can't reproduce the phenomenon, so I don't know what happen. It may be Windows ( I haven't rebooted for 10 days, and several of my tests while developping MotionDetection were more than suspects ( frames duplicating themselves in cycle for example ). Anyway, now it works, so I'll assume it was not MaskedMerge in cause ( but I'll still check the MMX version, since the clip I added may not have had the same pitch as the first one ).

For the MMX in MotionDetection, I use psadbw, which is reported as iSSE by the documentation I use ( Tommesani.com ). The usemmx parameters is very helpful when debugging, that's why I left it ( it is set to true by default anyway ).

For binarize, I didn't thought of that, thank you very much , I'll try it ASAP.

For the prefetch, I tried, but I never got any clear speed improvment ( 2-3 % at most ). I must have done something wrong, but I never found what.

I'll see what I can do with your addition proposals ( as soon as I've the time ). And I'll use UPX for the next release ( I already use VC7, and compile with the 'release' target ).

mf
12th January 2004, 10:30
Originally posted by Kurosu
2) antiblink
Whatever version, it is my oldest filter. There is probably a lot to optimize. Here's how it works:
- check for chroma oscillations (the oscillation is the rainbow) over 4 frames; mf, beware that those very oscillations can falsely be interpreted as motion on chroma
That's my whole idea. Currently, I have chroma edges multiplied by luma edges (where luma edges are weighted slightly higher, but if there isn't much edge in chroma, luma edge will get canceled out anyway), and this works pretty good except for black/white text on a colored background. This will also generate edges and blur the text in question to death. Now this isn't very visible (in the same way as sh0dan's rainbow killer simply destroys most of the chroma while not being very noticable), but it bugs me. So multiplying that chroma*luma edge mask with a chroma motion mask, should cancel out my false chroma edges and solve the problem. I should then also be able to use more destructive filtering on the rainbows because there's reduced danger of false matches. Of course, it will make my filter even slower, but how could I stay notorious of slow filters if I don't keep adding things to make them slower :D.

Didée
12th January 2004, 12:37
Though my "testing status" is still v1.4.4, I'd like to point out that inflate/deflate is still problematic for me: the plugin often returns _green_ masks after using in/deflate. From the "changelog" I suppose this is still present in 1.4.6. (?)

originally posted by Kurosu

- Logic: who has ever used it? me, but that doesn't countPlus me, and that already makes two of us ;)
Last time I tried to use Logic was in v1.4.0. There it was impossible to use any other function once Logic was called. Could be fixed in the meantime, I must check the new version for that.

Logic also seems invaluable to me, for example for [**censored to keep the surprise**] :)

- Didée

mf
12th January 2004, 13:00
Originally posted by Didée
Though my "testing status" is still v1.4.4, I'd like to point out that inflate/deflate is still problematic for me: the plugin often returns _green_ masks after using in/deflate. From the "changelog" I suppose this is still present in 1.4.6. (?)
That's cause lots of MaskTools functions like to fill the chroma planes with whatever they see fit. U= and V= should override this, and if not, just use MergeChroma (if you want to keep the chroma) or Greyscale().

Manao
12th January 2004, 13:05
1.4.0 had an issue with multiple instances of the same filter. Kurosu corrected it in the 1.4.1. I looked quickly the source code and didn't see anything wrong specific to Logic functions.

For the inflate / deflate, since mf didn't reported any issue, and since I found nothing wrong while testing, I think you did something wrong. However, I'll check when I'll come back home, because I didn't check these functions since 1.4.2. Meanwhile, could you give me description of the cases when you get green masks ? ( avs scripts mainly, and if there were a lot of program running on your computer ) Is it systematic ?

Edit : seing the mf's post, I'll add that if U and V planes are null, the picture will be green ( from dark green to bright ). When both chroma planes are 255, picture is pink / violet. When you said green, I thought uniform dark green ( meaning all three planes null ). By default, U and V parameters are at 1, which means chroma plane isn't processed ( it is roughly the result of a malloc )

Didée
12th January 2004, 14:35
Well, the effect was often like that:

- script is set up to return the mask only:

# something like this
edgemask=[function_of_edge_detection]
edgemask.inflate()
return(last)

- load script into VdMod

- The clip is fine green (RGB 0,255,0)

- When "playing" the script, the green turns to normal coloring after some number of frames, plays normal for some frames, goes green again ...

But yes, simply converting the whole thing to greyscale explicitely would be an idea, indeed :o

I only thought to mention my experience, while the topic is up ... if no-one else is experiencing this behaviour, then it must be a PEBKAC problem on my side ;)

- Didée

Kurosu
12th January 2004, 15:51
It's all in the docs...
3 = do the work
2 = copy if can be copied
1 = leave as such

What happens:
- on first call, an empty frame is generated by malloc (or new, but in fact more low level functions you never access directly) and left to fill by whatever happends. Although it's not guaranted because of memory reuse, it is filled with 0, ie green
- on next calls, avisynth reuses frames that are around and don't need to be conserved; you get what is left from say some of the previous frames (maybe from the ones given to the filter)
- no more frames are made, the old ones (<=>their memory space) are conserved; go into a loop

Why waste CPU cycles while you won't use that information? Consider what you are really using, and what really needs to be kept. mftoon only works on luma, so why even consider the chroma planes? I made the default in almost all filters to only use chroma. Sure, it looks weird, but that *shouldn't* matter.

mf
12th January 2004, 19:18
Originally posted by Kurosu
What happens:
- on first call, an empty frame is generated by malloc (or new, but in fact more low level functions you never access directly) and left to fill by whatever happends. Although it's not guaranted because of memory reuse, it is filled with 0, ie green
- on next calls, avisynth reuses frames that are around and don't need to be conserved; you get what is left from say some of the previous frames (maybe from the ones given to the filter)
- no more frames are made, the old ones (<=>their memory space) are conserved; go into a loop
Which comes back to what I said: "fills chroma with whatever they see fit" :D. I've seen completely green, echoing in the chroma planes (chroma lagging behind the luma), just plain garbage, and whatnot. But it really doesn't matter ;).

Manao
14th January 2004, 00:17
New version, with some corrections, and a new filter :

Changelog :

1.4.7
- Renamed MotionDetection to MotionMask. I know it's kind of silly, but it's a lot more coherent that way.
- Added the check of the width for the use of iSSE in MotionMask
- Slightly modifyed MMX optimizations in Binarize.
- Added a new filter : YV12Convolution. It allows you to convole the picture by a matrix of (almost) any size.

Documentation on the new filter :

12) YV12Convolution(clip clip, string horizontal, string vertical, int total, bool automatic )
- horizontal and vertical are lines of integer coefficients spaced by any number of space or characters (different from number : e.g : "1 5 9 g 5" and "1 5 9 5" are equivalent ( at least they should )). These lines represents vectors. Their length must be odd ( in order to be centred on a pixel ). The matrix of convolution will be equal to vertical' * horizontal / total ( matlab notation, for those who know matlab, else, the matrix' coefficient a(col,row) is equal to horizontal(col) * vertical(row) / total )
- If automatic is set to 'true', total is the sum of the coefficients of the matrix. It means that, that way, overall brightness of the picture isn't touched.
- Negative coefficients aren't yet supported ( they'll come very soon, however ).
- Default values are horizontal = "1 1 1", vertical = "1 1 1", total = 9, automatic = true

A few remarks :
- division by 'total' is made at the end of the calculation of the value of a pixel.
- There are no MMX optimizations ( and I don't think they'll ever be some ), but it's not too slow ( ~12fps on an athlon XP with a 704x480 picture and a 9x9 picture ).
- I don't allow the use of every possible matrices, but the available matrices are enough, imho. I choose them that way because it allowed me to optimized a lot the calculations.
- In the next release, negative values will be supported ( thus allowing to calculate a gradient mask ). What prevents it for been activated in this release is the parser of string which doesn't take yet into account '-' ( it's a delimiter ).
- Don't put 0 in 'total', or you'll have a division by zero ( corrected in the next release also ).
- When processing U and V planes, the matrice have a larger influence, since pixels are bigger in these planes.

As usual, any bug report is welcomed.

Edit : The LUT filter will also come in the next release. I don't see a use for CombMask ( I'm not used to process interlaced sources ), so if somebody could enlight me on a use of such a mask. Finally, I intend also to implement other edge's detection ( to begin with the one in MSmooth, which I particulary appreciate ).

mf
14th January 2004, 12:13
Originally posted by Manao
I don't see a use for CombMask ( I'm not used to process interlaced sources ), so if somebody could enlight me on a use of such a mask.
scharfis_brain, me, and Mug Funky have made scripted deinterlacers. So far it's been kind of a mess making a comb mask, so something like that (preferably stolen from DGBob, afaik that one has a pretty good comb detection) would be very nice. I've been able to isolate combing (black and white lines against a virtually solid grey background), but I haven't been able to make that into a comb mask. Also, I'm interested if my isolated combing would be more efficient than applying a comb mask on a normal picture. I've PMed neuron2 about it, but it seems he really only visits here occasionally. Or he's just deleted my PM without even sending me a read reciept :D.

Manao
14th January 2004, 12:25
But I don't see how such a scripted filter could be better than Decomb. Anyway, I'll do it, it's not that hard to implement. You'll just have to wait a few days.

mf
14th January 2004, 13:29
Originally posted by Manao
But I don't see how such a scripted filter could be better than Decomb. Anyway, I'll do it, it's not that hard to implement. You'll just have to wait a few days.
If nobody thought they had better ideas than dropping one field and spline interpolating the other (which is what decomb does per default), we'd be stuck in the stone age forever, deinterlacing-wise. FunkyDeint, SSTomsMoComp, and other scripted deinterlacers are all valuable alternatives, usefulness varying per source and video type. I'd have thought of you to think a little more out of the box than "I don't see how it could be better than Decomb" :). Just to illustrate, my best idea for a line darkener (http://mf.onthanet.com/linedarkening) before I made mfToon was of the same type as fxToon, simply identifying lines and individually darkening them. Then I started thinking out of the box and used an unsharp mask to darken adjacent edges :). It was lying there all along (unsharp mask is one of the oldest sharpening techniques), I just didn't see it.

LB
15th January 2004, 19:01
First I want to say, thanks for the awesome filter! But, I have a question regarding the ones on: http://www.geocities.com/manao47/Filters/

I download any of the versions on there and look at the file itself and they all say version 1,4,0,0 so I want to make sure that they are indeed the right ones, but the version label has simply been left off the filename.

LB

Manao
16th January 2004, 23:07
New version : 1.4.8 :

Changelog :

1.4.8
- YV12Convolution now supports negative coefficients in the matrix. It allows to use the filter has an edge detecter.
- YV12Convolution has now a new parameter : bool saturate, which, if set to true, or if there is a possibility of getting out of the range [0..255] during calculation,
clips each pixel into that range ( which means it's slightly slower )
- A new filter : LUT. Read further for more information on how to use it.
- Versionning is back ( thanks for pointing me to that fact LB )

Now, the description of YV12LUT :

13) YV12LUT(clip clip, string Yexpr, string Uexpr, string Vexpr)
- Yexpr is a string containing a serie of numbers / function's names / operators / 'x', all separated by spaces. It represents the expression, in reverse polonese notation. It means that, for example, "(sin(x) * 3 + x^4) / 2" will become "x sin 3 * x 4 ^ + 2 /".
- One of its use can be a level filter like the one of avisynth : noting input_low : il, input_high ih, output_low ol, output_high oh, the formula given in the avisynth's documentation becomes :
"x il - ih il - / 1 gamma / ^ oh ol - * ol +"
- There is only one variable, which has to be 'x'.
- There are for the moment 8 functions implemented : sin, cos, tan, exp, log, acos, asin, atan. Say the ones you need, they'll be implemented
- There are 6 operators yet : +, -, *, /, ^, %

Next filter, CombMask.

Manao
17th January 2004, 01:54
I got some free time tonight, so a new version is up :

Changelog :
1.4.9
- New filter : CombMask. As usual, read further for more documentation

The new filter :

14) CombMask(clip clip, int thY1, int thY2)
- Produces a mask showing areas that are combed. The thresholds work as for the other filters : after calculating the combing value, if this one is under thY1, the pixel is set to 0, over thY2, it is set to 255, and inbetween, it is set to the combing value divided by 256.
- The combing value is (upper_pixel - pixel)*(lower_pixel - pixel). Thus, it is not normalized to the range 0..255, because if it was do, value would be close to 1 or 2, no more. That means you can use threshold higher than 255, even they should not be useful.
- Defaults are 20 and 20 ( thus making a binary mask )

No optimizations on this filter. I'm waiting in fact for you to tell me if the output is the one needed for deinterlacing filters.

mf
17th January 2004, 17:05
You didn't recycle anything existing for this?

Kurosu
17th January 2004, 17:33
Originally posted by Manao
The combing value is (upper_pixel - pixel)*(lower_pixel - pixel).
Oh my. I don't recall how Decomb works (but...), but you mean that pixels on diagonal edges will eventually be reported as combed due to their high values? Why not:
- check for each line evidence of combing (eventually whole frame combing)
- output (a(upper_pixel) - a(pixel))*(a(lower_pixel) - a(pixel)) where a() stands for average over 3 (or 5, or...) pixels? Sure it will lead to less sharp masks, but quite less over-sensitive ones...
?
Or maybe some kind of hysteresis*:
- do your calculus normally
- apply another weigh for the pixels whose neighbors also seem combed? (not nice, discontinuity problems in the mask may arise)

*in fact it could be an optionnal binarize setting/mask tweaker: increase the confidence whenever the neighborhood has a high ratio of good evidence.

Soon 1.5! (I'd have already changed version number due to new features (no more bugfixes) :D

mf
17th January 2004, 20:19
Brainstorm on IRC:

15:20 <@mf> http://mf.creations.nl/avs/isolatedcombs.png
15:21 <@Akirasuto> nice :)
15:21 <@mf> hey! i just had an idea
15:22 <@Akirasuto> ?
15:22 <@mf> edge tracing could reduce false matches!
15:23 <@Akirasuto> o-o
15:23 <@mf> sadly it's not something i can do ;/
15:23 <@mf> edge tracing really is something advanced that you need to code
15:25 <@Akirasuto> hmmm...
15:25 <@Akirasuto> why would edge tracing reduce false matches?
15:26 <@mf> look at kazuki's uncombed part
15:26 <@mf> to an algorithm, those edges might look like combing
15:27 <@Akirasuto> how about using your isolated combmask as a condition for field matching criteria?
15:27 <@mf> however, if you make something that follows the edges, and cancels out everything that's not a solid shape, you don't have to worry about kazuki's uncombed edges anymore, because they'd be canceled out
15:29 <@mf> in fact, changing the nature of the comb detector can already do that
15:29 <@mf> allow me to demonstrate
15:33 <@mf> http://mf.creations.nl/avs/isolatedcombs2.png
15:34 <@mf> to a comb detector, both left and right zoomed images are almost equal
15:34 <@Akirasuto> ah ha...
15:34 <@mf> the difference here is, that in the left (real combing), the brightness pattern (light dark light dark) is continuous
15:35 <@mf> in the right part (false combing) the brightness pattern follows the edge, meaning as the curve goes down the brighness pattern goes down too
15:36 <@mf> so you'd have to determine the pattern for a specific part that is detected as combing, and when the pattern isn't followed, the entire line is canceled out
15:38 <@mf> well, am i on to something or what ;D
15:39 * iluid watches mf's ideas fly over his head
15:40 <@Akirasuto> you're on to something that could be quite cpu intensive :d
15:41 <@mf> ha? why?
15:43 <@Akirasuto> nevermind, I was probably thinking of something else ^^;
15:43 <@mf> well of course it's not realtime
15:46 <@mf> what i have now runs at 12fps
15:49 <@mf> it's so nice to see it run
15:49 <@Akirasuto> :)
15:49 <@mf> it just goes *flicker* *flicker* whenever there's combing
15:50 <@mf> in that sense, you're right that it's good at detecting if a frame is combed
15:50 -!- mode/#ai-ls [+p] by Akirasuto
15:54 <@mf> and in another idea, an extreme field matching filter would also be nice
15:56 <@mf> a filter that is built upon the notion that your source SHOULD have been 100% progressive originally
15:56 <@mf> so whenever there's combing, it just tries extreme field matching until the combs are gone
15:56 <@mf> possibly even copying parts of the previous or next frame, if field matching isn't possible
15:57 <@Akirasuto> what happens if it's a orphan(sp?) field?
15:58 <@mf> it'd get replaced by parts of the previous frame (or the entire previous frame)
15:58 <@Akirasuto> then you'd lose motion, wouldn't you?
16:01 <@mf> of course
16:01 <@Akirasuto> okay :)
16:02 <@mf> but that's the whole idea of "built upon the notion that your source SHOULD have been 100% progressive originally"
16:02 <@mf> from that way of thinking, you cannot expect orphan frames
16:02 <@Akirasuto> indeed =)
16:03 <@Akirasuto> I guess what we can do is using the extreme field matching and override it for some of the odd balls
16:03 <@mf> sure
16:04 <@mf> if there's visible loss of motion somewhere, let 'em override it ;p
16:04 <@Akirasuto> XD
16:04 <@mf> if it's not visible, there's no harm done and the filter did its job well

So many ideas, so little time... :rolleyes:

sh0dan
4th February 2004, 14:43
Could I request Invert to be removed from the next version. I upgraded the internal one to support all colorspaces. Furthermore it also supports inverting individual components.

So having an YV12 only in MaskTools shouldn't be necessary.

bond
29th February 2004, 15:54
i think i found a bug in masktools edgemask implementation:

sample2 shows how normally a frame would look like
sample1 shows how every 15th (exactly) frame looks like:

samples (http://8ung.at/bond/bottomline-keyframe.zip)

i mean the "horizontal stripes-effect" seeable especially on the right in sample1

i tested different resize filters (namely lanczos, bilinear and simpleresize)
mpeg2dec3 and mpegdecoder
and the pic was trimmed and cropped

my edgemask settings were:
EdgeMask(2,2,255,255,"sobel",y=3,u=1,v=1)
from my testings it should also happen with different thresholds and strings


btw: also these frames show that on some frames the picture is not displayed in light vs. dark green but in black and white (i couldnt figure out when/why this change happened)


also it can be seen that no matter how i crop, there is always a small line detected as edge on the bottom

Manao
29th February 2004, 16:39
sh0dan : the new version ( which I didn't advertize, it was a minor bugfix ) doesn't have Invert anymore.

bond : I can already explain the black & white / dark & light green : when you set y, u or v to 1, there are no allocation of the color / luma plane, so you can end up with anything. That should not frighten you however, since specifying y, u or v = 1 means you don't care about that particular color / luma plane.

Thinking about it, do you know that every 15 frames, in an mpeg2 stream, you have a keyframe ?

I'll try to solve the first & last line bug, but that part of code is ugly ( especially in MMX ). Meanwhile, I advise you to try msmooth to create a mask, that's still my favorite edge mask creator.

bond
29th February 2004, 16:45
Originally posted by Manao
Thinking about it, do you know that every 15 frames, in an mpeg2 stream, you have a keyframe ?no :D
but its always good to learn something new ;)

I'll try to solve the first & last line bug, but that part of code is ugly ( especially in MMX ):)

Manao
29th February 2004, 17:49
OK, new version, 1.4.11, only bugfixes : http://www.geocities.com/manao47/Filters/masktools-v1.4.11.zip

Changelog :

1.4.11
- Bugfix : EdgeMask, MMX optimizations give different results. They are disabled by default. To activate them, use usemmx = true. They'll be used only with mod 16 resolution
- Bugfix : EdgeMask : first and last lines weren't always computed.
- Bugfix : MaskedMerge : MMX optimizations darken slightly the picture. They are disabled by default. To activate them, use usemmx = true. They'll be used only with mod 8 resolution.
1.4.10
- Bugfix : first and last lines were not correctly computed with inflate / deflate
- Invert is no longer a filter of the Masktools, it has been moved inside AviSynth.

Thanks bond for reporting the bug on EdgeMask.


I let MMX optimizations switchable, because they speed up the process a lot. For most of the masks, differences between C and MMX version are small, so you can use usemmx = true. For MaskedMerge however, the difference is annoying, since it darkens the result. So it's up to you ( you can't see the difference without interleave original and merged clip )

Chainmax
29th February 2004, 18:29
The two DLLs on the zip report as being v1.4.0.0 and 1.4.9.0 :confused:.

bond
29th February 2004, 19:09
Originally posted by Chainmax
The two DLLs on the zip report as being v1.4.0.0 and 1.4.9.0 :confused:. yep the included versions are not the latest, as with inflate the first/last lines are not computed correctly (altough they should according to manaos changelog)

Manao
1st March 2004, 00:49
There are two dll, the wrong one is the one in the 'Sources' directory. I always forget to delete it before releasing.

But I checked the other one, and inflate / expand work correctly, even on the first / last rows.

Edit :

I uploaded a version with only 1 dll, and which reports the correct file version.

bond
1st March 2004, 13:12
Originally posted by Manao
But I checked the other one, and inflate / expand work correctly, even on the first / last rowshm than maybe the failure (?) is not caused by inflate()

have a look at the first row in this sample (http://8ung.at/bond/firstrow.zip) and how it is processed

i used the latest masktool compile

Didée
1st March 2004, 15:44
Manao:

May I ask, with low voice and very carefully ;) , if it would be possible to include an additional kernel for the EdgeMask function?

In the meantime, there are so much different possibilities to create EdgeMasks, but I am still using the old and slow method of GeneralConvolution :( for certain reasons:

What I often need for my scripts, are accurate EdgeMasks, as well in the placement of the borders, as in the strength (lightness) of the returned border in respect to the "feature strength" in the original frame.

Now, all other available methods fail in one or another respect:

- Msmooth/Msharpen create only binary masks - not at all suited for me.

- When using your vector-oriented approach of YV12convolution as an edge detector , I can only get something like

__0__1__0
__1_-4__1
__0__1__0

(for example) out of it. This generally works, of course, but I'd really prefer to have the diagonal neighbors included also, as this makes the detection much more exact, especially on certain kinds of image features.

- EdgeMask (Roberts) is not pixel-centered (2*2 kernel).

- EdgeMask (Sobel) has the same limitation as YV12convolution of not including the diagonal neighbors.

- EdgeMask (hq), as mentioned in the readme, would be much better. Alas, it's not implemented ... ;)


So, what I would like so much to see, is (in ascending order of possible exitement):

1. Implemention of Laplacian kernel

2. Implementation of a kernel with more correct weighting of pixel distance, like for example

_-2_-3_-2____or____-4_-7_-4
_-3_20_-3____or____-7_44_-7
_-2_-3_-2____or____-4_-7_-4 , or similar.


3. (Dreaming) Sort of an "double-edge-detector":

With "normal" edge detection by convolution, one will always end up with an edge mask that covers the lighter part of an edge only. Therefore, to get an edge mask that exactly covers the complete edge, I usually do something like:

Overlay( MakeMask(source), MakeMask(source.invert), "lighten")

(in shortened notation), to actually get both sides of the edges.


If anything of the above could be implemented, it would make things so much easier for me ...
... and my scripts much faster ;)

Or did I fail to see an existing, obvious solution?

Thanks for listening

- Didée

Manao
1st March 2004, 17:54
bond : can you give me the avisynth script ? Because I have no problem on my computer with that binary. Something is strange however in your picture. It seems somehow that the chroma is not aligned, meaning chroma pixels which should be at even coordinates seems to be placed at odd coordinates.

Edit :

Didée : Yes, yes and (perhaps) no. First two can be done, but they be slower than previous filter. In YV12Convolution, I only allowed matrices being the produce of two vectors in order to speed up the process, but I can make another version where you give the whole matrix. That should answer to 1 & 2.

For 3, you may be wrong. I looked quickly into the source code ( it's the part written by Kurosu, I don't know it well ), and he uses an absolute value during computation ( at least for sobel, but not for all the filters ), so you should have all the edges.

Else, you could also try something like :

Subtract(source.expand(), source.inpand()),

And use YV12LUT after that, in order to obtain a real edge mask ( for example, YV12LUT(Yexpr = "x 128 - abs 2 *") or something like that.

bond
1st March 2004, 18:04
how do you see that chroma pixel stuff?
edit: if you mean the red areas misplaced on the chair... thats the ghosting effect of moving objects we discussed before!

again my coloring/testing script

LoadPlugin("C:\...\mpegdecoder.dll")
LoadPlugin("C:\...\MaskTools.dll")
LoadPlugin("C:\...\SimpleResizeYV12.dll")

mpegsource("C:\...\movie.d2v")
trim(136757,145073)
crop(2,82,716,416)
HybridFupp(640,256,255)

function HybridFupp(clip input, int width, int height, int "sharpness")

{
resizemask = input.edgemask(2,2,255,255,"sobel",y=3,u=1,v=1).inflate().SimpleResize(width, height).greyscale().ConvertToRGB32()
MoMask = input.motionmask(25,25,255,255,22,y=3,u=1,v=1).inflate().SimpleResize(width,height).greyscale().converttorgb32()

soft = input.SimpleResize(width, height).ConvertToRGB32().RGBAdjust(1, 1, 5, 1)
MEdgesharp = Mask(input.SimpleResize(width, height).ConvertToRGB32().RGBAdjust(1, 5, 1, 1), resizemask)
MMotionblur = Mask(input.SimpleResize(width, height).ConvertToRGB32().RGBAdjust(5, 1, 1, 1), MoMask)

Addedgedsharp = Layer(soft, MEdgesharp, "add", sharpness)
AddMotionblur = Layer(Addedgedsharp , MMotionblur, "add", 255)
return AddMotionblur

}

Manao
1st March 2004, 18:23
There was no chroma shifting finally, it was just that it seemed to me color was displaced, but no, it wasn't that. I found the issue, but, there again, it was a choice made inside the edges / motion detectors not to take into account the border pixels. I'll correct it, but it will take some time for the edge' detectors ( 5 of them (!) ).

However, expect soon ( meaning 2 - 3 hours ) a release with MotionMask corrected, and with a slight bug in inflate/ expand / inpand / deflate which I found just on the moment ( thanks bond for your reports, because it made me make a lot of tests which allowed the triggering of very unexpected bugs ;) )

bond
1st March 2004, 18:28
Originally posted by Manao
thanks bond for your reports, because it made me make a lot of tests which allowed the triggering of very unexpected bugs:)

Manao
1st March 2004, 20:23
New version, http://www.geocities.com/manao47/Filters/masktools-v1.4.12.zip

Changelog :

1.4.12
- Behavior modifications : MotionMask and EdgeMask now also computes pixels on the borders
mainly by extending the mask to these pixels.
- Bugfix : Inflate / Inpand / Expand / Deflate, when using negative parameters for y,u and v,
some weird problems could occur.
- Added functionnality : In YV12LUT, the function abs is now defined.

Next version should include Didee's propositions, but I'm also working on something else, so you'll have to wait a little.

Manao
2nd March 2004, 17:30
New version ( FuPP found yet another bug this morning ) : http://www.geocities.com/manao47/Filters/masktools-v1.4.13.zip . I also added another filter.

Changelog :
1.4.13
- Bugfix : One more, in the MotionMask ( the last row was not correctly computed )
- Optimizations : MaskedMerge gives now the same output in MMX and C, so MMX optimizations for it are back by default.
- Added : In EdgeMask, you now can use the laplace kernel. See the documentation on that filter
- Added : 'New' filter, DEdgeMask, which allows you to choose your kernel ( at a cost : slight speed drop )

SoonUDie
3rd March 2004, 13:18
YV12Layer() seems to be broken.

No matter what I do, it always reports the "Image formats don't match" error.

Even when I do something like this:

YV12Layer(a.ConvertToYV12(), b.ConvertToYV12() ... etc. )

It still gives me the error. All the clip properties are identical.

Didée
3rd March 2004, 15:58
Cannot reproduce that: works correctly for me.

Manao: a big thank-you !!

- Didée

/* walks away in a blissful mood, one arm wrapped around the new MaskTools, the other around the freshly bugfixed AviSynth */

mf
3rd March 2004, 16:39
Originally posted by SoonUDie
YV12Layer() seems to be broken.

No matter what I do, it always reports the "Image formats don't match" error.

Even when I do something like this:

YV12Layer(a.ConvertToYV12(), b.ConvertToYV12() ... etc. )

It still gives me the error. All the clip properties are identical.
Same here. I used MaskedMerge instead ;).

Manao
3rd March 2004, 17:12
mf and SoonUDie, could you give me an avs script which shows the problem. Can't reproduce it on my computer.

However, looking into the source code, there's a check made here that differs from other filters. It tests whether the pixel_type are the same. They should be except if you're loading two different clips. Is it the case ?

sh0dan
3rd March 2004, 17:35
Replace:
if (vi1.pixel_type != vi2.pixel_type)
env->ThrowError("YV12Layer: image formats don't match");

with
if (!vi1.IsSameColorspace(vi2))
env->ThrowError("YV12Layer: image formats don't match");

I420 is not same pixel_type, but is transparently delivered as YV12.

Manao
3rd March 2004, 18:18
Yes that's what I thought, but since it is not my code, and since the next line tests whether both are YV12 or I420 :if (!vi1.IsYV12() || !vi2.IsYV12())
env->ThrowError("YV12Layer: only YV12 formats");I assumed that the pixel_type's test was needed for the filter to work. I corrected that and did a silent update : http://www.geocities.com/manao47/Filters/masktools-v1.4.13.1.zip

Thanks sh0dan !

SoonUDie
4th March 2004, 02:31
Thanks, it seems to be working now!

SoonUDie
7th March 2004, 17:58
Thanks for the work on this great filter, but I've noticed what I think are a few more problems:

1. The documentation isn't current in some cases... the most obvious is edgeMask. EdgeMask requires 4 thresholds but only 2 are listed. It took me quite a while to figure out what was wrong, as I kept getting an "Invalid arguments" error for what seemed to me to be no reason.

2. DEdgeMask really needs a user-settable divisor setting. In its standard form, it's somewhat useless as an edge detector. For example, the default matrix (laplace) ends up producing a mask with NO LUMA VALUES.

can you replicate these problems?

Manao
7th March 2004, 19:20
1. I'll correct the documentation ( and when I'll have some more time, make an html documentation )

2. For DEdgeMask, the divisor has the proper value. However, I just looked at the source code, and I forgot that while testing, I had made some modifications which I forgot to correct. So luma and chroma threshold aren't used for the moment :rolleyes: .

Well, it's corrected, thanks for reporting that to me. You can fetch it here (http://www.geocities.com/manao47/Filters/masktools-v1.4.14.zip)

Changelog :

1.4.14
- Bugfix : In YV12Layer, a useless test could prevent the filter to work. The test has been removed
- Bugfix : In DEdgeMask, threshold weren't taken into account. They are now
- Bugfix : Logic filter is now fully functionnal, in C and MMX
- Added : documentation to Logic filter
- Added : two modes for Logic : "Min" and "Max" ( C, MMX, iSSE )
- Added : In DEdgeMask, the possibility to set the normalization factor
- Corrected : documentation.

Edit : Could the warpenterprise plugin page be updated to the latest masktools ? Currently, a lot of people are making scripts usable by others, but which requires a version of the masktools up to date.

SoonUDie
8th March 2004, 04:03
Awesome, it works great now! Also, the new divisor option is *really* helpful. Thanks :D

Didée
11th March 2004, 16:39
Although a little late: Many thanks for the new version, Manao!

The edge detection is really good now, since we can specify the normalization.
Going to head over to 'logic' now, and see what can be done there.

But, I found a problem - either with MaskTools, or with me ;)

For me, the YV12LUT command is often producing strange results:

- e.g. when applying the example you gave for adjusten Y levels only, then:
strange results if I either use YV12LUT several times in a script, or when specifying certain values.

- as soon as I use "abs" within YV12LUT, the returned clip is simply black. This is a big pity, since " YV12LUT(Yexpr="x 128 - abs 2 *") " would be a *godsend* to turn the results of difference/subtract operations into some usable masks, instead of having to use the slow overlay(clp,clp.invert,"lighten") method for that.

- Didée

Manao
11th March 2004, 17:17
That is strange. ABS works fine for me. And several instanciations also. Could you give a script sample which shows the issue ?

And when you say that some value gives errors, can you says which ones. I found that negative values are an issue ( they are understood as an operator, I'll correct it ASAP ). Are there any other problematic values ?

Manao
12th March 2004, 11:22
Alright, a bugfix for the 'minus' issue in YV12LUT :

http://www.geocities.com/manao47/Filters/masktools-v1.4.14.1.zip

However, I didn't find any other bugs or issues, so Didée, could you develop a little your issues with YV12LUT, so I'll be able to reproduce them ?

Didée
12th March 2004, 11:28
Oops, didn't see Manao was posting at the same time. Testing new version ...


Hmh. Don't know what's going on here, but I get even more :confused: :

Last days, I got said unpredictable results. I was on my Athlon Xp1800 then.
Today, I'm at another place, working on a recent Celeron machine. Here, I get nothing useful at all out of YV12LUT.

Mpeg2source("source.d2v")

looks fine, big surprise. When I add

YV12LUT() or YV12LUT(Yexpr="x")

it still looks fine, so the default no-op seems OK.
But, when I instead add

YV12LUT(Yexpr="x 2 *") [or YV12LUT(Yexpr="x .5 /")]

then the returned clip has ZERO luma on all pixels.

Specifying

YV12LUT(Yexpr="x 66 +")

returns a clip where all pixels have Y=66 ...


Am I doing some braindead mistake? To me it looks as if "x" is not evaluated correctly, or not at all if I do any math operations on "x". Everything that involves "x" in the computation is returned as ZERO; constants not related to "x" are working as expected - but that doesn't help if I can't get "x" into the formula ;)

[...testing something...]

Oh, and "Uexpr" & "Vexpr" for me don't do any change to the clip: whatever formula I specify, I get back exactly the original U & V values.

For the moment, I have really no idea.

- Didée



No, alas YV12LUT in v1.4.14.1 also doesnt't work, at least not on this machine here.
However: Yexpr="x 123 - abs" returns "correctly" (of course incorrectly) a clip with constant Y=123, so the minus bug seems indeed fixed ;)

Manao
12th March 2004, 12:03
The 'minus' bug was only for negative numbers ( -123 for example ), which were considered as the operator - ).

I can explain the U & V thing : YV12LUT behaves like all other filters in the MaskTools, and by default, U & V aren't processed, even if you specify Uexpr and Vexpr. So, you have to set U = 3 and V = 3 in order to process these planes.

Now, for the real issue. That is definitely strange. It seems indeed that the 'x' symbol is always equal to zero. Which can't be, except if it is not recognized as an 'x'.

The samples you gave work on my computer. So I'm rather lost. However, I do see a slight possibility : to test whether the symbol is an x or not, I only test the equality between the first character of the symbol, and the character 'x'. That means that the symbol has to be 'x', not 'X', and it may mean also that the string has not to be given in UTF-8. However, I can't see how such a thing could happen.

So I launch a call to other who may test the problem here : copy & paste the example : YV12LUT(Yexpr = "x 2 *") and tell me if it gives you a black clip or the clip with luma multiply by 2.

Mug Funky
12th March 2004, 13:32
hmm... by the look of things the next release will be Masktools v root 2

Manao
12th March 2004, 13:57
Looool :)

Mug Funky
12th March 2004, 15:29
(that's probably the most geeky thing i've ever said)

hmm... YV12LUT(Yexpr = "x 2 *") gives a clip with luma*2 as expected.

i was wondering if there were docs around for this stuff? i've figured how to use a couple of the functions by reading through the source, but obviously that's tough going. (note: i didn't search very hard, but i did search)

[edit]

it seems there's a minor bug in either YV12convolution or my computer...

instead of throwing "YV12Convolution: Vector's length have to be odd" it simply crashes virtualdub.

Manao
12th March 2004, 17:26
Mug funky : there is a MaskTools.txt which explains each function. For YV12Convolution, I can't reproduce the bug. Did VDub or Windows give you an error message while crashing ?

Manao
12th March 2004, 21:37
Alright, I have more data on the issue you're encountering, Didée.

While testing something with YV12Subtract, I observed the behavior you were describing for YV12LUT. It seems in fact totally related to the filter preceding YV12LUT. I'm currently listing all the problematic filters, and I found for the moment YV12Subtract and MotionMask for the masktools, I don't know for the other filters outside the MaskTools ( I tried some of them, they were all working ). Now, I'll try to find why this is happening.

Stay tuned

Manao
18th March 2004, 01:38
New release : fetch it here (http://www.geocities.com/manao47/Filters/masktools-v1.4.15.zip)

Changelog :

1.4.15

- New Filter : HysteresyMask. It will allow you to build a new edge mask from two edge masks, one only having a few edges ( but we're sure they indeed are edges ), the other having two much edges ( due to a too low thresholding for example ). Look in the documentation to have further explanations.

1.4.14.2

- Several bugfixes concerning the behavior of negative values for Y, U and V ( edgemask, dedgemask, motionmask, combmask, logic )
- Several bugfixes concerning the use of offX / offY / w and h ( filters than can use it are : maskedmerge, binarize, expand, YV12subtract, yv12lut )
- In YV12LUT, a bug prevented to use it with some filter. It should work now.
- In YV12Convolution, float coefficients can be used now. If none is used, all the processing will take place with integer, so it will be faster than if you use a float. Moreover, if there is the possibility of overflow ( giving a result over 255 or under 0 ) during computation, a slower but safe function will be used to saturate computation to 0 and 255.

1.4.14.1

- Bugfix in YV12LUT to allow the use of negative numbers

-------------------------

Description of the new filter :

15) HysteresyMask(clip clip1, clip clip2)
- clip1 will be a binary edge mask, build with a higher thresholding than clip2. In that case, HysteresyMask will expand the connex set of the clip1 into those of the second clip. It's easier to understand with an example, which you'll get here :

http://www.geocities.com/manao47/Filters/Documentation/hysteresy.html

These examples were created with the following script : source = MPEG2Source("R:\foo.d2v")
mask1 = source.edgemask(y=3,u=0,v=0,thY1 = 10, thY2 = 10, type = "sobel")
mask2 = source.edgemask(y=3,u=0,v=0,thY1 = 20, thY2 = 20, type = "sobel")
return HysteresyMask(mask2,mask1,y=3,u=0,v=0)The first picture corresponds to mask1, the second to mask2, the third to the result of HysteresyMask

bond
18th March 2004, 09:21
looks great!

thanks a lot manao :)

Manao
21st March 2004, 19:10
I forgot to add something to the changelog : I added a parameter to YV12Subtract, its documentation is now :

6) YV12Subtract(clip clip1, clip clip2, int tolerance,
int offX, int offX, int w, int h, bool widerange)
(works in-place, mode=2 will copy the plane of clip2 to clip1)
Performs almost exactly the same as Subtract, but uses MMX.
- If widerange is set to false ( default ), the behavior will be the following :
if mode<0:
if clip1 < clip2, output = 128 + clip1 - clip2
else output = clip1 - clip2
else
output' = |clip2 - clip1| - tol
if output'<0, output = output'
else output = output'
- You can remark that overflow is possible, which leads to the dot issue.
To correct that, use the parameter widerange = true. The tolerance is then
used in a different way : the filter will return

128 + ((clip1 - clip2) / 256)^(1/tolerance) * 128.

Thus, no overflow. The tolerance act as a gamma parameter, which can come in handy.

LB
14th April 2004, 03:26
Hey, thanks for the great release! I just wanted to mention that v15 has the wrong version # in it's properties log - it says 14 instead of 15.

Manao
14th April 2004, 15:21
New version up : http://www.geocities.com/manao47/Filters/masktools-v1.4.15.2.zip

Changelog :

1.4.15.2
- Bug finally solved on YV12LUT. Silly programming bug, as always...
- In YV12LUT, logical and relationnal operators added ( <, <=, >, >=, ==, !=, &, !&, |, ° ( xor ) )
- In YV12LUT, a ternary operator added ( ? ) : works as in C

If those who were experiencing problems with YV12LUT ( Didée ? ) could check, I really hope that the bug is gone this time.

For the relationnal, logical and ternary operators, it can be used for making mask, for applying gamma correction differently for pixels under 128 and over 128 ( as it was asked, once ), and so on.

Oh, and I forgot : version number is corrected ( I forget it half the time :) )

Didée
14th April 2004, 15:44
Manao,

will test this new version ASAP, and report especially about YV12LUT.

And so promising new things to play with, wohoo! W00t!

For sure you've deserved a crate of beer ;)


- Didée


edit

Had only very limited time for testing, but it seems YV12LUT is really okay now. Two usual script sniplets that never ever before had worked correctly, do it now.

Big cigar :cool:, Manao!

Hmmh, and to make use of the nice new operators, one could feed some FrameEvaluate()'ed variables into it ... ;)

scharfis_brain
15th April 2004, 12:05
small, stupid question:

is YV12Lut the same like the Curves-Function of Photoshop or the Virtualdub Curves-Filter by Bugsbunny?

If yes, would it be possible to import Photoshop's AMP-Files to YV12Lut?

Manao
15th April 2004, 12:31
I never worked with photoshop. However, if you could post samples of such AMP-files, I could look into it.

scharfis_brain
15th April 2004, 12:49
example curves: http://members.chello.at/nagiller/VDub/curves.html

the VDub-curves-filter: http://members.chello.at/nagiller/VDub/index.html

LigH
15th April 2004, 12:52
@ Manao:

Direct links to GeoCities downloads often does not work (referrer leech block).

Workaround: First visit the site http://www.geocities.com/manao47/Filters/ -- then select the file there.

mf
15th April 2004, 13:06
Originally posted by LigH
@ Manao:

Direct links to GeoCities downloads often does not work (referrer leech block).

Workaround: First visit the site http://www.geocities.com/manao47/Filters/ -- then select the file there.
We know, he knows :). Instructions are to rightclick, copy shortcut, open new window, paste it into address bar.

Manao
15th April 2004, 13:18
LigH : right clicking, copying link and pasting it into your navigation bar should always allow you to download the file.

scharfis_brain : YV12LUT works only in YUV colorspaces, so it won't be usable easily. AMP file are a closed format I guess, I wasn't able to find documentation on the net. However, I seems relatively easy to reverse engineer it ( at least I hope ), but even if I suceed, I'll only get LUT for RGB channels, so I'll have to make a conversion into RGB, and then back to YUV.

I could write a RGBLUT if you want, it wouldn't take too much time. Then I could see if I'm able to understand AMP files ( it seems they are basically raw LUTs for RGB and possibly A channels )

scharfis_brain
15th April 2004, 13:33
this would be great!
but instead of doing an RGBLut (do this, too if you want), couldn't you just convert the RGB-Lut into a YUV-one?

Manao
15th April 2004, 13:42
scharfis_brain : it would require a huge LUT ( 48 MB ), but it could be done. I'll look into it.

scharfis_brain
15th April 2004, 13:51
why that?

is is THAT hard to convert the three LUTs (R, G and B) to three other LUTs (Y, U and V)?

sorry I am a novice tho chromaspaces, I am just able to handle them problerly...

Didée
15th April 2004, 13:58
[kidding on]

Hey - and I want to import my PictureWindow *.crv files!!

[kidding off]

( I guess hardly anybody is aware of PictureWindow. I suggest to visit Digital Light & Color (http://www.dl-c.com), and check the evaluation version. Seldom I have seen a proggy that is worth its money so much! - with PW, I usually have all my work already done just by the time Photoshop would finally have finished initializing itself :D )


Scharfi:

Head over to WarpEnterprises, and look for "adjust.dll". With it, you can define your own graduation curves very simply by manually specifying control points, and so on.
Only drawback: it's YUY2 only :(


- Didée

sh0dan
15th April 2004, 14:11
Originally posted by Manao
scharfis_brain : it would require a huge LUT ( 48 MB ), but it could be done. I'll look into it.
Just about anything is better than a 48Meg lookup table. It will be dog-slow. Any per pixel LUT larger than your cache size is sure to kill your CPU. It will almost certainly be faster to do a proper colorspace conversion.

(And we are not even talking multiple filter instances)

Manao
15th April 2004, 14:11
It's not hard, but what photoshop does when using a color modification table, is basically to apply three functions Fr, Fg, and Fb to each channel of each pixels, meaning that a pixel with R=r, G=g and B=b will become R=Fr(r), G=Fg(g) and B=Fb(b).

Now, when you go into YUV colorspace, you make a multiplication between a matrix and the vector (r,g,b) which gets you a vector (y,u,v). To come back, you do the same with another matrix.

To apply the AMP file, having YUV as input, you should first multiply (y,u,v) by a matrix, apply Fr, Fg, and Fb, and then come back to YUV.

During that process, you're interlinking y, u and v values, because, so you have to precompute the result obtained by that process for each threesome. They are 256*256*256 = 16 millions of such threesomes, and each one gives you a 24 bits value, meaning 48 MB.

The process is simple, but precomputation costs are heavy.

Edit : I just saw sh0dan answer, he is right, so I'll make RGBLUT instead.

Manao
15th April 2004, 15:30
Done :

http://www.geocities.com/manao47/Filters/masktools-v1.4.15.3.zip

Changelog :

1.4.15.3
- RGBLUT added : works the same as YV12LUT ( except R, G and B replace Y, U and V ). In addition, you can specify an AMP file ( arbitrary color mapping file format from photoshop ).

So basically, to load & apply an ampfile, use : RGBLUT(ampfile = "ampfile.amp")

scharfis_brain
20th April 2004, 00:27
motionmask() seems to be buggy.

a simple script like this:

avisource("30p.avi")
converttoyv12()
motionmask()

delivers a video, which is only partially masked.

meaning some frames contain a mask, others only a blank mask :(
this is making it completely useless.

scharfis_brain
20th April 2004, 01:28
whoops, the thsd-paramters default seems to be too low!
I've raised it to 255.
This delivers a motionmask all the time :)

mf
20th April 2004, 12:43
Originally posted by scharfis_brain
motionmask()
delivers a video, which is only partially masked.
meaning some frames contain a mask, others only a blank mask :(
this is making it completely useless.
My suggestion: try MotionMask(thY1=0, thY2=255, y=3,u=1,v=1) and then manipulate that mask to your liking.

Manao
23rd April 2004, 16:51
Yet another bugs found : new version up : 1.4.16 (http://www.geocities.com/manao47/Filters/masktools-v1.4.16.zip)Changelog :
1.4.16
- Bugfixes : Logic "min" & "max" modes weren't properly working, it's corrected.
- Bugfixes : Logic & Subtract weren't using MMX & iSSE optimizations, due to a very silly bug. It's Corrected.

--------

Now, a remark for all those who use Overlay. You have to be aware that it makes a conversion to YUY2, which takes some time. And often, a filter of the masktools is able to do the same operation, if no mask is used.

For example :
- Overlay("lighten") = Logic("Max")
- Overlay("darken") = Logic("Min")
- Overlay("difference") = YV12Subtract(y=3,u=3,v=3)
- Overlay("blend") = MaskedMerge(y=3,u=3,v=3)

The masktools' filters will avoid the conversion in YUY2, will treat less pixels ( half less ), will be able to treat only luma or chroma if wanted, and may also have MMX / iSSE optimizations.

Another remark : since YV12LUT is able to understand if then else statements, it is powerful. For exemple, the following code ( taken in sharfis_brain's intellibob ) :hy=z.levels(0,1,127,0,255)
jy=z.levels(128,1,255,255,0)
sy=overlay(hy,jy,opacity=0.5)Can be replaced by :sy = z.YV12LUT(Yexpr = "x 128 < x 128 + 383 x - ?",y=3,u=1,v=1)(They differs only from coring issues in Levels, which should have been set to false in this case )

dandragonrage
23rd April 2004, 23:22
From what I can tell, either combmask or maskedmerge has a problem (memory leak?). Without them, I get a constant ~10FPS. With them, it's like 4FPS..3FPS..4FPS..3FPS..2FPS..3FPS..2FPS..1FPS..2FPS..1FPS..0FPS..1FPS..0FPS..0FPS..1FPS..etc. It just keeps getting slower and slower.

My available memory keeps going lower too, but that may just be Vdub buffering or something similar. Either way, I don't have any problems w/o combmask+maskedmerge.


blur1 = in.Unfilter(-60,-250)
mask1 = in.combmask(5,10).blur(1.58).blur(1.58).Blur(1.58).Greyscale().Levels(0,2,200,0,255)
maskedblur = in.MaskedMerge(blur1,mask1,Y=3,U=3,V=3)


nm this paragraph


Edit to add: I am using 1.4.16. Vdubs estimated total time keeps going up too. It was at 12 hours like 20-30 mins ago, now it's past 16. If it keeps going like this, the file will never finish!

Manao
24th April 2004, 05:31
dandragonrage : there is no memory leak ( no allocation done inside both filters ). I tried the script you gave me, and after 5 minutes, there was nothing wrong with either speed or memory consuption. I run the script through VDub, but without compressing, and I got a steady 20 fps.

Would it be possible that something else creating your issue ?

dandragonrage
24th April 2004, 05:44
Well, it doesn't go down like that when I don't use combmask. Though it JUST started dropping straight to 0FPS after about 10 minutes and coming back up maybe 10 minutes later on a script that has always worked fine before. I didn't add any plugins or anything.....

I'm playing with it now..

AVISynth is always giving me problems...First was eDeen, now something else, don't know yet...


Hmm....Only thing I've changed is installing DivX because I was using XviD but it was giving me corruption on some spots on like DivX 5.02 files. I installed DivX 5.1.1. Could that somehow have something to do with my problems?

Mug Funky
14th July 2004, 07:28
yo, manao: this isn't totally related, but how do you get the AMP files out of photoshop? i'm using v7 right now.

is it the same as "alv" or the files used in "curves"?

Manao
14th July 2004, 07:39
I don't have photoshop, so I don't know. Scharfi made available some amp files, so I guess he knows how to output them.

RGBLUT will work with any binary file that stores the curves in the R G B order, using 256 bytes for each of them, so if you can't output amp files, and if the size of the alv files is 256*3, you can try the alv files, who knows, it might work.

scharfis_brain
14th July 2004, 10:24
in photoshops curves filter you need switching the mode, that creates the curve

- make the curve of your choice using the spline - tool
- switch to the pencil (it disables spline)
- save the curve

BBugsBunny
15th July 2004, 17:52
The Adobe File Format specification can be found here:
http://www.fine-view.com/jp/lab/doc/ps6ffspecsv2.pdf

An amp file can generally contain 1, 3, 4 or 5 curves.
If there is one -> rgb(grey) values
3: R, G, B values
4: RGB and R, G, B values
5: If you're in the CMYK colorspace and save a amp

Nince to see that a avisynth filter can now process amp files as well.
Perhaps now in summer I finally get a "by mouse filter draw function" to work, so one does not need PS any more.
Also I'm thinking to implement a YUV colorspace, so these YUV amp files could later be also imported into thos avisynth filter...

So little people seem to know how to get a mouse support in vdf filters - only phaeron gave me some input.

Didée
19th July 2004, 00:03
This is an IMO interesting proposal:

When using YV12LUT on a frame, it would be cool to have ... a control clip:

TwoFrameLUT( input_clip, control_clip, Yexpr = "[f(x,y)]", Uexpr= ... )

or similar, where "x" is a pixel's plane value from input_clip, and "y" from control_clip.

YV12LUT is such a useful transform operation, but often I'd wish to have more steering possibilities *what* it shall do. The possibility of having a "control clip" (speak: a mask clip that contains some sort of metrics information found by other operations) which information then can be used by, more or less, free formulas through the LUT command, would be extremely valuable.

Many things can only be done with cumbersome intermediate operations, intermediate clips, logics and differences, but this is slow, comes with precision loss, eats memory, and ... would not be necessary.
And some other things simply can't be done at all.

So, having something like "TwoFrameLUT()" would probably avoid many other "feature requests" ... :D

(The first script for it is almost ready ;) )


Thoughts?


- Didée

Manao
19th July 2004, 20:09
New version : MaskTools v1.5.1 (http://jourdan.madism.org/~manao/MaskTools-v1.5.1.zip) Changelog :
* complete rewritting of the documentation ( a huge thanks to Wilbert )
* DEdgeMask now supports a float divisor. However, if the divisor is integer, it *should* be faster.
* DEdgeMask now has back its parameter "setdivisor", but it's only for backward compatibility with some scripts.
* YV12LUTxy : it's a new filter, implementing the idea presented by Didee on the previous post. The "y" symbol has the value of the collocated pixel in the second clip.

malkion
19th July 2004, 22:33
Thanks Manao!

Didée
20th July 2004, 12:09
Don't know how to put my exitement in words. Thank you, Manao.

And Wilbert as well - the new documentation is so much easier to follow than the old *.txt file ... maybe more people will discover the power of the MaskTools now.

Also thanks for making MaskTools accept "setdivisor" again. This will avoid problems with other, older scripts.


Just to give a (faint glance of an) idea of the power of the new yv12LUTxy:

An often arising operation is the following:

- We have two masks: mask1 and mask2

- We want:
--- use mask1 where it is *brighter* than mask2.
--- where mask1 is *darker*, we want to do *nothing* (black)


Shootout: What would be the shortest/fastest operation sequence with the former toolset?

Something like: yv12subtract(mask1,mask2).binarize.logic("darken") :rolleyes:

Three operations for a simple task... takes "much" time, at least in complex scripts.
Now with yv12LUTxy, it is

mask1.yv12LUTxy(mask2, Yexpr="x y > x 0 ?")

Only one operation :) - and since it's a LUT, it is as fast as can only be :) :)


But, this example is almost trivial. The tip of an iceberg.

What now becomes possible, is some sort of "parametric" operations, if I can say so. Anyone ever was in need of getting the proportion between the pixel values of two masks? - A real brainckracker I couldn't solve up to now.

But now with yv12LUTxy, it is simply ... x/y ... :D


Okay, enough singing of Hosianna for now.

Just thanks


- Didée



P.S. Let me a day or two for cleaning-it-up, Manao. You'll get it then.

Manao
22nd July 2004, 17:58
Silent update : a silly bug found by Didee & krieger ( http://forum.doom9.org/showthread.php?s=&postid=527138#post527138 )

Now, setdivisor should work as previously.

geoffwa
26th July 2004, 16:55
There's already a function in Avisynth called Invert() for swapping (RGB-only) color-channels.

Manao
26th July 2004, 18:44
Huh ? Could you develop a little more your idea ? Invert in Avisynth is working in RGB / YUV / YV12 ( avisynth 2.55 ), so there is no need anymore for it to be in the masktools.

malkion
26th July 2004, 22:57
Manao, I dont get the fitplanes function.

what is the equivalent syntax for YToUV (clipU, clipV [, clipY])?

it says FitPlane (clip, string resizer). Thanks.

Manao
26th July 2004, 23:06
These functions were made by Kurosu, I never looked into it. But as far as i can tell, resizer is one of the following string : "bilinear", "bicubic", "lanczos", "reduceby2" or "point".

Now, the filter FitY2U, FitY2UV, FitY2V, FitU2Y, FitV2Y. They'll leave intact the first channel ( before the '2' ) and copy it into the channels after the '2'. Since in YV12, luma and chroma planes don't have the same size, you need either to shrink or to enlarge the plane. Hence the choice of the resizer.

So, no equivalent of YtoUV. But other functions with other uses.

Mug Funky
12th August 2004, 19:35
hooray for faster difference masking!


yv12lutxy(last,last.deleteframe(0),yexpr="x y - abs",Y=3,U=-127,V=-127)


this is gonna make smart bobbing SO much faster!

Didée
13th August 2004, 07:54
Welcome to yv12LUTxy wonderland, Mug Funky :D

Do you remember LimitedSharpen? Well, where the core of the script before looked like this
too_bright = YV12subtract(
\ logic(normsharp,bright_limit,"max")
\ ,bright_limit
\ )

too_bright = (power == 0.0) ? too_bright.YV12LUT(Yexpr="x 128 - abs").binarize(overshoot,upper=false)
\ : too_bright.YV12LUT(Yexpr="x 128 - abs "+string(power)+" ^")

too_dark = YV12subtract(
\ logic(normsharp,dark_limit,"min")
\ ,dark_limit
\ )
too_dark = (power == 0.0) ? too_dark.YV12LUT(Yexpr="x 128 - abs").binarize(overshoot,upper=false)
\ : too_dark.YV12LUT(Yexpr="x 128 - abs "+string(power)+" ^")

MaskedMerge(normsharp,bright_limit, too_bright, Y=3,U=1,V=1, useMMX=true)
MaskedMerge(last,dark_limit, too_dark, Y=3,U=1,V=1, useMMX=true)

it now looks like that:
OS = string(overshoot)
yv12lutxy( bright_limit, normsharp, yexpr="y x "+OS+" + - < y x ?")
yv12lutxy( dark_limit, last, yexpr="y x "+OS+" - - > y x ?")
That's a bit of a difference, isn't it!

Practically, this enables e.g. an equivalent to 4*supersampled XSharpen'ing that's running 2.0~2.5 times faster than the traditional script. Oops.
I'll post it this weekend, perhaps with some other stuff.

- Didée

Mug Funky
13th August 2004, 16:39
i am SO excitement :)

You Know
27th August 2004, 03:40
i'm try to use YV12LUT on V channel but it seems work only on luma channel :confused:

return YV12LUT(last, yexpr="255")

OK image are very brightens.

return YV12LUT(last, uexpr="255")
return YV12LUT(last, vexpr="255")
return YV12LUT(last, uexpr="255", vexpr="255")

no effect is normal???

anyone can try this?

PS i use avisynth beta2

Manao
27th August 2004, 05:41
For each filters in the masktools, there are 3 parameters, Y, U and V, which allow you to process or not the channel. By default, y=3, U=1 and V=1, which means that we process only Y, and that U and V are left untouched.

For more details, have a look here (http://jourdan.madism.org/~manao/MaskTools.htm#description) .

Didée
27th August 2004, 07:33
Can you confirm that UV channels can or cannot be processed by yv12LUTxy? I think I had some problems with it - but currently I can't touch all that stuff.

Mug Funky
27th August 2004, 08:49
it works for me, didee. only did a quick test though (and currently my virtualdubmod is having difficulties that may or may not have nothing to do with avisynth. lots of warnings on exit, and referenced memory type of errors)

Didée
27th August 2004, 09:26
K, then I'll have to figure more own silliness at some time. Major task.

Thanks for confirmation.

You Know
29th August 2004, 18:19
@manao

thanks, i have only see function firm parameters

Schlumpf
17th October 2004, 22:31
I have a wish for a feature in masktools, that would make amv-editing easier :)
Whenever I want a certain,moving character to be overlayed onto the videolayer below, i have but one option in Premiere to cut it out. Well... there are several more options in Premiere, but the vast majority of them refer to the same technique in the end, meaning: Luma/Chroma-Differences.
Now, whenever I am unlucky enough, that my source doesn't provide hard-enough contrasts, which is the case quite often, the only option left is to cut out the wanted parts frame-by-frame with Photoshop and reimport them or use them as a black&white transparency mask.

Recently I found out about the MotionMask funtion in masktools and tried to "abuse" it for my masking purposes.
After a bit of tweaking, I found the following line to give the best contrast:

MotionMask(thY1 = 1, thY2 = 20, thC1 = 1, thC2 = 30, thSD = 255).Greyscale()

This gives me a black&white Image which could be used as a transparency mask in Premiere, if there weren't 2 flaws left:
1)The moving areas are white now, but they are not "complete". There are many black spots inside of them, but I need the whole obejct.Any ideas on how to fill the area until it is completely white?

2)The generated mask seems to contain ghosting. Example: In frame 1 we have a man standing completely still. In Frame 2 he raised his left arm. The MotionMask Output on frame 2 will now be a mask where you can see 2 left arms.
Is it possible to show only the pixels that have changed from the preceding frame and not a mixture of both?

I hope my english wasn't too confusing, otherwise I could try and dig up some webspace where I can upload the sample I'm currently working on.

scharfis_brain
17th October 2004, 22:37
to only show one instead of two arms use this method:

MotionMask(thY1 = 1, thY2 = 20, thC1 = 1, thC2 = 30, thSD = 255).Greyscale()
logic(last,last.trim(1,0),"AND")

Schlumpf
17th October 2004, 23:09
Ok, that method might work with my given example (which was purely fictional), but it seems to fail with more action motion on the screen.
I really need to find some webspace... :(

Manao
18th October 2004, 05:28
Use MVMask from the MVTools, you should get a better motion mask.

In order to fill a binary mask, you can try Expand.Expand...Expand.Inpand.Inpand...Inpand but you'll deform the edges of the mask

Another solutiob to fill it, which might work, is to use a blur followed by a binarize, but it's rather hard to find the threshold which will allow you to fill only the gap inside motion areas.

Schlumpf
18th October 2004, 16:18
Use MVMask from the MVTools, you should get a better motion mask.
I could finally convince a friend to lend me some of his webspace and uploaded an extract of the sample I'm currently working on (encoded in VBLE): Sample (http://www.netcologne.de/~nc-schmidew/Hammerbutton.avi)

You can see the line I used in Masktools if you scroll up. The borders are crisp and nice with that and the overall image would be perfect if it weren't for the 2 flaws I described.
I fiddled with the syntax of mvmask from the MVTools package and found it to be inferior for my purposes.

Orig=AVISource("C:\Material\MotionMask\Hammerbutton.avi")
vec_forw = Orig.MVAnalyse(isb=false,pel=8,sx=8,sy=8,st=3,stp=48,lambda=2000)
MVMask (Orig, vec_forw, ml=40, gamma=1, showsad=true, Ysc=100).Greyscale()

That's the best I could manage and borders are very blocky/blurred.

In order to fill a binary mask, you can try Expand.Expand...Expand.Inpand.Inpand...Inpand but you'll deform the edges of the mask
Tried that and as you said: The amount of inpand/expand needed in order to fill all holes would massacre the original edges.
Your suggestion with binarize lead to a similar effect as well as some tests with different median filters.
Looks like I will have to spend hours in Photoshop again ~__~
But thanks for your efforts, I really appreciate it!

tedkunich
1st December 2004, 08:24
@Manao

It seems that RGBLut when using an AMP file only applies the RBG mode (i.e. grey scale) of the AMP file and ignores the individual R G and B components. Is there some other parameter that needs to be set for it to operate in /R/G/B mode? I'm using Masktools 1.5.5


Thanks

T


[edit] found a previous post about RGBLut defaulting to the RED only and adding R=3,G=3,B=3 to the params fixed it....


Thanks

Manao
1st December 2004, 09:07
I'll change that behavior. In YUV, we often have only to process the luma channel, so the defaults y=3, u=1, v=1 are purposeful, but in RGB, it's more than silly.

Thanks for pointing that out :)

krieger2005
14th December 2004, 23:36
I have a problem when using MaskedMerge for merge the U and V-Channel for two clips. I done a mask in this way:

bMask=blue.YV12LUT(YExpr="x 20 > 255 0 ?", UExpr="x 18 > 255 0 ?", VExpr="x 18 > 255 0 ?").Blur(1)


When i try to merge the Clips so:
MaskedMerge(a,a.BlankClip(pixel_type="YV12", color=$000000),bMask,Y=1, U=3, V=3, useMMX=true)
not only the parts in the mask marked were merged but the hole image. So the hole U-V-Channels were changed. How should i do it right? I thought i done it right...

And second:
Is this enough to build the mask for maskedmege so than only U-V-Channels were proceed:
bMask=blue.YV12LUT("x 20 > 255 0 ?").Blur(1)

Manao
14th December 2004, 23:53
You have to remember that each channel ( Y, U and V ) are independant. To process a channel, you must specify it using the y, u and v parameters ( usually setting them to 3 ).

That also means that an YUV mask is in fact made of three distinct masks : the one on Y, the one on U and the one on V.

So, in your case, you must create the U and V masks by adding u=3, v=3 in yv12lut

krieger2005
15th December 2004, 01:40
Still the same problem... The best is, i post the hole script here...

mpeg2source("D:\VTS\Kasaki\d2v\film.d2v", iPP=true)
a=last

Tweak(sat=3, hue=0.6, cont=1.6)
ConvertToRGB32()
blue=RGBLUT(rExpr="0", gExpr="0", bExpr="x 120 > 255 0 ?", r=3, g=3, b=3)
blue=blue.GreyScale.ConvertToYV12

bMask=blue.YV12LUT(UExpr="x 18 > 255 0 ?", VExpr="x 18 > 255 0 ?", y=1, u=3, v=3).Blur(1)
bl=a.ConvertToRGB.RGBAdjust(0.95, 1.03, 1.15, 1).ConvertToYV12
MaskedMerge(a,bl,bMask,Y=1, U=3, V=3, useMMX=true)
return interleave(bl,last) # bl and last are equal, but should not be


Here bl and last are same... bMask is a mask with dark-pink and light-pink colors...

------ stop EDIT ----
I set the thresholds false... sorry

Manao
15th December 2004, 07:21
BTW, you should use "binarize" if you only want to threshold your video, it'll be faster than YV12LUT

Didée
29th December 2004, 14:47
Alas, a bug report:

In MaskTools v1.5.5, chroma handling of YV12LUTxy is halfway broken:

yv12lutxy( v1,v2, yexpr=STR1, uexpr=STR2, vexpr=STR3, Y=3,U=3,V=3)

does process all three Y,U,V planes with the STR1 expression. STR2 & STR3 do not apply, there's no chance to treat U & V individually.

Smells like a typo, or a copy'n'paste error ;)

Manao
29th December 2004, 14:50
Indeed, a bad copy'n'paste error :) Well spotted, I'll correct it asap and release another version.

Manao
3rd January 2005, 07:38
Corrected : new version up at manao4.free.fr :

http://manao4.free.fr/MaskTools-v1.5.6.zip

Didée
3rd January 2005, 08:51
Merçi beaucup, Manao! That helps finishing the next script, codename "lutMANIA" ;)

State of Mind
3rd January 2005, 09:37
This may be a stupid question, but what exactly does MaskTools do? A variety of things? I have checked the documentation, but don't understand many of the terms used in the descriptions. I was just wondering if this MaskTools has any highlights that make DV look better quality-wise?

Didée
3rd January 2005, 11:15
In the documentation, part I) 1) gives a simple description of the scope of the MaskTools.

MaskTools contains many functions to perform transformations on a frame's pixels, generally speaking.
There are no filters in it that can >directly< produce something useful (except for the LUTs). But they offer a cornucopia of possibilities to produce valuable "helper" clips - as the name implies, mostly all sorts of masks (for later performing any filters to only specific parts of a frame), but also convolutions for customized blurring/sharpening kernels, and other neat stuff.

So, while there is nothing in it that would directly improve anything on DV sources, a script that does improve DV sources probably will use the MaskTools. ;)

I could hardly imagine [anymore] to do any serious avisynth scripting without the MaskTools - for me personally, they have become an integral and mandatory part of the Avisynth world. iiP, LimitedSharpen, Restore24 , BlindDeHalo/2, LimitedTemporalSoften, Ylevels, FineEdge, ... plus some forgotten small scriptlets - all those functions wouldn't exist (or would be slow beyond usability) without the incredible MaskTools.

Wilbert
3rd January 2005, 11:32
So, while there is nothing in it that would directly improve anything on DV sources, a script that does improve DV sources probably will use the MaskTools.
Yeah right.

I could hardly imagine [anymore] to do any serious avisynth scripting without the MaskTools - for me personally, they have become an integral and mandatory part of the Avisynth world.
Yeah right. I guess I'm not a serious avisynth scripter then :confused:

Don't get me wrong, because this MaskTools is great stuff, but don't exaggerate the necessity of it. Or do you think that using MaskTools to denoise analog stuff will get you better results than using "ordinary" denoisers?

State of Mind
3rd January 2005, 11:40
Originally posted by Wilbert
Yeah right.

Why "Yeah right?"
Just trying to get all info here. :D

Didée
3rd January 2005, 12:53
Originally posted by Wilbert
Yeah right. I guess I'm not a serious avisynth scripter then :confused: That's not what I have said. It should have become clear that I was speaking only about *my own* habits. All of the *easy* stuff has already been invented (well, most of it). To get more tailored solutions, one needs more dedicated processing.
Or shall we make a sportive contest a la "all plugins are forbidden from now on, only Avisynth's internal functions are allowed to use?"


analog stuff Oh! I heard some rumours that such sources still would exist. Is this really true? :D


do you think that using MaskTools to denoise analog stuff will get you better results than using "ordinary" denoisers? Thus quoth the man that didn't try preprocessing with LimitedTemporalSoften yet ;)

(Although, if you're going to feed stuff like that Dido clip from the denoiser comparison, then the spatial part probably would have to get adjusted. *Such* noise is very difficult to process - especially since below that noise, what is left to find is ... not very much.)

Wilbert
3rd January 2005, 13:05
That's not what I have said. It should have become clear that I was speaking only about *my own* habits.
That DV comment sounded as a general comment. (Therefore) I took your other comment to be general too, but I wasn't sure. But, ok :)


Or shall we make a sportive contest a la "all plugins are forbidden from now on, only Avisynth's internal functions are allowed to use?"
I didn't say you are not allowed to use MaskTools :) Remember that I wrote documentation for it, and I don't do that for plugins that I don't like.


Thus quoth the man that didn't try preprocessing with LimitedTemporalSoften yet ;)

(Although, if you're going to feed stuff like that Dido clip from the denoiser comparison, then the spatial part probably would have to get adjusted. *Such* noise is very difficult to process - especially since below that noise, what is left to find is ... not very much.)
That's a good idea. I will try it to my Dido clip. How should I adjust the spatial part?

"Analog stuff" Oh! I heard some rumours that such sources still would exist. Is this really true? :D
Well, if we all go digital, and the broadcast flag is introduced, it will be the only thing left. Maybe ... :)

Didée
3rd January 2005, 13:19
I will try it to my Dido clip. How should I adjust the spatial part?
Stronger pre-blurring. The pre-blurring is only a rough spatial cleaner to get a better measurement from the full, unrestricted temporal blur. For strong noise, replace that "blur(preblur)" with something like "bicubicresize([33%~~66%],.33,.33).bicubicresize([100%],1.0,0.0)". Finding the "sweetspot of preblurring" is the main trick.

Hmh, better should make an own thread for that one, too. Oh my.

State of Mind
3rd January 2005, 13:33
I think because I am so quality-driven (outrageously picky) and I love to just sit in my chair and analyze things over and over 100 million times that I will probably be the person to do the most customized scripting along with the general stuff that starts it. And since I have yet to learn a lot, I will likely ask a crapload of questions to better understand everything that goes on in the world of AviSynth. But, I am absolutely impresed at what can be done and in love with AviSynth. :D

Mug Funky
9th January 2005, 15:16
my .amp files aren't working :(

RGBlut(ampfile="C:\MediaTools\AviSynth 2.5\plugins\filmlook_02.amp",R=3,G=3,B=3)
gives me a processed red channel, but nothing else.

i can provide the amp file, but it's nothing special - it has a curve for RGB, plus R, G, and B as well (total 4 curves). generated with potatoshop 7.

btw, limitedTemporal looks interesting.

gst
9th January 2005, 16:36
gives me a processed red channel, but nothing else

Same here. And i use photoshop 7 to for create the .amp file.

Manao
9th January 2005, 17:49
Give me the ampfile, it seems that the file format has changed. When I implemented it, there were only the curves for the three channels. There wasn't the curve for RGB.

gst
9th January 2005, 18:10
http://x.spirit.free.fr/test.amp

Manao
9th January 2005, 19:46
gst : thanks ! However, the file you posted contains 6 curves. The first one is a real curve, while the five others are in fact the identity ( unprocessed ). So i don't know what to do of that.

What's the expected behavior of your ampfile ? Can you post a screenshot of what the curves should look like ?

Can you post also others ampfiles, more complicated, because one may not be enough for me to understand how the curves should be used.

gst
9th January 2005, 21:44
Original
http://x.spirit.free.fr/amp/amp_before.png

Modified
http://x.spirit.free.fr/amp/amp_after.png
http://x.spirit.free.fr/test.amp

Complex
http://x.spirit.free.fr/amp/amp_complex.png
http://x.spirit.free.fr/amp/complex.amp

Complex with 3 channels used :
http://x.spirit.free.fr/amp/amp_complex3channels.png
http://x.spirit.free.fr/amp/complex_3channels.amp

Didée
10th January 2005, 01:31
Shamelessly quoting myself: :)

Originally posted by Didée

Originally posted by CraigBjorn
The only downside .. is that we only have photoshops curves availible for import. If there were a way to import giimp curves ..

Photoshop curves. Gimp curves. What about CorelDraw curves? Or PaintShop curves? Personally, I'd like to see PictureWindow curves. Others might prefer even other applications.

I dislike the hooking to specific formats of specific applications. There should be something like a general curve generator. Basically, it's already there: the "adjust.dll (http://www.avisynth.org/warpenterprises/files/adjust_25_dll_20031110.zip)" plugin. Call the filter with your control points as parameter, get the resulting curve. Really a pity that it's "yuy2 only" ... [HINT!] :)

While it's not a problem for me, I think the usage of Photoshop curves exclusively is a little unfair to the bigger part of the world ...

E-Male
12th January 2005, 07:20
well, your selfquote isn't up2date

Manao
12th January 2005, 07:48
gst : i still don't understand how the fileformat work, and especially, what to do of the RGB channels. Do you have any insights on how it should work ?

Mug Funky
12th January 2005, 09:46
i made a curve with REALLY simple values in it, then read it in a hex editor.

i don't know what the 5th curve is for, but the rest is pretty straightforward.

the order of curves in the file is RGB, R, G, B, and another one.

when i make a curve for a CMYK file, the last curve is used for K. i guess it's one generic format for all colourspaces in photoshop.

the question is how the "value" curve is applied with the individual curves? i suppose it'd be easy enough to figure out.

Manao
12th January 2005, 09:52
the question is how the "value" curve is applied with the individual curves? i suppose it'd be easy enough to figure out.I don't. I don't see the point of the RGB curve, and I don't know how i should use it. I'm not able to reproduce gst's samples, because the RGB curve is never the identity.

E-Male
12th January 2005, 09:54
last curve could be for the alpha channel (similar to gimp)

btw, seems like we got the same problem with both formats:
?what to do with the rgb/value curve?

Didée
12th January 2005, 11:10
Seems like the RGB/value curves are a 2nd adjustment step, applied equally to all three of the R,G,B channels. That makes sense, especially when working in an 8bit format: That way one can do e.g. an S-shape contrast enhancement together with fine graduaded R,G,B adjustments wich a much better precision, compared to two individual filter operations performed sequentially.

Manao
12th January 2005, 11:14
I tried RGB[R[x]] and R[RGB[x]] and none gave me the expected result ( ie the one on the screen shots ). I don't know what I else I could try.

gst
12th January 2005, 11:52
I have no clue, sorry. But there's a virtualdub filter which works fine. It was made by bugs-bunny :
http://forum.doom9.org/showthread.php?s=&threadid=68600

And page 6 of this thread, he says :


An amp file can generally contain 1, 3, 4 or 5 curves.
If there is one -> rgb(grey) values
3: R, G, B values
4: RGB and R, G, B values
5: If you're in the CMYK colorspace and save a amp

E-Male
12th January 2005, 13:38
Originally posted by Manao
I tried RGB[R[x]] and R[RGB[x]] and none gave me the expected result ( ie the one on the screen shots ). I don't know what I else I could try.

my only hope atm is some enlightening word by teh gimp developers
i wrote to their dev-ML

BBugsBunny
14th January 2005, 17:16
I've updated my filter - now it has got a very basic mouse support that I'm very likely going to improve in upcoming versions.
So the curve can now be edited with mouse within the filter and then be exported to an amp file.
here's the thread:
http://forum.doom9.org/showthread.php?s=&threadid=88269

gst
14th January 2005, 22:37
Nice job Bugs Bunny.
Maybe you can share some tips to manao, it would be great to use the curves directly with avisynth.

BBugsBunny
15th January 2005, 21:22
Sure I can share some tips. Just send me a PM!
To the photoshop curves in general:
Photoshop can process images in different colour spaces.
If you transform an RGB image into CMYK you get 4 channels plus a channel that processes all, so 5 in total.
That's why amp files can have more than 4 curves.
In RGB you normally have 4 curves.
The first one is the RGB curve Then R followed by G and B.
My import function works like this:
If there is only one curve in the file it gets loaded into the RGB curve. If there are 3 curves the get loaded into the separate R G B channels. If there are 4 then the first gets into RGB the rest into R, G, B. If there are more than 4 curves the first 4 are imported (like the case with 4), all above do not get imported.
I always store an amp file with 4 curves whether or not all are used. This amp file can always be imported back to Photoshop.
Now to the RGB / R / G / B channels:
If you use (in my filter) RGB + R / G / B processing, there are 2 calculation steps - just like in Photoshop.
If eg. in the RGB curve the input value of 10 has got an output value of 20, then you sum up 10 to all pixels that have got a R value of 10, 10 to all pixels that got a G value of 10 and same for B. Then in a second step - if you've got for an input of 10 in the R cuve an output of 15 then all pixels that got an R of 10 after the first processing, then get a value of 15. So eg. doing an inverse on the RGB curves and also on the R / G / B curves you got noninverse picture (=input) again.
My weighted mode operates a bit different. It first calculates the Y value and then sums up to all the values of this pixel (eg. R G B 4 5 6) the same value. (Double inverse does not work here any more).
In general the RGB curve can be used to do things like contrast, brighntes, gamma, coring (and other things).
Hope this helps ab bit!

krieger2005
20th January 2005, 00:19
sorry for the maybe stupid question, but i don't know what i should do now. The following code deliver for me a simple grey background:

c=last
remGrain=YtoUV(UtoY.RemoveGrain(4), VtoY.RemoveGrain(4), RemoveGrain(4)).Blur(1.58)
q=YV12LUTxy(c,remGrain,UExpr="x y - abs",Y=1, U=3, V=1)
p=YV12LUTxy(c,remGrain,UExpr="x y - abs",Y=0, U=3, V=0)
return YV12Subtract(p,q,Y=3,U=3,V=3).ColorYUV(autogain=true)

But this is not the real problem. This little Script deliver for me a green screen:
c=last
remGrain=YtoUV(UtoY.RemoveGrain(4), VtoY.RemoveGrain(4), RemoveGrain(4)).Blur(1.58)
q=YV12LUTxy(c,remGrain,UExpr="x y - abs",Y=0, U=3, V=0).ColorYUV(autogain=true)
return q


The Problem: in the first example: How can YV12LUTxy deliver same results (because Subtract return a grey screen), if for q Y=1 and V=1 are used and for p Y=0 and V=0 are used.

Why YV12Lutxy return "no difference" between remGrain and c? I looked for the U-Channel and it changed in remGrain.

I use the Masktools 1.5.6.

BTW: Does some know, if RemoveGrain operate on U and V-Channels or only on Y-Channel?

Manao
20th January 2005, 07:17
krieger :

first script : when you use y=1, you say to the filter that the y channel is meaningless to you, so it can make what it want of it. You've got no control at all over the result. So it may very well end up as if y=0 had been used.

second script : remgrain is basically the denoised version of c. So it's not very different from it. Hence, the differences on the U channel, if any, are bound to be small, close to 0 in fact. Y = 0, u = 0, V = 0 gives a dark green. If U stay close to 0 ( and i'd bet that in that case, x y - abs is always under 10 ), you'll still get a dark green clip as result, though it should not be uniform.

Didée
20th January 2005, 09:00
Originally posted by krieger2005
BTW: Does some know, if RemoveGrain operate on U and V-Channels or only on Y-Channel?
It is supposed to do so. The full syntax is

"RemoveGrain(mode=a,modeU=b,modeV=c)"

where unspecified parameters are defaulted to the value of the last (or only) specified parameter. Therefore, your puzzle game

remGrain=YtoUV(UtoY.RemoveGrain(4), VtoY.RemoveGrain(4), RemoveGrain(4)).Blur(1.58)

should deliver the same result as

"RemoveGrain(4).blur(1.58)".

krieger2005
20th January 2005, 20:25
Therefore, your puzzle game

remGrain=YtoUV(UtoY.RemoveGrain(4), VtoY.RemoveGrain(4), RemoveGrain(4)).Blur(1.58)

should deliver the same result as

"RemoveGrain(4).blur(1.58)".
Hehe, nice to know :).

So it's not very different from it. Hence, the differences on the U channel, if any, are bound to be small, close to 0 in fact
You are right. But i thougt that the ".ColorYUV(autogain=true)"-call would make these differences visible. But it seems to operate only on the Y-Channel (or there are more options to set right, that i show it right. I will read this in the help-pages).

Thanks for help

Manao
20th January 2005, 20:30
If you want to see better the difference, use the expression : "x y - abs 20 *", that should do.

AVIL
9th March 2005, 20:29
Hi :

In the masktool documentation :

"YV12Substract is the same as Subtract, also works in YV12, but *should* be a bit faster (because MMX optimised)."

But in fact, Subtract uses an offset of 126 (pixel difference is halved and added by 126)while YV12Subtract uses 128 as offset.

You Know
6th April 2005, 15:17
MaskedMerge (MaskTools 1.5.6) seem not work, teorically white should be 100% opacy and black 100% trasparent.


base = MPEG2Source("Menu.d2v",idct=4).ConvertToYV12()

AudioLayer = ImageReader("setuplayer.bmp",0,100,29.970,false) \
.ConvertToYV12()
AudioMask = ImageReader("setupmask.bmp",0,100,29.970,false) \
.ConvertToYV12() \
.Binarize(threshold=128, upper=false)

return MaskedMerge(base,AudioLayer,AudioMask)


see result here http://wwwstud.dsi.unive.it/~nfalco/doom9/EVA.zip

Manao
6th April 2005, 15:27
First : default paramters for Binarize are Y=3, U=1, V=1, which means that U and V won't be processed at all, and that these planes will be garbage, hence, your mask isn't what you expected.

Second : default parameters for MaskedMerge are Y=3, U=1, V=1, which means ( this time ) that U and V will be left untouched ( i.e. copied from the original clip ).

So it's not a bug.

Edit : in order to do what you want to do, you have to copy the luma mask into the chroma channels. That can be done by :

YToUV(mask, mask).bilinearesize(width(mask), height(mask)).mergeluma(mask, 1)

Didée
6th April 2005, 15:41
The attachment first needs to be approved by a moderator.

No, the MaskTools are working correct. What you are experiencing is an effect of the standard YUV[16,235] <--> RGB[0,255] conversion. Your Bitmap file comes as RGB, but after ConvertToYV12() the black level (RGB=[0,0,0]) and white level (RGB=[255,255,255]) will have become [16,128,128] resp. [235,128,128] in YV12 (or YUY2, for that matter).

For "normal" tasks of colorspace conversions, this is the correct behaviour when working with video files. But when working with masks, it is not.

Your options are:

1a) ConvertToYV12().Levels(16,1.0,235,0,255,false)
1b) ConvertToYV12().ColorYUV(levels="TV->PC")

2) ConvertToYV12(matrix="PC.601")


Methods 1ab) do work, but might be suboptimal (smooth gradients will get small stairsteps in them).
Method 2) is preferred, but requires a recent versions of AviSynth (not sure ATM when those "matrix" options were included.)


Edit: hehe, tooo slow again. However:
Originally posted by Manao
in order to do what you want to do, you have to copy the luma mask into the chroma channels. That can be done by :

YToUV(mask, mask).bilinearesize(width(mask), height(mask)).mergeluma(mask, 1)
What about

mask.FitY2UV()

?

Manao
6th April 2005, 15:45
Didée : I edited my post, have a look at it.

Didée
6th April 2005, 15:56
Manao:

Okay, never again I will answer to any post before at least 24 hours have passed ;)

But I seem to have my dumb day today: Why are you jiggling around with the planes through YtoUV()? I don't see it ATM...

Manao
6th April 2005, 16:00
I don't know if there's something faster to copy the Y channel in the U and V. Oh, well, perhaps FitY2UV does the job, but i never checked if this filter is working correctly.

You Know
6th April 2005, 16:52
thank to all this quite work there is also a color problem due to convesion


YMask = ImageReader("setupmask.bmp",0,1650,29.970,false).ConvertToYV12()
AudioMask = YToUV(YMask.ReduceBy2(), YMask.ReduceBy2(), YMask)

return MaskedMerge(base,AudioLayer,AudioMask, Y=3, U=3, V=3)