Log in

View Full Version : "Absolute Value" of Subtract()?


Karyudo
7th November 2004, 21:29
Yarrrgh. I've been poking around with commands like Subtract(), Greyscale(), Levels() and even Invert(), but I can't find the combination that will do what I want, which is to produce a specific greyscale clip for use with Overlay() or Layer().

I'm starting with a raw clip, plus that same raw clip with rotoscoped frames inserted. I now want to copy just the rotoscoped changes (not the whole rotoscoped frame!) to a new clip that has been captured with different contrast, saturation, etc. So what I think I need is a clip that is all black, except for (greyscale) white bits where the rotoscoped changes exist.

When I do a Subtract(), I get 128-level grey everywhere but where there are changes due to rotoscoping, which show up as either white or black (or grey) specks/lines/shapes. That's a start.

But to do what I want to do with Layer(), I need a 0-level black background -- so by default there are no changes to the source -- and primarily-white (i.e. above 128-level grey) specks, regardless of whether they're actually <128 or >128 in the original Subtract(). I just want a black clip that shows any difference at all as a brighter (near-white?) entity.

I think this would be pretty easy if there were an "absolute value of subtract" function, but of course there's no such thing. Yet.

Any ideas??

scharfis_brain
7th November 2004, 21:40
there are two possibilities:

1st method

script it yourself:

subtract(a,b)
positive=levels(128,1,255,0,255)
negative=levels(0,1,127,255,0)
overlay(positive,negative,opacity=0.5)

the problem with this approach is, that it completely ignores chroma differences.



2nd method

abuse motionmask from mastools.dll

interleave(a,b)
motionmask(thy1=0,thy2=255,thc1=0,thc2=255,thsd=255)
selectodd()

Karyudo
7th November 2004, 21:51
Actually, for me, the chroma differences aren't important at all! I'm planning to use the new capture as the main clip, this black-with-white-bits clip as an alpha channel, and the existing rotoscoped clip as the overlaid "donor clip". That will bring just the rotoscoped parts into the new clip, without me having to re-roto everything. I can adjust the saturation and contrast of the "donor clip" to be as close to the new capture as possible. Since I'm mostly rotoscoping dust, etc., in the end it should be close enough.

I'll give these methods a try. And I must say I like the sound of "abusing" MaskTools! Thanks, scharfis!

