Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Usage

Reply
 
Thread Tools Search this Thread Display Modes
Old 18th July 2004, 18:23   #1  |  Link
Didée
Registered User
 
Join Date: Apr 2002
Location: Germany
Posts: 5,390
Some finger exercises with image levels

Lately, the discussion about the different gamma curves of TV sets and PC monitors came up again. This reminded me of some gamma tricks I'm used to occasionally apply in image processing. And now I even found time set it up in Avisynth

The most-faced problem is: video appears "too dark" on PC monitors.
The usual solution is: raise black level, or slope-up the gamma curve.

Both make the details in very dark areas better visible - but both create the usual ugly "washed-out" effect at the same time.

A more pleasing solution is, to adjust the gamma curve for dark areas more strongly than for bright areas.

Functions:
(MaskTools.dll is needed. >= v1.5.5 is recommended.)

edit 07 dec 2004: all functions updated to latest MaskTools' semantics (currently v1.5.5)

Code:

function Ylevels(clip clp, int a, float gamma, int b, int c, int d)
       { wicked="x "+string(a)+" - "+string(b)+" "+string(a)+" - / 1 "+string(gamma)+" / ^ "+string(d)+" "+string(c)+" - * "+string(c)+" +"
        # Reminder: Yexpr = "x a - b a - / 1 gamma / ^ d c - * c +"
        # return( clp.subtitle(wicked) )
         return( clp.YV12LUT(Yexpr = wicked, U=2,V=2) )  
         }
         
function YlevelsG(clip clp, int a, float gamma, int b, int c, int d)
       { wicked = gamma > 1.0
          \      ? "x "+string(a)+" - "+string(b)+" "+string(a)+" - / 1 "+string(gamma)+" / ^ "+string(d)+" "+string(c)+" - * "+string(c)+" + x * x 255 x - * + 255 /"
          \      : "x "+string(a)+" - "+string(b)+" "+string(a)+" - / 1 "+string(gamma)+" / ^ "+string(d)+" "+string(c)+" - * "+string(c)+" + 255 x - * x x * + 255 /"
         return( clp.YV12LUT(Yexpr = wicked, U=2,V=2) )  
         }
         
function YlevelsS(clip clp, int a, float gamma, int b, int c, int d)
       { wicked="x "+string(a)+" - "+string(b)+" "+string(a)+" - / 1 "+string(gamma)+" / ^ "+string(d)+" "+string(c)+" - * "+string(c)+" + x 162,97466 / sin 255 * * x 255 x 162,97466 / sin 255 * - * + 255 /"
         return( clp.YV12LUT(Yexpr = wicked, U=2,V=2) )  
         }
All functions are called the same way as AviSynth's "levels()" command, except for the coring parameter. Coring is not available with the Ylevels() functions. They'll always work on the full [0,255] value range.

Ylevels() is a simple replacement for Avisynth's internal levels() command, with a few neat differences:

- processes only luma --> faster, better preservation of color saturation
- no clipping: Ylevels(40,1.0,220, 40, 220) will not clip the output to [40,220] as levels() does. Values below 40 / above 220 will be scaled accordingly to the correct vales. This means, one can use any values for IN_LOW, IN_HIGH as "control points" without getting the input clipped at those values.


But that's not the deal.


YlevelsG() and YlevelsS() apply the given levels conversion by 100% @ Luma==0, by 0% @ Luma=255, and accordingly in-between.

YlevelsG() does a linear sweep (G = Gradient)
YlevelsS() does a sine sweep (S = yes, exactly )

Try those with gamma values 1.5 ~ 4.0. I suppose some will like them.

YlevelsG (not YlevelsS) does "inverse" scaling for gamma values < 1.0, but that's not that great. It's just for completeness.


But that's not all, yet.


While building the LUT expression for the sine sweep , at one point I accidentially swapped some things, and the result was ...

YlevelsC()

For this one, 2.0 < gamma < 16.0 is reasonable.

