PDA

View Full Version : masking shadows / dark portions of an image


morsa
4th January 2006, 02:25
Ok, here I go again.I'm quite interested about being able to use Masktools or whatever to isolate shadows from video so I can process them alone.
My problem is I've been looking around for almost 2 days to find some examples, read Masktools documentation and I still have no clue about how to do that?
Can someone more experienced point me to examples, documents or anything about how to script that?

Mug Funky
4th January 2006, 03:42
if your definition of "shadow" is just "everything below a certain luma", then you can get a mask with binarize, or yv12lut, or levels.

if you're looking at more advanced ways to define shadow areas, it could get a little fiddly (like local minima over a certain radius, or colour temperature...).

try:

overlay(clip.shadowfilter(),clip,mask=clip.levels(32,1,112,0,255,coring=false))

[edit]

"shadowfilter()" is just something i made up to represent some filters you'd like to run on the shadows

Didée
4th January 2006, 03:42
In the end, it also depends pretty much on what exactly you're going to do (what kind of filtering), and also on the type of source (animation <-> natural).

Basically you create a mask of the dark areas, a version of the input clip with YourSpecialDarkFilter() applied, and then combine them via MaskedMerge.

But what exactly is the "dark area" that should be masked?

Most simple: everything that's below a threshold.
input.Binarize(32,upper=true) will mask all pixels <=32 with "255", and all pixels above with "0".
This is not very good. The mask has a sharp transition (and lots of spray noise), and the different effects of different filtering may become visible at the mask boundaries.

Better: soft thresholding.
LO = string( 24 )
HI = string( 48 )
input.yv12lut("x "+LO+" < 255 x "+HI+" > 0 255 x "+LO+" - 255 "+HI+" "+LO+" - / * - ? ?")
will create a mask where pixels <=24 get white, pixels >48 get black, and a soft transition inbetween.

Having a mask, you can combine original and the "dark filtration":
input = Whatever

LO = string( 24 )
HI = string( 48 )

darkmask = input.yv12lut("x "+LO+" < 255 x "+HI+" > 0 255 x "+LO+" - 255 "+HI+" "+LO+" - / * - ? ?")
darkmask = darkmask.FitY2UV()
dark_filter = input.YourSpecialDarkFilter()

MaskedMerge(input, dark_filter, darkmask, U=3,V=3)
Note: since the mask was build on the Y channel only (that is what was evaluated), the mask's luma channel is copied to the UV channels via FitY2UV. Doing so, MaskedMerge will also copy the chroma channels of the filtered clip to the input.


That's the basic approach. Is this what you're aiming for, or did you mean something other?

morsa
4th January 2006, 04:47
Ohh, guys, I love you both.
I finally was able to make something decent with binarize, and then denoising and blurring the mask, to avoid the hard edges.
But in facy I was at first interested about the "soft thesholding" thing and I wasn't able to figure out how to do it.
Basically what I'm doing is getting rid of the big blocks and crappy noise a DV "natural" "real live" stuff has on every dark/shadow area (It was shot at night at the street.
I'm applying MVdenoise1 script two times on the dark zone and then merging
(I like to think about it as "Shadow Smoother on Steroids").
If using Binarize, does the mask also applyes to U and V ?

Didée
4th January 2006, 04:56
It might contain something, but probably not much that would be of any use here. I'd go for copying the luma mask to UV. (At least for MaskedMerge - Overlay() i use so seldom that i forgot how it works in this respect :o )

edit: does MVDenoise work OK in those dark areas? Could be that all the fuzz that's going on in the darks spoils the motion estimation...

morsa
4th January 2006, 05:15
Ok, So I will work on scripting with the soft thresholding and YV12LUT
Ohh, MVDENOISE1 script is working perfectly and making wonders....
Blacks look way much better, increasing the overall percieved quality.I guess that decreasing saturation on them will give even better results.(I suppose it will give better contrast without changing luma levels)


PS: I'm thinking that one of this days many of us should get together and define the basis for a small and concise documentation about how to use all these things like overlay, masktools, MVtools, etc.
It is something that is used for lot of things but is not really well explained.
I think the best would be tutorial style...

Mug Funky
4th January 2006, 06:11
avs manual is a good start... it's actually really useful, especially for those internal functions that you've forgotten the usage for.

i for one would like to see avs used as the engine for a fully fledged NLE program - one that avoids pretty much all the problems of commercial ones (unnecessary recompression, stupid behaviour on audio, extreme slowness and frequent catastrophic crashes for instance). it'd be a big undertaking though. i'll probably make a start when i get round to learning C/C++/VC++...

if avs were used in this way people could graphically set their filters without having to worry about syntax.

*dreaming*

morsa
4th January 2006, 07:54
well, I was looking at it and it wasn't of much help........at least in this situation..
Well...



Note:I don't think that it is completely necessary to learn Vc++ to make it...
if it is an engine you can communicate with it in many ways.If it were working Premiere style it would be through scripting much the way it works right now!!
The hard part is producing a decent interactive GUI.
Premiere uses its own library for the GUI, that AFAIK, is defined through scripting too.
Maybe I'm getting dumber day after day, but that should be possible even with javascript....(kidding in some way).
Also, Premiere doesn't strictly recompress everything....
Avid expressDV does!!!! :)
Premiere EDL import is the worst thing I've ever seen.Even a school boy could have written a better one.
May be Adobe has a really big reason for making crap like that cause if not I should believe the people behind their products are completely stupid.
Anyway.Don't continue this here, or this thread will get trashed and I think it could be quite usefull for many others like me.

morsa
5th January 2006, 13:25
Didée:

What did you mean with this post?
http://forum.doom9.org/showthread.php?p=732664#post732664

I'm also interested about this method.
My cleaning of shadows is working quite nice.Anyway sometimes I'm getting some blocks at some places on some special situations.

EDIT1:

Ok.My quick and rough solution was replacing the MVDenoise1 script by your MCNR_simple2 script (Ozzy settings) and guess what.....Blocks seem to have gone away... :)

Didée
5th January 2006, 15:25
May I ask how your call of MVDenoise1() exactly looks like? Krieger had posted several versions, and to me none of them look like fitting ideally to your problem with dark areas.

To your question: problem is that with the available "easy" methods of motion compensated denoising you've always to make a tradeoff between

a) using defensive thresholds & settings - this will avoid artefacts, but reduce efficiency of denoising by so much that one could as well use more simple filtering

or

b) use more aggressive thresholds & settings - this will denoise efficiently, but will bring up artefacts as well, so that one is better off with using more simple filtering.

That's why I'm exploring different ways of reckognizing & handling the errors of motion compensation. This delivers wonderful results ... but is so slow that you're better off using more simple filtering. ;)

morsa
5th January 2006, 21:35
this was my last setting:

function mvdenoise1(clip,int "block"){
backward_vectors2 = clip.MVAnalyse(blksize=block, isb = true, lambda = 1000, delta = 2,truemotion=true, chroma = true)
backward_vectors1 = clip.MVAnalyse(blksize=block, isb = true, lambda = 1000, delta = 1,truemotion=true, chroma = true)
forward_vectors1 = clip.MVAnalyse(blksize=block, isb = false, lambda = 1000, delta = 1,truemotion=true, chroma = true)
forward_vectors2 = clip.MVAnalyse(blksize=block, isb = false, lambda = 1000, delta = 2,truemotion=true, chroma = true)
return clip.MVDenoise(backward_vectors2, backward_vectors1, forward_vectors1, forward_vectors2, tht = 10, thsad = 200 , thSCD2 = 100)
}

with thsad = 200 and thSCD2 at default it was giving me many artefacts