Avisynth: Color Correction & Improvement

To get a bit more experience with avisynth I read a lot of articles and howtos. I think the most important thing when restoring (repairing, enhancing, whatever you like to call it) videos right after de-interlacing (if interlaced) is color correction. So let’s take a look at colors and avisynth.

There are three things, which can be tuned easily to provide better colors: Brightness, Contrast, Saturation. Going a bit deeper, you could also handle the color-channels independently, for example if you convert the clip to RGB you could higher the saturation for the red channel, for the green channel and/or for the blue channel (so if you think theres too much blue, you’d just limit blue a bit without touching red and green). Apart from that, there are some more techniques which might be useful. For example color-enhancement – Sometimes you got dark parts in a picture (nearly black) – Such parts contain some information, for example there might be a table but you won’t see it. If you higher gamma/brightness you’ll start to see it. So yes, it’s there, even if you don’t see it. You got two options: a) you’re increasing brightness/gamma just in that black part to see more of the frame or b) you’re making it even darker (more black) and blur it a bit (to remove such information which you won’t see anyway) to enhance compressibility. So, as you can see, there’s a lot you can do to colors in a video. And believe me, that’s not all.


At a PC you got a range from 0 to 255 at the YUV signal. On a TV these are limited, at the luma component from 16 to 235 and for the chroma component 16 to 240. I don’t think that this is still important today, however, just to make sure (Because they’re causing problems with some tv sets / and well it’s an legacy thing out of analogue times), we should limit this accordingly. However, let’s take a look at some example:


You can see in the first histogram (the top thing) that there are brown borders on the left and on the right, these define the „invalid“ parts. As you can also see on the left, there’s a bit in the invalid part (marked yellow), and also a bit on the right (not that easy to see).




Limiter(16, 235, 16, 240) 


The ColorYUV example leads to a more bright image / less saturation, we can correct this later. You can see that the histogram changed „noticable“ with coloryuv – With Limiter the invalid ranges are just removed and nothing else changed. I’d prefer ColorYuv. However – Whatever you did, we got now good values for a TV (Always assumed, you want to be able to watch that video flawlessly on your TV)

Brightness & Contrast

As you can see on the histogram above (the coloryuv one) the white doesn’t start at the left brown bar. We need to change that by tuning off_y of ColorYUV. In case you’re using this to manually tune the colors, you don’t need to do the conversation (pc->tv) above. So start by doing:

ColorYuv(off_y=6, gain_y=0) 

and adjust off_y till there’s no yellow parts in the brown bar anymore. This should look like this:
Now you can see that a lot goes into the right brown bar, so we need to limit it there, too, you can do that by tuning gain_y, for example (the white stuff should always be between the brown bars):

ColorYuv(off_y=6, gain_y=-12)

This looks in my source like this:


Saturation / Hue

Changing the Saturation and Hue is way easier, though i’d recommend to not deal with it, except you got a very bad source. Because let’s imagine you’re noticing that some picture is way too red. You could now limit the red color a bit, by doing so „every“ red would be limited in your movie, so some parts might look worse than before. Also highering red – Faces might look weird. So this is something you should try to avoid in my humble opinion. However:

You could use TweakColor to work on the colors. For example:

# just a wrapper around TweakColor not useful at all
function pseudoColors(clip input)
    # magenta: 20 - 80 (center: 50) - higher saturation of magenta with 1.2
    TweakColor(input, startHue=20, endHue=80, sat=1.2)
    # red: 80 - 140 (center: 110) - lower saturation of red with 0.5
    TweakColor(startHue=80, endHue=140, sat=0.5)
    # yellow: 140 - 200 (center: 170) - don't do anything
    TweakColor(startHue=140, endHue=200, sat=1.0)
    # green: 200 - 260 (center: 230) - higher green by 2.0
    TweakColor(startHue=200, endHue=260, sat=2)
    # cyan: 260 - 320 (center: 290) - make cyan greyscale/filter it out
    TweakColor(startHue=260, endHue=290, sat=0)
    # blue: 320 - 20 (center: 350) - do nothing
    TweakColor(startHue=320, endHue=20, sat=1)

    return last