No, I won't explain it - just try & enjoy it
Code:

function YlevelsC(clip clp, int a, float gamma, int b, int c, int d)
       { wicked="x "+string(a)+" - "+string(b)+" "+string(a)+" - / 1 "+string(gamma)+" / ^ "+string(d)+" "+string(c)+" - * "+string(c)+" + 255 x 162,97466 / cos 255 * - * x x 162,97466 / cos 255 * * + 255 /"
         return( clp.YV12LUT(Yexpr = wicked, U=2,V=2) )  
         }
Closing comment:

If these functions should be used for encoding or not, depends on the source. I would be carefully, at least ...

But:

These functions are pretty fast! (Manao: thankyouthankyouthank...)
- So they can be nicely used in the "Avisynth" section of ffdshow ...


Have fun


- Didée
__________________
- We´re at the beginning of the end of mankind´s childhood -

My little flickr gallery. (Yes indeed, I do have hobbies other than digital video!)

Last edited by Didée; 7th December 2004 at 11:53.
Didée is offline   Reply With Quote
Old 18th July 2004, 20:16   #2  |  Link
malkion
Registered User
 
Join Date: Feb 2004
Posts: 156
Thanks Didee!

(now about that msu-sharpening script u developed, heh, just send it)
malkion is offline   Reply With Quote
Old 18th July 2004, 20:25   #3  |  Link
Didée
Registered User
 
Join Date: Apr 2002
Location: Germany
Posts: 5,390
I'll post it when it's ready to be posted

- Didée
__________________
- We´re at the beginning of the end of mankind´s childhood -

My little flickr gallery. (Yes indeed, I do have hobbies other than digital video!)
Didée is offline   Reply With Quote
Old 18th July 2004, 20:51   #4  |  Link
malkion
Registered User
 
Join Date: Feb 2004
Posts: 156
Hey Didee, I like YlevelsG very much, except my CRT is kinda old, and the gamma is skewed. I set fddshow's luma offset from 50 to 60 just to watch vids. I even tried YlevelsG and Ylevels together, and I still get real time decoding. Not bad at all. But the full effect of YlevelsG is missed that way. Anyways, I can still use fddshow luma offset and YlevelsG together for a more brilliant picture. I'm about to try Ylevels first then YlevelsG to see if this option works...

There's so many options... hehe
malkion is offline   Reply With Quote
Old 21st July 2004, 15:23   #5  |  Link
jorel
Guest
 
Posts: n/a
Didée, thank you very much
i'm caming from http://forum.doom9.org/showthread.ph...0&pagenumber=3 (picture too dark with avisynth script thread),i'm testing the results.

for who need the link to download masktools:
http://jourdan.madism.org/~manao/
  Reply With Quote
Old 23rd July 2004, 20:40   #6  |  Link
jorel
Guest
 
Posts: n/a
@ Didée and all :
no luck here, the image still dark and changing the matizes(more green) comparing with the dvd(cartoon) source. anyone had good results? Didée, suggestions or differents adjusts in the scrip? thanks!....i lost my will to encode, we're loosing quality! ...waiting good solutions or hints.
  Reply With Quote
Old 24th July 2004, 14:05   #7  |  Link
Didée
Registered User
 
Join Date: Apr 2002
Location: Germany
Posts: 5,390
Speaking of above functions, perhaps you'd need it to "bite" more in the darks only. Technically no problem, the distribution can be made at free will.

However, the following is YlevelS() with still careful settings:



To my eyes, that's effective.


- Didée
__________________
- We´re at the beginning of the end of mankind´s childhood -

My little flickr gallery. (Yes indeed, I do have hobbies other than digital video!)
Didée is offline   Reply With Quote
Old 24th July 2004, 17:57   #8  |  Link
morsa
the dumbest
 
