View Single Post
Old 11th August 2012, 15:56   #98  |  Link
frustum
Registered User
 
Join Date: Sep 2010
Location: Austin, TX
Posts: 40
I've been away from avisynth for a long time, and as such, haven't even read many of the recent comments. I have scanned them, but I need to reread more of the whole stream and think about it. In a side email to videoFred about autolevels, I wrote the following, but by the end decided to ask everyone their thoughts.

Stoffal, "ignore" ignores the specified fraction of highest and lowest luma pixels of the scene before taking statistics and deciding how much to adjust luma. Just like in sporting events where they toss out the highest and lowest results from the panel of judges before averaging the rest, "ignore" is a way to prevent a few outliers from throwing off the processing for the entire frame.

I'll probably spend some time trying to improve autolevels in the coming weeks. In the original autolevels, the Y channel would get modified, but the UV channels would be untouched. However, mathematically, that isn't right. UV really isn't an independent color space, just a linear combination of RGB. To make it concrete, if you have these two rgb colors:

$804040
$C06060

both should have the same color, but the second one is 50% brighter (ignoring any gamma which might happen later) as r,g,b are each scaled by 1.5. But the YUV equivalents are

r=128 (0x80), g= 64 (0x40), b= 64 (0x40)
y= 83 (0x53), cr=160 (0xa0), cb=117 (0x75)

r=192 (0xc0), g= 96 (0x60), b= 96 (0x60)
y=125 (0x7d), cr=176 (0xb0), cb=112 (0x70)

You can see that the cr and cb components are affected by scaling RGB, even though they are different brightnesses of the same hue.

So, even though it seems mathematically correct to scale the UV as the brightness changes, I do see that sometimes it makes slight color shifts and magnifies them especially when autolevels is stretching the histogram a lot, and people are objecting to that. But if I don't scale at all, as things are made brighter, they will lose saturation, and things which are made darker will gain saturation.

Do you have any idea of how to deal with this?

For instance, I could add a chroma_strength parameter; set it to 0 and the UV values aren't changed at all, and would be the default so that we have the same behavior as the original autolevels. If you set chroma_strength to 1.0, then you get the current 0.6 autolevels behavior where things are scaled according to what the math suggests is correct. If you set it in between, then you get the weighted average between these two cases.

And/Or I could add chroma_scale_limit, and perhaps a luma_scale_limit, as parameters. It would prevent autolevels from scaling UV and Y, respectively, more than the specified factor. For a scene with a very narrow range of Y values, currently it gets stretch all the way out to 0..255 (or 16..235). Setting luma_scale_limit to 2.0 would prevent autolevels from scaling Y by more than the range 0.5 to 2.0. For instance, I just got some film back and the leader, which is nominally gray but has almost no contrast, turns into a rainbow because the slight UV variations get scaled dramatically at the same time the luma is getting scaled from a range of (60..78) to (16..235) or whatever.

And since this filter provides both autolevels() and an autogamma() interface, I guess I would add a gamma_scale_limit along the same lines.

And if we are now talking about having a transfer function mapping the mathematically correct scaling to something more modest, should it be a simple linear ramp with clamping, or should it have a soft transition to the limit-clamped range? This filter already has too many parameters.

An idea I mentioned before that circumvents some of this is to not do processing in YUV space at all, but to map RGB or YUV to a better color space where chroma really is independent of luma (or whatever it is called in that color space), stats are taken, luma is adjusted, then map back to RGB or YUV.

I also noticed that 2.6 added a dither parameter to levels(), so I should probably add the same feature to autolevels().
frustum is offline   Reply With Quote