View Full Version : Color temperature change
Stormborec
26th November 2014, 19:28
Exists a plugin or a script, which could change the color temperature?
I've got a TV, where isn't enough of settings. On the screen are faces and grass too yellow, and sky is rather gray than blue.
If I add blue, then sky is OK, but faces are violet, and grass is rather blue than green.
When I add green, then the colors of faces and sky are worse yet.
When I add red, then grass is still the more yellow and sky is violet.
Stormborec
26th November 2014, 19:50
I'm playing with colorYUV and ColorMill (in RGB), but the results aren't satisfactory (like I wrote before).
raffriff42
26th November 2014, 22:42
I wrote a script that does a fair job - "CheapColorTemp"
http://forum.doom9.org/showthread.php?t=170309
To emulate color temp shift, you normally adjust offset_mid only,
using offset_lo to to correct the black balance if needed,
and offset_hi to to correct the white balance.
(MaskTools (http://avisynth.nl/index.php/MaskTools2)is required)
#######################################
### emulate color temperature changes in three luma ranges
##
## @ offset_x - arbitrary units; <0 means lower temp (warmer colors)
## (range -50 to +25; default 0)
##
function CheapColorTemp(clip C,
\ int offset_lo, int offset_mid, int offset_hi)
{
Assert(IsClip(C) && C.IsYUV, "CheapColorTemp: source must be YUV")
offset_lo = Min(Max(-50, offset_lo), 25)
offset_mid = Min(Max(-50, offset_mid), 25)
offset_hi = Min(Max(-50, offset_hi), 25)
return C.ColorYUVx3(
\ off_u_lo =offset_lo, off_v_lo =Round(-0.7*offset_lo),
\ off_u_mid=offset_mid, off_v_mid=Round(-0.7*offset_mid),
\ off_u_hi =offset_hi, off_v_hi =Round(-0.7*offset_hi))
}
#######################################
### apply ColorYUV U & V offsets to three luma ranges
##
## @ cont_x, off_x - see ColorYUV
## @ showmasks - if true, show original + 3 masks in quad split
##
function ColorYUVx3(clip C,
\ float "off_u_lo", float "off_u_mid", float "off_u_hi",
\ float "off_v_lo", float "off_v_mid", float "off_v_hi",
\ bool "showmasks")
{
off_u_lo = Float(Default(off_u_lo, 0.0))
off_u_mid = Float(Default(off_u_mid, 0.0))
off_u_hi = Float(Default(off_u_hi, 0.0))
off_v_lo = Float(Default(off_v_lo, 0.0))
off_v_mid = Float(Default(off_v_mid, 0.0))
off_v_hi = Float(Default(off_v_hi, 0.0))
showmasks = Default(showmasks, false)
C_lo = C.ColorYUV(
\ off_u=off_u_lo, off_v=off_v_lo)
C_mid = C.ColorYUV(
\ off_u=off_u_mid, off_v=off_v_mid)
C_hi = C.ColorYUV(
\ off_u=off_u_hi, off_v=off_v_hi)
return MergeLMH(C, C_lo, C_mid, C_hi, showmasks=showmasks)
}
# http://forum.doom9.org/showthread.php?p=1691736#post1691736
#######################################
### merge Lo, Mid, Hi clips based on clip "C" luma
##
## @ xover_x - aproximate 50% luma blend between ranges
## default 102 (40%), 191 (75%)
## @ showmasks - if true, show original + 3 masks in quad split
##
function MergeLMH(clip C, clip "C_lo", clip "C_mid", clip "C_hi",
\ float "xover_lomid", float "xover_midhi",
\ bool "showmasks")
{
xlo = Min(Max( 0, Default(xover_lomid, 102)), 127) * 3.0 / 256
xhi = Min(Max(128, Default(xover_midhi, 191)), 255) * 3.0 / 256
showmasks = Default(showmasks, false)
## (mt_lutxyz too slow; use mt_lut x3)
mask_lo = C.mt_lut(
\ yexpr="x -0.01 * "+String(xlo)+" + 256 * ",
\ u=-128, v=-128)
mask_hi = C.mt_lut(
\ yexpr="1 x -0.01 * "+String(xhi)+" + - 256 * ",
\ u=-128, v=-128)
mask_mid = mt_lutxy(mask_lo, mask_hi,
\ "x y + -1 * 256 + ",
\ u=-128, v=-128)
R = C
R = (!IsClip(C_lo)) ? R : R.Overlay(C_lo, mask=mask_lo)
R = (!IsClip(C_mid)) ? R : R.Overlay(C_mid, mask=mask_mid)
R = (!IsClip(C_hi)) ? R : R.Overlay(C_hi, mask=mask_hi)
return (showmasks==false) ? R
\ : StackVertical(
\ StackHorizontal(C, mask_lo),
\ StackHorizontal(mask_mid, mask_hi)
\ ).BilinearResize(C.Width, C.height)
\ .Subtitle("Low", align=9)
\ .Subtitle("\nMid", align=4, lsp=0)
\ .Subtitle("\nHigh", align=6, lsp=0)
}
Stormborec
27th November 2014, 17:24
Thanks, that's what I was looking for.
I don't understand exactly, where is function in the script, which calculates the values, that are in curves of the graph of black body ... such a script should be in the "list of external plugins" - there is no plugin for change of color temperature
Stormborec
27th November 2014, 17:46
It doesn't work to me ... "invalid arguments to function CheapColorTemp"
I tried:
imagesource("z4xkepN.jpg").converttoyv12
CheapColorTemp(offset_mid=1)
or
c=imagesource("z4xkepN.jpg").converttoyv12
CheapColorTemp(offset_mid=1)
Stormborec
27th November 2014, 17:56
Shouldn't there be something like "last" or "input" instead "clip C"?
Jenyok
27th November 2014, 18:45
It doesn't work to me ... "invalid arguments to function CheapColorTemp"
I tried:
imagesource("z4xkepN.jpg").converttoyv12
CheapColorTemp(offset_mid=1)
or
c=imagesource("z4xkepN.jpg").converttoyv12
CheapColorTemp(offset_mid=1)
.
Tried so...
.
c=imagesource("z4xkepN.jpg").converttoyv12
CheapColorTemp(c, 1, 1, 1)
.
You need to call CheapColorTemp() function with three integer arguments. Integer "1" is for example.
.
#######################################
### emulate color temperature changes in three luma ranges
##
## @ offset_x - arbitrary units; <0 means lower temp (warmer colors)
## (input range is unlimited, but is normally around -20 to +20; default 0)
##
function CheapColorTemp(clip C,
\ int offset_lo, int offset_mid, int offset_hi)
{
Assert(C.IsYUV, "CheapColorTemp: source must be YUV")
return C.ColorYUVx3(
\ off_u_lo =offset_lo, off_v_lo =Round(-0.7*offset_lo),
\ off_u_mid=offset_mid, off_v_mid=Round(-0.7*offset_mid),
\ off_u_hi =offset_hi, off_v_hi =Round(-0.7*offset_hi))
}
#######################################
### apply ColorYUV U & V offsets to three luma ranges
##
## @ off_x - see ColorYUV
## @ xover_x - aproximate 50% luma blend between ranges
## ( no reason to mess with this)
## @ showmasks - if true, show original + 3 masks in quad split
##
function ColorYUVx3(clip C,
\ float "off_u_lo", float "off_u_mid", float "off_u_hi",
\ float "off_v_lo", float "off_v_mid", float "off_v_hi",
\ float "xover_lomid", float "xover_midhi",
\ bool "showmasks")
{
off_u_lo = Float(Default(off_u_lo, 0.0))
off_u_mid = Float(Default(off_u_mid, 0.0))
off_u_hi = Float(Default(off_u_hi, 0.0))
off_v_lo = Float(Default(off_v_lo, 0.0))
off_v_mid = Float(Default(off_v_mid, 0.0))
off_v_hi = Float(Default(off_v_hi, 0.0))
xlo = Min(Max( 0, Default(xover_lomid, 102)), 127) * 3.0 / 256
xhi = Min(Max(128, Default(xover_midhi, 191)), 255) * 3.0 / 256
showmasks = Default(showmasks, false)
C_lo = C.ColorYUV(off_u=off_u_lo, off_v=off_v_lo)
C_mid = C.ColorYUV(off_u=off_u_mid, off_v=off_v_mid)
C_hi = C.ColorYUV(off_u=off_u_hi, off_v=off_v_hi)
## mt_lutxyz too slow!!
mask_lo = C.mt_lut(
\ yexpr="x -0.01 * "+String(xlo)+" + 256 * ",
\ u=-128, v=-128)
mask_hi = C.mt_lut(
\ yexpr="1 x -0.01 * "+String(xhi)+" + - 256 * ",
\ u=-128, v=-128)
mask_mid = mt_lutxy(mask_lo, mask_hi, "x y + -1 * 256 + ", u=-128, v=-128)
return (showmasks)
\ ? StackVertical(
\ StackHorizontal(C, mask_lo),
\ StackHorizontal(mask_mid, mask_hi))
\ .BilinearResize(C.Width, C.height)
\ .Subtitle("Low", align=9)
\ .Subtitle("\nMid", align=4, lsp=0)
\ .Subtitle("\nHigh", align=6, lsp=0)
\ : C.Overlay(C_lo, mask=mask_lo)
\ .Overlay(C_mid, mask=mask_mid)
\ .Overlay(C_hi, mask=mask_hi)
}
.
Stormborec
27th November 2014, 20:07
Super! Now it works ...
Are rusults of this script equivalent of: coloryuv(off_u=x,off_v=y)???
raffriff42
27th November 2014, 20:23
You need to give values for all arguments, as I didn't bother to make them optional with default values (sorry about that).
So to give a video a lower color temperature (more yellow, less blue), use something like CheapColorTemp(0, -5, 0)or for a higher color temperature (more blue), use something like CheapColorTemp(0, 5, 0)
Are results of this script equivalent of: coloryuv(off_u=x,off_v=y)???Yes, more or less; the problem with simply calling coloryuv is that the highlights and lowlights are altered more than they should be (ie, there is too much saturation in blacks and whites).
Jenyok
28th November 2014, 19:03
Super! Now it works ...
Are rusults of this script equivalent of: coloryuv(off_u=x,off_v=y)???
.
Where are you from? mate ?
.
Stormborec
28th November 2014, 20:34
Czech (Nedvěd, Rosický, Čech :D )
Stormborec
28th November 2014, 21:15
http://imgur.com/xrwqvuF
My TV does something else - grass goes to yellow, but the faces are also yellow, rather than red (like on the first screenshot) ...
I think, the TV works with every shade separately (just like the color management / calibration) and there is no global method, how to compensate the color shift ...
Stormborec
28th November 2014, 21:34
The picture on my tv looks nearly like on this screenshot, so I can insert inverted line, if I want get the correct colors. But it's only approximate:
http://imgur.com/epMbn95
some undersaturation + colorshift
In the coloryuv there are yet gain and gamma parameters, but it's too complicated. I didn't manage research, how gain and gamma work in this tool. But gain is according to the documentation rather used for luma.
Maybe "tweak" should be able to change separate color ranges, but I'm afraid, on my TV are the color shifts done depending on different colors tints and also levels of brightness. So it's practically impossible to make the correction.
raffriff42
28th November 2014, 22:53
I should have read your first post more completely. This seems like a TV calibration or video driver issue, and not a good application for Avisynth.
It's nearly impossible to calibrate colors looking at normal program material. If your video driver includes a calibration routine (mine is called "display optimization wizard") use it before doing anything else. For professional or semipro use, use a proper colorimeter (http://en.wikipedia.org/wiki/Tristimulus_colorimeter).
Then check video playback with test patterns, especially gray scale ramp, available at http://w6rz.net/. Instructions are available at the link.
feisty2
29th November 2014, 05:02
Czech (Nedvěd, Rosický, Čech :D )
chill, i heard there're lots of hotties there
Stormborec
29th November 2014, 11:39
Like everywhere else ...
Thanks. I think, it would be overkill to buy a colorimetr ... I think, I've got relatively well calibrated monitor, therefore the easiest solution could be to compare different levels of gray on the TV and on the monitor. My idea was to put some lightweight script of Avisynth into ffdshow.
Maybe if I took part of the script - just off_u, off_v in two or three levels of brightness ... set the correct parameters and then I could play with colors without changing gray balance - maybe by setting cont_u, cont_v - if I managed figure out how it works separately (I know, that cont_u and cont_v with the same values just means saturation change)
btw. Should I use opt="coring" in coloryuv for my purposes?
Stormborec
29th November 2014, 21:07
"Maybe if I took part of the script - just off_u, off_v in two or three levels of brightness ..."
Is it correct - just copy the function ColorYUVx3 from raffriff42's script without any changes? It seems, that it works :D many thanks, raffriff42
btw. why is there the comment: "## mt_lutxyz too slow!!" ?
Pity that I don't understand masktools ...
function ColorYUVx3(clip C,
\ float "off_u_lo", float "off_u_mid", float "off_u_hi",
\ float "off_v_lo", float "off_v_mid", float "off_v_hi",
\ float "xover_lomid", float "xover_midhi")
{
off_u_lo = Float(Default(off_u_lo, 0.0))
off_u_mid = Float(Default(off_u_mid, 0.0))
off_u_hi = Float(Default(off_u_hi, 0.0))
off_v_lo = Float(Default(off_v_lo, 0.0))
off_v_mid = Float(Default(off_v_mid, 0.0))
off_v_hi = Float(Default(off_v_hi, 0.0))
### What makes the calculation: * 3.0 / 256?
### The smooth transition between the ranges ?
xlo = Min(Max( 0, Default(xover_lomid, 102)), 127) * 3.0 / 256
xhi = Min(Max(128, Default(xover_midhi, 191)), 255) * 3.0 / 256
C_lo = C.ColorYUV(off_u=off_u_lo, off_v=off_v_lo)
C_mid = C.ColorYUV(off_u=off_u_mid, off_v=off_v_mid)
C_hi = C.ColorYUV(off_u=off_u_hi, off_v=off_v_hi)
mask_lo = C.mt_lut(
\ yexpr="x -0.01 * "+String(xlo)+" + 256 * ",
\ u=-128, v=-128)
mask_hi = C.mt_lut(
\ yexpr="1 x -0.01 * "+String(xhi)+" + - 256 * ",
\ u=-128, v=-128)
mask_mid = mt_lutxy(mask_lo, mask_hi, "x y + -1 * 256 + ", u=-128, v=-128)
return C.Overlay(C_lo, mask=mask_lo)
\ .Overlay(C_mid, mask=mask_mid)
\ .Overlay(C_hi, mask=mask_hi)
}
LemMotlow
2nd December 2014, 16:01
I should have read your first post more completely. This seems like a TV calibration or video driver issue, and not a good application for Avisynth.
It's nearly impossible to calibrate colors looking at normal program material. If your video driver includes a calibration routine (mine is called "display optimization wizard") use it before doing anything else. For professional or semipro use, use a proper colorimeter (http://en.wikipedia.org/wiki/Tristimulus_colorimeter).
Then check video playback with test patterns, especially gray scale ramp, available at http://w6rz.net/. Instructions are available at the link.Agreed. 100%.
You don't calibrate a graphic or video to look good on your TV or monitor. That would mean making a different version of every video for every TV or monitor you use. It's nonsense. You calibrate the TV or monitor to established standards of accuracy as well as you can, then adjust your images to display properly on a standardized device. Not the other way around.
The picture on my tv looks nearly like on this screenshot, so I can insert inverted line, if I want get the correct colors. But it's only approximate:
http://imgur.com/epMbn95The color balance in the top image of your pic looks nearly correct. The bottom image is too red.
In the coloryuv there are yet gain and gamma parameters, but it's too complicated. I didn't manage research, how gain and gamma work in this tool. But gain is according to the documentation rather used for luma.ColorYUV documentation in Avisynth looks pretty clear to me. If you don't get an understanding of concepts like gain, gamma, black levels, white balance, gray balance, all you'll do is work against yourself. Without histograms, graphs, or test patches, you'll get nowhere. It's impossible to correct color properly by eyeball alone. Why do you think advanced software from Adobe and Vegas have those features? They're not just for looks. Even Avisynth and VirtualDub have similar helpers available.
Maybe "tweak" should be able to change separate color ranges, but I'm afraid, on my TV are the color shifts done depending on different colors tints and also levels of brightness. So it's practically impossible to make the correction.Tweak is too basic for what you're trying to do, and you don't know how it works anyway. I agree, it's difficult to correct complex color ranges with Tweak, but it does work well as a starting point and is often essential.
it would be overkill to buy a colorimetr ... I think, I've got relatively well calibrated monitor, therefore the easiest solution could be to compare different levels of gray on the TV and on the monitor.That defies the laws of physics and of logic. A PC monitor or a TV can't be properly calibrated without a colorimeter -- which is simply a precise measuring tool, far more accurate than your eyes. The software used with that tool is your guide to proper adjustment. Without those tools you're like the blind leading the blind. Specifically, the image controls available on the typical consumer monitor are totally inadequate for proper calibration. You need tools designed for the job.
There's enough documentation and instructional material around to contradict everything you're doing. Every working graphics artist, photog, and videographer, and advanced video hobbyist knows very well that you're taking the wrong approach. You can even find calibration and colorimeter videos on YouTube. Free.
An older version of standard TV/projector calibration done the right way (still works for you and me): http://www.curtpalme.com/forum/viewtopic.php?t=10457
Don't buy the calibration software hyped by Curt Palme. For TV, use the free stuff (HCFR): http://www.homecinema-fr.com/colorimetre-hcfr/hcfr-colormeter/
Test example of how to calibrate a PC monitor the right way, this one using an i1 Display2 and XRite: http://www.tftcentral.co.uk/reviews/eye_one_display2.htm
The new version of the i1 is the I1 Profiler. Used in the same manner. Also used to calibrate your TV with HCFR software.
Example of proper monitor calibration from a member I used to know in another forum (and from my home state, too!): Post shows graphic analysis by HCFR software using the tools described. http://forum.videohelp.com/threads/335402-VHS-capture-critique?p=2083260&viewfull=1#post2083260
Otherwise, I'm afraid you'll have to live with what you get on your own.
Stormborec
4th December 2014, 19:10
You are right. Your solution is true, when it's possible.
I've got only integrated GPU and my cheap TV has only minimum toggles like "contrast", "saturation". So, the software solution is only solution.
Stormborec
4th December 2014, 19:27
I know, what the parameters in coloryuv mean. I don't know what they exactly do. E.g. coring - works it the way like: 15>>>16, 10>>>16, 1>>>16 or rather 15>>>20, 10>>>18, 1>>>16
LemMotlow
4th December 2014, 23:26
You are right. Your solution is true, when it's possible.
I've got only integrated GPUDoesn't matter. You make initial corrections with the monitor, not with the graphics card. Many integrateds have color correction settings, which should be turned off or set to neutral defaults anyway. The calibration software takes over from there.
and my cheap TV has only minimum toggles like "contrast", "saturation". So, the software solution is only solution.Even a cheap Visio has basic grayscale settings. If your TV is that cheap, what do you expect? My $400 SONY is no blockbuster but has 9 settings in its advanced menu. TV controls or not, it seems a fantastic amount of time and work to recreate every video to match a TV that has so little to offer.
I know, what the parameters in coloryuv mean. I don't know what they exactly do.Well...if you don't know what ColorYUV settings do, you don't know what they mean.
E.g. coring - works it the way like: 15>>>16, 10>>>16, 1>>>16 or rather 15>>>20, 10>>>18, 1>>>16That's not the way it works. By default, coring is off. When it's on, it clamps output to 16-235. That is, anything below a pixel value of 16 becomes 16 (crushed), anything above 235 becomes 235 (clipped).
ColorYUV documentation is pretty clear to me. Forget about the math formulas unless you want to spend all your time doing calculations. A histogram can show you what's happening when you change settings. The following is a simple histogram filter in Avisynth. This mode works only in YV12:
Histogram(mode="Levels")
There are other modes and other types of graphic displays.
You need more insight into color theory. An image that looks too red can look that way because of two basic reasons: (a) there's too much red, or (b) there's not enough green and blue. It depends on the image. Subtracting red will make the image look less red but also darker. Adding Blue and green (cyan) corrects the overall color balance but might make it too bright. Which would be correct? Use a histogram to look at the overall brightness and black levels and examine the general dominance of colors.
You've seen the term "white balance". If you don't know the RGB values for the color "white", you won't know how to get a correct white balance. "White" in TV-range terms means RGB values of Red 235, Green 235, blue 235. Notice, white consists of equal values of all three colors. Another color that looks white but not as bright is RGB 200-200-200. A color that looks like a plain middle gray is RGB 128-128-128. A darkish gray like the darker shadows of a white shirt would be RGB 64-64-64. "TV black" at RGB 16 is RGB 16-16-16. Notice, all those shades from bright white to middle gray to black have equal values of R, G, and B. If you can get those shades to be close to the correct RGB balance, all the other colors fall into place. How do you determine those RGB values in an image? You use a pixel sampler to read pixel values -- yeah, another handy tool that's in popular use.
Look into color theory a little deeper. Do you correct too much blue by adding red? Nope. Red isn't the "opposite" of blue. Add red to blue, you get pink. Blue's opposite is a secondary color, yellow (red + green). Add yellow (red + green) or reduce blue.
If your color imbalance is due to the kind of nonlinear color problems you get with VHS, you'll likely need RGB to correct that.
If you don't use the tools, you'll have a rough time catching on. Here are links to two basic tutorials on how to get information from histograms. The examples are camera histograms and Photoshop types, but all histograms give the same information -- they just use different formats.
Part 1: http://www.cambridgeincolour.com/tutorials/histograms1.htm
Part 2: http://www.cambridgeincolour.com/tutorials/histograms2.htm
As for Avisynth's documentation on ColorYUV...
http://avisynth.org.ru/docs/english/corefilters/coloryuv.htm
Example: the off (offset) parameter. What's complicated? If you add an offset of 10 to luma or chroma, every pixel value gets 10 added to it. 16+10=26. 200+10=210. A positive offset shifts all color or luma values to the right (brighter). A negative offset shifts all pixel values to the left (darker). If you use a histogram of some kind, you'll see it happen. You'll also see it happen if you just look at the image. Try this:
ColorYUV(off_y=30)
Then leave "Y" alone and try it with each YUV color, one at a time, as in ColorYUV(off_v=30) or ColorYUV(off_u=30).
Try the same thing with the Levels histogram at the end of the script to see what the histogram shows you.
Use the tools, man. Right now you're stabbing in the dark.
StainlessS
5th December 2014, 14:42
EDIT: Below intended as 'Be Aware',
Mid grey @ TV Levels is (16 + 235) / 2.0, ie 125.5, usually taken as 126.
EDIT: ColorYUV assumes full scale PC levels.
Stormborec
5th December 2014, 18:58
Thanks for informations. I've tought, that in YUV - changing U and V don't cause change of brightness? What I know, shifts in V are Red vs. Green and in U Blue vs. Green. (off_v, off_u)
https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcRMbPMtoLi4Em5AXbauQPGLR3SOXOQDbb0s7lzwpXDejmrZtWlR
Stormborec
5th December 2014, 19:14
For analyzing I use coloryuv(analyze=true)
LemMotlow
5th December 2014, 19:55
Thanks for informations. I've tought, that in YUV - changing U and V don't cause change of brightness? What I know, shifts in V are Red vs. Green and in U Blue vs. Green. (off_v, off_u)
https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcRMbPMtoLi4Em5AXbauQPGLR3SOXOQDbb0s7lzwpXDejmrZtWlRThat's true. It does in RGB, because RGB stores color together with luma info in the same location.
Stormborec
5th December 2014, 21:29
Yes. Color tunings in YUV is quite impractical. It's better in RGB - e.g. Colormill in Virtualdub ... I don't know, if in Avisynth is also some RGB adjusting tool, with division on shades, midtones, lights ...
Lyris
5th December 2014, 22:06
Exists a plugin or a script, which could change the color temperature?
I've got a TV, where isn't enough of settings. On the screen are faces and grass too yellow, and sky is rather gray than blue.
If I add blue, then sky is OK, but faces are violet, and grass is rather blue than green.
You might need to change the color decoding (using a color management processor) more than color temperature.
How are you coming to conclusions re the colors? Just visual observation? You should hire an ISF or THX calibrator to measure and adjust.
Stormborec
5th December 2014, 22:28
It's visibly off. But it seems, that gamma curve is OK. Just the colors are bad.
Stormborec
5th December 2014, 22:39
Could somebody write, how to change the script for two ranges of luma, please? It is too slow for real time playing ...
Stormborec
10th December 2014, 20:05
I'm playing with coloryuv, and I wonder why:
imagesource("gray.bmp").converttoyv12
coloryuv(off_u=-20,off_v=15)
coloryuv(off_u=20,off_v=-15)
coloryuv(cont_u=50,cont_v=50)
gives different outputs than:
coloryuv(off_u=-20,off_v=15)
coloryuv(off_u=20,off_v=-15,cont_u=50,cont_v=50)
In the first case is input=output.
But in the second one is there a colorshift
Does anybody know why?
It seems, that the cont_ is done before off_ ...
StainlessS
10th December 2014, 21:09
It seems, that the cont_ is done before off_ ...
Perhaps of interest, but just take as rough guide.
Below is from Visual Basic version of ColorYUV LUT building function.
RPow is gamma, ignore SPow, its an S shape power curve not available in ColorYUV (actually translated from ColorYUV2 rather than ColorYUV)
Pord is just the bool controlling whether RPow is applied before SPow (or other way around).
The line of interest is marked in BLUE. Ignore Pord,SPow stuff in RED.
Private Sub Make_Lut(Lutix As Long)
Dim x As Long, val As Double, levels As Long, pord As Long
Dim off As Double, gain As Double, cont As Double, rpow As Double, spow As Double
Dim V As Double
Dim maxim As Long
Dim coeff0 As Double, coeff1 As Double
Dim s As Long
Dim G As Double, v1 As Double, v2 As Double
For x = 0 To 3
If opt_Levels(x).Value = True Then
levels = x
Exit For
End If
Next x
Select Case Lutix
Case 0 ' Y
maxim = 235
coeff0 = coeff_y0
coeff1 = coeff_y1
Case 1 ' U
maxim = 240
coeff0 = coeff_u0
coeff1 = coeff_u1
Case 2 ' V
maxim = 240
coeff0 = coeff_v0
coeff1 = coeff_v1
End Select
pord = Lut_pord(Lutix)
off = (Lut_off(Lutix) + vscale) / vscale
gain = (Lut_gain(Lutix) + vscale) / vscale
cont = (Lut_cont(Lutix) + vscale) / vscale
rpow = (Lut_rpow(Lutix) + vscale) / vscale
spow = (Lut_spow(Lutix) + vscale) / vscale
If rpow < 0.004 Then rpow = 0.004
If spow < 0.004 Then spow = 0.004
Debug.Print rpow
For x = 0 To 255
val = x * vshift
If (levels = 1) Then ' TV->PC
If (Lutix = 0) Then 'Luma
val = Int((val - 16 * vshift) * coeff0 / coeff1 + vshift / 2)
Else ' Chroma
val = Int((val - 128 * vshift) * coeff_u0 / coeff_u1 + 128 * vshift + vshift / 2)
End If
ElseIf (levels = 2 Or levels = 3) Then ' PC->TV or PC->TV.Y
If (Lutix = 0) Then ' PC->TV and PC->TV.Y
val = Int(val * coeff1 / coeff0 + 16 * vshift + vshift / 2)
ElseIf levels = 2 Then ' Only PC->TV
val = Int((val - 128 * vshift) * coeff_u1 / coeff_u0 + 128 * vshift + vshift / 2)
End If
End If
val = val / vshift
V = val / 256#
V = (V * gain) + ((V - 0.5) * cont + 0.5) - V + (off - 1)
If (rpow <> 0 Or spow <> 0) Then
If pord = 0 Then
If (rpow <> 0) Then ' Here, rpow 1st
If (V > 0) Then
G = (1 / rpow)
V = V ^ G
End If
End If
If (spow <> 0) Then
V = V - 0.5
s = 0
If (V < 0#) Then
s = 1 ' remember sign
V = -V ' abs()
End If
V = V * 2# ' Make in range 0 -> 1.0
G = (1 / spow)
V = V ^ G ' rpow
V = V / 2# ' Back to range 0 -> 0.5
If (s) Then V = -V ' ReApply sign
V = V + 0.5
End If
Else
If (spow <> 0) Then ' Here Spow 1st
V = V - 0.5
s = 0
If (V < 0#) Then
s = 1 ' remember sign
V = -V ' abs()
End If
V = V * 2# ' Make in range 0 -> 1.0
G = (1 / spow)
V = V ^ G ' rpow
V = V / 2# ' Back to range 0 -> 0.5
If (s) Then V = -V ' ReApply sign
V = V + 0.5
End If
If (rpow <> 0) Then
If (V > 0) Then
G = (1 / rpow)
V = V ^ G
End If
End If
End If
End If
V = (V * 256#) + 0.5
val = Int(V) ' Round towards -ve infinity
If val > 255 Then
val = 255
ElseIf val < 0 Then
val = 0
End If
If val > maxim Then
If (chk_Coring.Value = vbChecked) Then val = maxim
ElseIf val < 16 Then
If (chk_Coring.Value = vbChecked) Then val = 16
End If
Lut(Lutix, x) = val
Next x
End Sub
So yes, cont is applied before off. EDIT: RPow (gamma) applied last (but before coring).
Stormborec
10th December 2014, 21:54
Thanks. It's a pitty, that I don't know Visual Basic.
I've made for myself some test video:
BlankClip(length=125,width=320,height=360,fps=25,pixel_type="yv12")
y1=coloryuv(off_y=55)
y2=coloryuv(off_y=110)
y3=coloryuv(off_y=165)
a=stackhorizontal(y1,y1.coloryuv(off_u=4,off_v=0).subtitle("40"))
b=stackhorizontal(y1,y1.coloryuv(off_u=4,off_v=1).subtitle("41"))
c=stackhorizontal(y1,y1.coloryuv(off_u=4,off_v=2).subtitle("42"))
d=stackhorizontal(y1,y1.coloryuv(off_u=4,off_v=3).subtitle("43"))
e=stackhorizontal(y1,y1.coloryuv(off_u=5,off_v=0).subtitle("50"))
f=stackhorizontal(y1,y1.coloryuv(off_u=5,off_v=1).subtitle("51"))
g=stackhorizontal(y1,y1.coloryuv(off_u=5,off_v=2).subtitle("52"))
h=stackhorizontal(y1,y1.coloryuv(off_u=5,off_v=3).subtitle("53"))
i=stackhorizontal(y2,y2.coloryuv(off_u=4,off_v=0).subtitle("40"))
j=stackhorizontal(y2,y2.coloryuv(off_u=4,off_v=1).subtitle("41"))
k=stackhorizontal(y2,y2.coloryuv(off_u=4,off_v=2).subtitle("42"))
l=stackhorizontal(y2,y2.coloryuv(off_u=4,off_v=3).subtitle("43"))
m=stackhorizontal(y2,y2.coloryuv(off_u=5,off_v=0).subtitle("50"))
n=stackhorizontal(y2,y2.coloryuv(off_u=5,off_v=1).subtitle("51"))
o=stackhorizontal(y2,y2.coloryuv(off_u=5,off_v=2).subtitle("52"))
p=stackhorizontal(y2,y2.coloryuv(off_u=5,off_v=3).subtitle("53"))
q=stackhorizontal(y3,y3.coloryuv(off_u=4,off_v=0).subtitle("40"))
r=stackhorizontal(y3,y3.coloryuv(off_u=4,off_v=1).subtitle("41"))
s=stackhorizontal(y3,y3.coloryuv(off_u=4,off_v=2).subtitle("42"))
t=stackhorizontal(y3,y3.coloryuv(off_u=4,off_v=3).subtitle("43"))
u=stackhorizontal(y3,y3.coloryuv(off_u=5,off_v=0).subtitle("50"))
v=stackhorizontal(y3,y3.coloryuv(off_u=5,off_v=1).subtitle("51"))
w=stackhorizontal(y3,y3.coloryuv(off_u=5,off_v=2).subtitle("52"))
x=stackhorizontal(y3,y3.coloryuv(off_u=5,off_v=3).subtitle("53"))
a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+r+s+t+u+v+w+x
StainlessS
10th December 2014, 22:32
V = (V * gain) + ((V - 0.5) * cont + 0.5) - V + (off - 1)
In ColorYUV a gain of zero results in no change, ColorYUV uses a weird way to represent conversion args (using Int),
in something more like tweak it would probably be more usual to provide gain as a multiplier where a gain of 1.0 produces no change
(and be exactly equivalent to the ColorYUV gain=0 thing).
So in above CODE line, gain and cont have been converted into multipliers where 1.0 == no change
(ColorYUV 0 -> 1.0 would mean no change, ColorYUV 128 -> 1.5 would mean 50% increase and ColorYUV 256 -> 2.0 would mean doubled).
As can be seen from CODE line, gain and cont calculations are more or less processed together at the same time, with off added in later.
Last of all RPow (Gamma) is processed and then coring.
Levels conversion (TV->PC or PC->TV is done before anything else, [EDIT: although code following levels is processed as if at PC levels]).
EDIT: So I would suggest best way of use on TV levels is something like
ColorYUV(Levels="TV->PC",gain= ... etc)
ColorYUV(Levels="PC->TV)
Above must surely be better than using Opt="Coring" on what is actually PC levels.
Stormborec
11th December 2014, 19:41
What is the advantage of processing in PC range, instead of in TV range?
StainlessS
11th December 2014, 19:48
Well getting the numbers correct is one reason, working in reduced range (TV) is not really gonna apply eg gamma correctly.
Perhaps other may disagree.
Stormborec
11th December 2014, 20:05
I thought that this is already expected by the tools of AviSynth - 16-235 OR 0-255 - that are just numbers ...
StainlessS
11th December 2014, 20:28
IIRC, Levels removes the TV levels 16 offset, scales 0.0 -> 1.0 and does gamma on that, then scales back down and adds back in the 16 offset.
ColorYUV only scales to TV->PC if requested and does not scale back afterwards, so
if you did a conversion of TV levels to RGB and applied gamma to that, and then converted back to TV YUV, and compared it to
ColorYUV applied to TV levels without the TV->PC levels conversion, I think the results would be different.
Try it out, let me know if they are the same. (EDIT: You could do it on a greyscale clip to remove U/V diffs)
Stormborec
11th December 2014, 20:40
What bothers me most on Coloryuv is, that when applying off_u / v, there is a shift in the black color - that black is not black, but i.e. dark blue ... I don't know what to do
StainlessS
11th December 2014, 20:45
Well that is what ColorYUV is suppose to do, perhaps you use the wrong tool for what is required (dont ask me what to use, no idea).
Afterthough, although you might wish to take a look at ColorYUV2, see here: http://forum.doom9.org/showthread.php?t=156774&highlight=coloryuv2
Stormborec
13th December 2014, 21:06
http://avisynth.nl/index.php/WhiteBalance
It looks like what I was looking for ... :thanks:
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.