View Full Version : Smooth levels adjustment - how to convert Levels to yv12Lut ?
ADLANCAS
7th January 2007, 04:45
There´s a very interesting function to smooth levels that I´ve got from Didée/Zambeli:
http://forum.doom9.org/showthread.php?p=838551#post838551
The function that I used is similar to the original from Zambelli, as following:
Levels_Smooth(5, 255, 5, 236)
###___Smooth levels function adapted from Didee's PC2TV/Zambelli function___###
function Levels_Smooth(clip clp, int min_before, int max_before, int min_after, int max_after){
chroma = clp
pc2tv = clp.Levels(min_before, 1, max_before, min_after, max_after, coring=false)
pc2tvd=mt_lutxy(clp,pc2tv,"x y - 4 * 128 +","x y - 4 * 128 +","x y - 4 * 128 +",U=3,V=3)
mt_lutxy(clp,pc2tvd.removegrain(mode=19),"x y 128 - 4 / -","x y 128 - 4 / -","x y 128 - 4 / -",U=3,V=3)
MergeChroma(chroma)
}
When Zambelli posted that, Didée suggested some changes...
2.
Levels() changes luma and chroma simultaneously. While you have too wide luma, chroma seems fine, and must not be reduced in the same way as luma. You could replace the levels() call with a YV12Lut() that's working only on luma ... or simply copy chroma back at the end.
I´d like to implement such function replacing levels by yv12lut, but I really don´t know how to do that.
Could someone help me ?
foxyshadis
7th January 2007, 17:20
The equation for your levels is:
output = [(x - min_before) / (max_before - min_before)] * (max_after - min_after) + min_after
(because you have no gamma correction) so the postfix is:
y = x min_before - max_before min_before - / max_after min_after - * min_after +
which you need to convert into strings in order to insert it into your first lutxy. See any of Didée's scripts for the general method.
btw, you might want to go with mt_lut(xy), just because you can simplify some things - you only need the expression once instead of 3 times.
Didée
7th January 2007, 18:53
Condensed & minimalized for the given case, it would be
function Levels_Smooth(clip clp, int min_before, int max_before, int min_after, int max_after)
{
min0 = string( min_before )
max0 = string( max_before )
min1 = string( min_after )
max1 = string( max_after )
exprY = "x x "+min0+" - "+max0+" "+min0+" - / "+max1+" "+min1+" - * "+min1+" + - 4 * 128 +"
levelD = mt_lut(clp, yexpr=exprY, U=1,V=1)
mt_lutxy( clp, levelD.removegrain(19,-1), yexpr="x y 128 - 4 / -", U=2,V=2)
return( last )
}
I would have made a "general" smooth-Levels function at some time, but there are some issues:
- the smoothing is done by a simple kernel blur. This works quite okay if pixels changes aren't too drastic, but it would be much better if it was done in a similar way like e.g. GradFun2db is doing its work
- to achieve (a bit) more precision with the simple kernel blur, the difference of the "raw" levelling is multiplied by 4 before blurring, and divided by 4 again after the blur. This achieves more prcision in parts where the levelling did only small changes (+/- 1/2/3), BUT it will overflow if there were some big pixel changes. In particular, such multiplying should not be used when a gamma adjustment is done, since this might cause sufficiently big pixel changes.
Again, a GradFun2db-style mode of operation would be better.
This probably could be rated "playground for plugin-writer with spare time" ;)
Lastly, there still is the chroma issue ... touching chroma not at all isn't always the right thing to do. But it doesn't make sense to just "somehow" change chroma, when luma is changed ... needed is, imo, to change chroma according to the changes that happened to luma. But then, instead of figuring some wild luma->chroma linking, propably it'd be better to just work in RGB ... ;)
Soulhunter
7th January 2007, 19:13
I think you can get a smooth histogram by using tweak3 (http://soulhunter.chronocrossdev.com/data/tweak3.zip) which is basically the original tweak + dithering... If you dont need gamma correction you can make a simple levels() function from it, no?
Bye
Didée
7th January 2007, 19:32
Well, maybe yes, maybe not ...
I don't want to go into ranting again, but once more, it's this black box principle:
"Try this. No need to tell you what exactly it does ... It does something, see if you like it."
Moreover, the ReadMe even says: "Same as Avisynth's Tweak()."
How should one even come to the idea that it does dithering, when the "documentation" says it's the same ... ?
If the don't want to publish sources - okay. But for the sake of heaven, what's so bad about a short description what is happening at all?
His ReadMe's never were golden, but in former times there was at least a chance to figure what basically is happening. Nowadays, his plugins were the blackest of black boxes to juggle with my pixels.
Soulhunter
7th January 2007, 20:14
No, today his plugins come completely without a readme... The short "Usage: Link to original tweak" is from me so the user knows the params are still the same... But you are right, I will add a short description with the next update of my website! :]
Thanks n' Bye
ADLANCAS
7th January 2007, 20:56
Thanks for all suggestions!
In particular, such multiplying should not be used when a gamma adjustment is done, since this might cause sufficiently big pixel changes.
I don´t intend to change gamma;)
I would have made a "general" smooth-Levels function at some time, but there are some issues:
I see what you mean, but in "general", it´s a nice function that has more advantages than disadvantages.
IanB
8th January 2007, 05:58
For YUV data with Tweak(), Brightness and Contrast adjust the bias and gain of the luma channel only. Hue and Saturation adjust the chroma channels only.yout = int((yin - 16) * cont + bright + 16.5)
zambelli
9th January 2007, 23:52
- the smoothing is done by a simple kernel blur. This works quite okay if pixels changes aren't too drastic, but it would be much better if it was done in a similar way like e.g. GradFun2db is doing its work
What kind of changes would you consider too drastic? Something along the lines of Levels_Smooth(0,255,116,144)? Or are you talking about luma differences between pixels within the image?
Adlancas, thanks for reviving this function. It's a pretty useful one, at least for me. Generic TV-->PC luma scaling rarely works for me - I typically have to manually adjust the luma range, and preserving a smooth luma range is beneficial.
Didée
10th January 2007, 09:56
What kind of changes would you consider too drastic? Something along the lines of Levels_Smooth(0,255,116,144)? Or are you talking about luma differences between pixels within the image?
With "too drastic change" I mean anything that changes a pixel by more than +/- 32. The achieved initial difference is stored in a single diff map, which can hold only changes of +/- 127. Divided by the "accuracy" multiplier of 4, that leaves an available range of +/- 32. Yes, it's a very simple function.;)
Quick estimate: as it is, things would be safe up to a gamma factor of 2.0. For bigger gamma factors, to avoid overflow the divider would need to be reduced.
Splitting the difference map in two full-range maps is another possibility.
... and making a plugin would be the best possibility. :)
vBulletin® v3.8.5, Copyright ©2000-2012, Jelsoft Enterprises Ltd.