Instead of „sat“ you might also use bright cont and hue. For example: There’s something yellow in your video, which should be green. So you want to shift the hue of „yellow“ to „green“. Negative values in „hue“ will do that. For example (not tested):

# selected yellow with start and endhue, and shifting hue to -50, negative values -> green, positive values -> red
TweakColor(input, startHue=140, endHue=200, hue=-50)

You see, there’s much you can do, you could even just remove some annoying colors. The usual way of doing such tuning is watching the video and looking for parts which seems to have wrong colors. Tuning them, and making sure it doesn’t make any other frame worse.


However, the above stuff needs to be applied to every frame; you need to find out the brightest and the darkest frame in the whole movie, and tune the settings accordingly. so with these settings you can make some frames too bright and some not bright enough; something which does this automatically would be cool, hm? Well, i’m using „autolevels“ for that, which does a quite good job if you feed it with many frames. It’s default value (5) isn’t very useful in the source i’m using here, while a value of 50 gives very good results. Take a look at the histogram:


Autolevels got a few problems though; due to the automatism weird light(ning) effects occur sometimes and on real dark frames like a star-field it makes the whole black into grey – So while it might be good for some sources, for most of the sience-fiction movies you probably have, you should look at it skeptical 🙂


there are three other plugins, which might be useful to you, when dealing with colors:

  1. HDRAGC – Enhances Shadows (I never got good settings with it for my sources)
  2. ExpLabo – Can be used for Color Correction (haven’t tried it yet)
  3. FilmYlevels – Gives a filmish look (haven’t tried it yet)

Haven’t tried it yet means, the screenshots looked promising, but well as you might (or should) know, screenshots are.. hehe. Usually optimized for a specific source; it’s simply not a good way to say something’s good or bad just because of a awesome good screenshot.

Update: I tried ylevels and flimylevels today, it seems those things are most useful on anime and not really useful on „normal“ video, because of the light-changes. If you use one of those (also hdragc, even if its lower there) it might well be that you notice a fading light from frame to frame (which looks bad) with autolevels the frames get a bit over-saturated, too – So finding good values is not that easy. autolevels has the advantage of using many frames, thus you can reduce the noticeable lighting. So.. Well, you have to check yourself. For very bad old sources this might be good, for anime this might be good also, for everything else.. Be skeptical and use your eyes.

Making White really White

At one old movie i noticed that they used a white paper to simulate „lightning“ the thing which occurs at a thunder. So they hold a white paper in front of the camera for one or two frames – At the bottom right edge this was noticable because there’s a curve. Here’s a screenshot:


So instead of using that it might be useful to turn such a frame into real white. Like saying: If 95% of the Screen is white, make it real white or something like that. Kuukuunen (thanks once again!) helped me a bit to get something which is doing that. There’s also a Thread which he wrote regarding „Understanding YUV, Luma, Luminance“ because there are some problems with greyscale -> i linked his thread at the bottom. Here’s by the way the function which would do the above:

function turnWhite(clip v, int "threshold")
    threshold = default(threshold, 235)
    conditionalfilter(last, blankclip( v, pixel_type="YV12", color_yuv=$FF8080 ), v, "averageluma()", ">", string(threshold))

play around with threshold and test for yourself. A value of 200 did what i wanted at the frame, i guess highering this would be possible, haven’t tried yet. Try to make the threshold as high as possible to not cause any false-positives. Whether thats useful or not you have to decide yourself; in fact as those are only 1-2 frames, you wouldn’t notice in normal motion. You should only notice this in slowmotion (like playing it with mplayer and using the dot to look at it frame by frame) however, it MIGHT enhance compressibility.

Other useful information

No Comments

Post a Comment