(As an aside, where can I find a layman's guide to MaskTools, with lots of sample frames to look at? I know of MaskTools, but I don't really know what all it can do, or why I might need it. I'd really like to learn...)

Manao
7th November 2004, 22:03
absolute value of subtractUse YV12Subtract, from the masktools : the documentation is
here (http://jourdan.madism.org/~manao/MaskTools.htm#subtract). An "absolute" subtract is YV12Subtract(clip1, clip2, widerange = false, tol = 0).

Concerning the masktools, there's no guide that I have heard of, but if you find the documentation unclear / uncomplete on a certain point, you're welcome to ask for precision / clarification, I'll use them to improve the documentation.

Karyudo
7th November 2004, 22:19
Thanks, Manao. I'll try reading the docs, once I can load the page (my problem, perhaps?).

I tried both of scharfis' methods, and Method 1 comes closer to what I was expecting. Unfortunately, overlaying positive and negative halves the brightess of any spots, which means I'll end up only half-fixing anything, doesn't it?

The MaskTools route gives a pretty good mask, but to my surprise it's all green! I'm not quite sure what to do with such a clip. Yes, I'm going to go away and do some reading. No, I'm not sure where to start. Got any 50-word summations of what sort of mask I've got, and how I might use it? And/or some suggestions as to what sites/threads I should be reading first?

Manao
7th November 2004, 22:55
I still have a lot of problem with my ISP, that explains the unavailibility of my website. However, you should find the same doc inside the .zip containing the filter.

The mask you're obtaining is green, because of the way the YV12 colorspace works : when the U and V channels are 0, the picture is not greyscale, but greenscale. To have greyscale, you must have u = v = 128 . Anyway, if you only want to filter the luma, you don't have to care about the chroma, so a greyscale or greenscale clip is of no importance.

Finally, a mask is meant originally to be used with MaskedMerge. It tells where to apply modifications ( pixels of the mask which are different from 0 ). You want for example to blur the moving parts of the video ? you detect those motion parts with motionmask, you make a copy of your video which you blur, and the you merge the results only where the pixels of the mask are not 0, with maskedmerge(clip, blurred, mask).

Karyudo
8th November 2004, 02:36
OK, I've gone away and done some reading as well as some goofing around with various MaskTools commands. Pretty cool. I can only barely think of some of the uses for several of those things, but as you'll see below, I think I'm catching on...

I've hit a snag, however.

Take a look at this partial screencap:
http://img55.imageshack.us/img55/150/masktoolsproblem2qc.png

In the upper left is my new cap, clearly flawed.
Below it is the old cap (no, it's not identical...), fixed through rotoscoping. I obviously want the new cap to have the same fix, but I don't want to have to re-roto everything. Or anything, even.

In the upper right is a MaskTools-generated mask. I did this with the following code:

dif=interleave(clip,clip_fix)
msk=dif.motionmask(thy1=0,thy2=255,thc1=0,thc2=255,thsd=255)
msk=msk.selectodd().binarize(1,false).expand()

In the lower right you see the result -- NOT what I want, exactly. But here's my method; I don't see what I've done wrong:

clip_masked=maskedmerge(new_clip,clip_fix,msk)

By using Binarize() during mask creation, I thought my mask should now be either 0 or 255, and using MaskedMerge should return either the existing pixels from new_clip, or the fixed pixels from clip_fix. But that is apparently not happening.

What have I messed up?

Karyudo
8th November 2004, 04:03
I'll tell you what I messed up -- I needed to add following:

clip_masked=maskedmerge(new_clip, clip_fix, msk, u=2, v=2)

I found that little snippet of code on the docs page (which finally loaded). It was a little tough to find, for the following reasons:

1. The docs page still says it pertains to version 1.4.16
2. The individual HTML help files for the filters do not describe all the various parameters, nor are (m)any examples given.
3. I still don't quite get why adding U=2 and Y=2 works (but I'll take it).

In trying to solve the problem, I also upgraded to MaskTools 1.5.5 (upped yesterday), so I wonder if that fixed my Binarize() so that this final change worked?

Anyway, I think I've got my problem solved, so thanks to both scharfis and Manao for the speedy help!

Manao
8th November 2004, 11:09
The documentation is up to date, except for the version number. I'll correct that.

What happened in your case was that you had to suppress an artifact which was both in the luma and chroma planes. By default, all the masktools filters work only on the luma, and you have to use the u and v ( setting them to 3 )settings to make them work on the chroma.

MaskedMerge works slightly differently : y|u|v = 1 means you copy the plane of the first clip. 2 means you copy the plane of the second clip. 3 means you process the plane. In your case, you should do artifact detection and maskedmerging in the three planes, so you should use y=u=v=3 for all your filters.

Karyudo
8th November 2004, 15:42
Thanks, Manao. Yeah, I sorta figured the documentation was OK -- especially since what I ended up doing worked! Still, when I looked only at the documentation for each individual tool in MaskTools (i.e. by loading the individual HTML files), those additional, global switches weren't mentioned at all. Which ended up making for some frustrating experimentation.

It never really occured to me that I was making a colour mask; I thought I was building purely a greyscale (or alpha channel) mask. Even your earlier post seemed to support this, when you told me not to worry about the mask being green.

But it's all sorted now, and I've added another (partial) set of tools to my AVS repertoire -- many thanks!

Manao
8th November 2004, 15:52
I'll quote you :Actually, for me, the chroma differences aren't important at all!That's why I told you the green wasn't important.

On the documentation, you shouldn't use individual html files ( I even wonder why i let them into the package, they are outdated ). All the filters works the same way - concerning Y|U|V, as described in the html file - except MaskedMerge ( I'll update its documentation ).

Karyudo
8th November 2004, 17:04
Point taken. But you shouldn't have followed what I wrote; rather, what I meant! ;) I thought chroma differences didn't matter because I was making an alpha-channel style mask. When I've used Layer() in the past, I've made an alpha-channel mask that is purely greyscale, but is applied to all channels (RGB, I guess, since the alpha channel is 8 bits of the RGB32 format). When I read that greenscale was the same as greyscale, that's how I was thinking about it. Now I see why that isn't true: because MaskTools is even more flexible and powerful than I originally thought!

Documentation is a bitch, no matter how you approach it. I hit my particular problem by looking at the documentation one way; maybe somebody else could find an equally frustrating problem if the documentation were organized some other way. For MaskTools, probably your monolithic file covering all commands is the best way to go. Up to you, of course; that's just my two cents. I'm just impressed as all hell that there are so many multi-lingual filter writers who take the time to produce docs in several languages, and maintain them. I'm pretty unilingual (although I could probably get by reading French documentation if I really had to), but I'd consider making docs even in my one language a pain in the ass.