Join Date: Oct 2002
Location: Malvinas
Posts: 494
Amazing!!!!!!!!!!!!!!!!!!!!!!!!!!!
Wouldn't be better to turn this directly into a plug-in??
morsa is offline   Reply With Quote
Old 24th July 2004, 18:03   #9  |  Link
Manao
Registered User
 
Join Date: Jan 2002
Location: France
Posts: 2,856
No, it wouldn't be faster, and it would lose all the tweakability of YV12LUT. Didee's functions are wrappers to make the use of YV12LUT easier in these kind of levels filtering, and for that, avs scripts are perfectly fit.
Manao is offline   Reply With Quote
Old 24th July 2004, 18:06   #10  |  Link
LigH
German doom9/Gleitz SuMo
 
LigH's Avatar
 
Join Date: Oct 2001
Location: Germany, rural Altmark
Posts: 4,891
By now, I was quite satisfied with the results of
Code:
Levels(0,1.4,255,8,248)
Tweak(sat=1.2,cont=1.1)
I'll be interrestend in comparing the results!
LigH is online now   Reply With Quote
Old 24th July 2004, 19:01   #11  |  Link
jorel
Guest
 
Posts: n/a
thank you boys....i did more tests.
differents results and reasons:

from vob in vdubmod:

http://img20.exs.cx/img20/6633/a105.jpg

using .avs script (source only)from dvd2avi project:

http://img20.exs.cx/img20/802/b98.jpg

little differences cos here was with xvid decompressor in vdub mod!

now here,big differences:
from vobs in vdubmod:

http://img34.imageshack.us/img34/5236/vobs.jpg

using .avs script (source only)from dvd2avi project:

http://img39.imageshack.us/img39/7083/pcscale.jpg

great differences cos was using ati decompressor in vdubmod(file information).

then,(correct me please) the differences in vdub depend of the decompressor used to show the pictures (like in vdub file informations).
now my doubt: if i'm using the ati the image is dark,if using xvid "seems" equal ..... what is working when encoding in CCE(D2S)?
  Reply With Quote
Old 24th July 2004, 19:52   #12  |  Link
Didée
Registered User
 
Join Date: Apr 2002
Location: Germany
Posts: 5,390
Quote:
Originally posted by LigH
By now, I was quite satisfied with the results of
Code:
Levels(0,1.4,255,8,248)
Tweak(sat=1.2,cont=1.1)
I'll be interrestend in comparing the results!
Okay.



What I see here, is:

One picture where detail in dark areas is clearly visible, but that suffers from contrast over the full range, making the overall appearance somewhat dull,
and one picture where detail in dark areas is clearly visible, and that has good contrast over the full range, making the overall appearance vivid.

q.e.d.

- Didee


[edit]

*damnit*

Sorry for the misspelling, LigH.
__________________
- We´re at the beginning of the end of mankind´s childhood -

My little flickr gallery. (Yes indeed, I do have hobbies other than digital video!)

Last edited by Didée; 24th July 2004 at 19:56.
Didée is offline   Reply With Quote
Old 25th July 2004, 12:16   #13  |  Link
LigH
German doom9/Gleitz SuMo
 
LigH's Avatar
 
Join Date: Oct 2001
Location: Germany, rural Altmark
Posts: 4,891
Well - a little tweaking of the Levels(gamma) and Tweak(sat,cont) parameters may lead to even better results than my default ones. But finally: If your Ylevels or the Levels/Tweak combo are more or less successful, is beyond my ability of recognition. Other people may be more trained in spotting differences.
LigH is online now   Reply With Quote
Old 25th July 2004, 18:57   #14  |  Link
Didée
Registered User
 
Join Date: Apr 2002
Location: Germany
Posts: 5,390
It gets clearer with some curves. The following curves are not mathematically exact - they're quickly free-handed, but give the idea.

A plain gamma correction looks like this:


We get a strong brightening effect over the full range. But from about 35% of the available range, we start loosing contrast (steepyness of curve gets < 1).

Ylevels simply blends the normal gamma curve, weightened with the inverse of the input's brightness. The result is similar to this:


By this weightening, the brightening of the dark areas is still achieved. But here, the cost of the additional levels that were assigned to the darks is distributed more equally over the remaining ranges: the curve's steepyness goes only a little below '1', plus the curve's overall deviation from y=x is much smaller.

You can tweak your levels().tweak() - combo until you get blue in the face: you'll never get the same effect. Starting with normal levels(), contrast in the upper 65% is lost. Then, you can get it back
- if at all, only with loss. Expanding the compressed ranges again will lead to posterization, because actually values got lost during gamma correction
- not at all with tweak() - (not really), since its contrast parameter works symetrically to Y=127.


Hey, I don't want to sell anything here

But the difference is really easy to spot, in my opinion:

interleave( levels(...).tweak(...), Ylevels(...) )

Flip this back 'n forth, and don't say you see no difference


- Didée
__________________
- We´re at the beginning of the end of mankind´s childhood -

My little flickr gallery. (Yes indeed, I do have hobbies other than digital video!)

Last edited by Didée; 25th July 2004 at 19:10.
Didée is offline   Reply With Quote
Old 25th July 2004, 19:24   #15  |  Link
scharfis_brain
brainless
 
scharfis_brain's Avatar
 
Join Date: Mar 2003
Location: Germany
Posts: 3,605
hehe, I was using Photoshops curves to build a curve, that improved the image, and then used RGBLut

(the curves mostly seem to be similar to your one)
__________________
Don't forget the 'c'!

Don't PM me for technical support, please.
scharfis_brain is offline   Reply With Quote
Old 25th July 2004, 19:52   #16  |  Link
Didée
Registered User
 
Join Date: Apr 2002
Location: Germany
Posts: 5,390
RGBLUT ony a YUV souce ... didn't you get some banding effects in areas of low luma? You're getting gaps through the YUV->RGB conversion (look at the histogram in Photoshop before-after), are spreading these gaps through gamma adjustment, and are left with the gaps after backconversion (again look at the histogram).

I don't pretend this springs to the eye obviously, but generally it's just like that.

- Didée
__________________
- We´re at the beginning of the end of mankind´s childhood -

My little flickr gallery. (Yes indeed, I do have hobbies other than digital video!)
Didée is offline   Reply With Quote
Old 25th July 2004, 19:56   #17  |  Link
scharfis_brain
brainless
 
scharfis_brain's Avatar
 
Join Date: Mar 2003
Location: Germany
Posts: 3,605
hehe, but since TMPEGenc only accepts RGB input, that isn't a big problem, isn't it?
__________________
Don't forget the 'c'!

Don't PM me for technical support, please.
scharfis_brain is offline   Reply With Quote
Old 7th December 2004, 12:13   #18  |  Link
Didée
Registered User
 
Join Date: Apr 2002
Location: Germany
Posts: 5,390
All Ylevels()-functions updated to the latest MaskTools' semantics (needs to specify "U=2,V=2" to carry the original color planes through).
__________________
- We´re at the beginning of the end of mankind´s childhood -

My little flickr gallery. (Yes indeed, I do have hobbies other than digital video!)
Didée is offline   Reply With Quote
Old 6th November 2006, 05:55   #19  |  Link
Jeremy Duncan
Didée Fan
 
Jeremy Duncan's Avatar
 
Join Date: Feb 2006
Location: Canada
Posts: 1,079
Didée,

I notified the FFdshow developers that the FFdshow Levels tab uses your code wrong. That it doesn't work as you've shown in this thread.

Here's the link:
Link

I asked them to look at this thread and implement the Levels you made in this thread into FFdshow properly.
Jeremy Duncan is offline   Reply With Quote
Old 6th November 2006, 13:53   #20  |  Link
Alain2
Registered User
 
Join Date: May 2005
Posts: 236
Talking about ylevels, Didee I sent you a pm on this subject back in June, but you never replied..
Alain2 is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 16:54.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2017, vBulletin Solutions Inc.