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 5th April 2014, 22:16   #1  |  Link
Reel.Deel
Registered User
 
Join Date: Mar 2012
Location: Texas
Posts: 1,640
Decompose RGB and YUV in color?

Hi everyone,

After reading the YCbCr page on Wikipedia there's an illustration that shows RGB and YUV decoposed but with color. I thought it was kinda neat and tried doing it with AviSynth.
I know there is ShowRed/Green/Blue and UtoY/VtoY but the output is greyscale. I started tinkering and came up with something but I'm not completely sure if it's correct?

Source for this little experiment:


--------

For RGB:
Code:
# Source
ImageSource("4.2_04.png", end=0)

# Processing
R = ShowRed("Y8")
G = ShowGreen("Y8")
B = ShowBlue("Y8")

blank = BlankClip(R, color_yuv=$000000)

R2 = MergeRGB(R, blank, blank, pixel_type="RGB24")
G2 = MergeRGB(blank, G, blank, pixel_type="RGB24")
B2 = MergeRGB(blank, blank, B, pixel_type="RGB24")

StackHorizontal(R2, G2, B2)


--------

For YUV:
Code:
# Source
ImageSource("4.2_04.png", end=0)
ConvertToYV24(matrix="PC601")
o = last

# Processing
U = UToY8()
V = VToY8()
Blank = BlankClip(U, color_yuv=$808080)

Y = MergeRGB(o,o,o, pixel_type="RGB24")
U2 = YToUV(U, Blank, Blank)
V2 = YToUV(Blank, V, Blank)

UV = StackHorizontal(U2,V2).ConvertToRGB24(matrix="PC601")

StackHorizontal(Y, UV)
Reel.Deel is offline   Reply With Quote
Old 7th April 2014, 18:29   #2  |  Link
Wilbert
Moderator
 
Join Date: Nov 2001
Location: Netherlands
Posts: 6,356
Just use RGBAdjust (setting r=g=0 for showing blue for example) and use ColorYUV (setting gain_y=-1, cont_u=-1 for showing v).
Wilbert is offline   Reply With Quote
Old 8th April 2014, 04:54   #3  |  Link
EncodedMango
Registered User
 
Join Date: Jun 2013
Posts: 65
That's really neat!
Might I ask what you're running the script in for the output or if you're using ImageWriter?

EDIT:
I stacked them vertically and used ImageWriter to output to bmp.
ImageWriter("%RGB.bmp")
ImageWriter("%YUV.bmp")

Last edited by EncodedMango; 8th April 2014 at 05:32.
EncodedMango is offline   Reply With Quote
Old 8th April 2014, 07:04   #4  |  Link
raffriff42
Retried Guesser
 
raffriff42's Avatar
 
Join Date: Jun 2012
Posts: 1,373
Nice, here's a little variation:


Code:
## (requires MaskTools)

r = Last.ConvertToRGB24
ConvertToYV24(matrix="PC.601")
o = last

U = UToY8()
V = VToY8()
Blank = BlankClip(U, color_yuv=$808080)

UA = U.mt_lut(("(x < 128) ? 128 : x").mt_polish)
UB = U.mt_lut(("(x > 128) ? 128 : x").mt_polish)
VA = V.mt_lut(("(x < 128) ? 128 : x").mt_polish)
VB = V.mt_lut(("(x > 128) ? 128 : x").mt_polish)
Y = MergeRGB(o, o, o, pixel_type="RGB24")

U2A = YToUV(UA, Blank, Blank)
U2B = YToUV(UB, Blank, Blank) 
V2A = YToUV(Blank, VA, Blank)
V2B = YToUV(Blank, VB, Blank)

UVA = StackHorizontal(U2A._sub("U+"), V2A._sub("V+"))
UVB = StackHorizontal(U2B._sub("U-"), V2B._sub("V-"))

StackVertical(
\  StackHorizontal(r, UVA.ConvertToRGB24(matrix="PC.601")),
\  StackHorizontal(Y, UVB.ConvertToRGB24(matrix="PC.601")))
return Last

function _sub(clip C, string msg) {
    return C.Subtitle(msg, align=5, size=C.Height/8, text_color=$c0c0c0)
}

Last edited by raffriff42; 18th March 2017 at 00:47. Reason: (fixed image links)
raffriff42 is offline   Reply With Quote
Old 8th April 2014, 22:17   #5  |  Link
wonkey_monkey
Formerly davidh*****
 
wonkey_monkey's Avatar
 
Join Date: Jan 2004
Posts: 2,456
Aside: I've often wondered why that image is still widely used in tests; it's washed out, soft, and only features a narrow range of colour.
__________________
My AviSynth filters / I'm the Doctor
wonkey_monkey is offline   Reply With Quote
Old 9th April 2014, 16:31   #6  |  Link
Reel.Deel
Registered User
 
Join Date: Mar 2012
Location: Texas
Posts: 1,640
Quote:
Originally Posted by Wilbert View Post
Just use RGBAdjust (setting r=g=0 for showing blue for example) and use ColorYUV (setting gain_y=-1, cont_u=-1 for showing v).
Thanks for the response Wilbert. RGBAdjust works as expected but with ColorYUV(gain_y=-1, cont_u=-1) the output still looks the same as the input.

Quote:
Originally Posted by sidspyker View Post
That's really neat!
Might I ask what you're running the script in for the output or if you're using ImageWriter?
I usually used AvsPmod or the good ol' VirtualDub but ImageWriter works just as well.

Quote:
Originally Posted by raffriff42 View Post
Nice, here's a little variation:
Thanks raffriff42, that's nice.

Quote:
Originally Posted by davidhorman View Post
Aside: I've often wondered why that image is still widely used in tests; it's washed out, soft, and only features a narrow range of colour.
Yeah I agree that picture is dull.


---------

Regarding YUV color decomposition, I've come across 2 different methods of doing this:

1). MATLAB
The code used is here and the output looks identical to the YUV script in the first post.

2). Perl or ImageMagick
This is the Perl script used. There's a comment about this code being wrong but I'm not sure if it was ever fixed or not, there's even a thread how to do this with ImageMagick.
Regardless here's how to do it with AviSynth.

Code:
# Source
ImageSource("4.2_04.png", end=0)
ConvertToYV24(matrix="PC.601")
o = last

# Processing
U = UToY8()
V = VToY8()

U2 = U.Invert()
V2 = V.Invert()

Blank = BlankClip(U, color_yuv=$000000)

Y = MergeRGB(o,o,o, pixel_type="RGB24")
U = MergeRGB(Blank, U2, U, pixel_type="RGB24")
V = MergeRGB(V, V2, Blank, pixel_type="RGB24")

UV = StackHorizontal(U,V)

StackHorizontal(Y, UV)



What method do you guys think it's more accurate? IMO I think it's the MATLAB method...
Reel.Deel is offline   Reply With Quote
Old 9th April 2014, 18:32   #7  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,425
Quote:
Originally Posted by Reel.Deel View Post
with ColorYUV(gain_y=-1, cont_u=-1) the output still looks the same as the input.
It should be ColorYUV(gain_y=-256, cont_u=-256)
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 9th April 2014, 19:31   #8  |  Link
cretindesalpes
͡҉҉ ̵̡̢̛̗̘̙̜̝̞̟̠͇̊̋̌̍̎̏̿̿
 
cretindesalpes's Avatar
 
Join Date: Feb 2009
Location: No support in PM
Posts: 712
Whatever the method, I think the chroma should be scaled according to the luma.

Code:
Function decompose_yuv (clip src)
{
	src
	Assert (IsYUV (), "decompose_yuv: clip must be YUV")

	b = last.BlankClip (color_yuv=$808080)
	y = ConvertToY8 ()
	u = UToY8 ()
	v = VToY8 ()
	y2 = IsYV24 () ? y : y.BicubicResize (u.Width (), v.Height ())

	u = mt_lutxy (u, y2, "y 0 >   x 128 - 128 * y / 128 +   x   ?")
	v = mt_lutxy (v, y2, "y 0 >   x 128 - 128 * y / 128 +   x   ?")

	y = YToUV (b.UToY8 (), b.VToY8 (), y)
	u = YToUV (u         , b.VToY8 (), b)
	v = YToUV (b.UToY8 (), v         , b)

	Interleave (y, u, v)
}
__________________
dither 1.28.1 for AviSynth | avstp 1.0.4 for AviSynth development | fmtconv r30 for Vapoursynth & Avs+ | trimx264opt segmented encoding
cretindesalpes is offline   Reply With Quote
Old 9th April 2014, 20:18   #9  |  Link
raffriff42
Retried Guesser
 
raffriff42's Avatar
 
Join Date: Jun 2012
Posts: 1,373
Quote:
Originally Posted by Gavino View Post
It should be ColorYUV(gain_y=-256, cont_u=-256)
Use this and never worry about ColorYUV's strange argument scaling again
Code:
### transform "normal" float arguments to 
### ColorYUV's "gain_x", "gamma_x" & "cont_x" scale 
##
function f2cuv(float f) {
    return Round((f - 1.0) * 256.0)  
}

/*
# example:
return Subtract(
\  ColorYUV(gain_y=-256, cont_u=-256),
\  ColorYUV(gain_y=f2cuv(0), cont_u=f2cuv(0))
\ )
*/
raffriff42 is offline   Reply With Quote
Old 16th April 2014, 13:57   #10  |  Link
Reel.Deel
Registered User
 
Join Date: Mar 2012
Location: Texas
Posts: 1,640
Quote:
Originally Posted by cretindesalpes View Post
Whatever the method, I think the chroma should be scaled according to the luma.
Thanks for the input, with your method the decomposed chroma looks a bit more defined.

If I'm understanding correctly luma and chroma are compared pixel by pixel. If a luma pixel is greater than 0, replace that pixel by ((((x-128)*128)/y)+128) and if not leave the original chroma pixel value.
Regarding mt_lutxy, I understand the concept but how does one really come up with such an expression? Is there a general guideline? What baffles me is how do you know when to add, subtract, etc.? And ultimately how do you know if it's correct or not?
Reel.Deel is offline   Reply With Quote
Old 21st April 2014, 11:25   #11  |  Link
cretindesalpes
͡҉҉ ̵̡̢̛̗̘̙̜̝̞̟̠͇̊̋̌̍̎̏̿̿
 
cretindesalpes's Avatar
 
Join Date: Feb 2009
Location: No support in PM
Posts: 712
Quote:
Originally Posted by Reel.Deel View Post
If I'm understanding correctly luma and chroma are compared pixel by pixel. If a luma pixel is greater than 0, replace that pixel by ((((x-128)*128)/y)+128) and if not leave the original chroma pixel value.
Actually it just means: adjust the contrast of each pixel individually to reach a luma of 128.

The comparison with 0 is just here to avoid to divide by 0.

Because the chroma is centered around 128, we need to shift it to 0 for the scaling with the “-128”, and shift it again after operation with “+128”.

In the expressions, “/y” scales the contrast to unity, and “*128” scales it to the target luma.

For the mt_lut* expression, you have to be familiar with the Reverse Polish Notation. If you’re not, there is a mt_polish() function to convert natural expressions to RPN.
__________________
dither 1.28.1 for AviSynth | avstp 1.0.4 for AviSynth development | fmtconv r30 for Vapoursynth & Avs+ | trimx264opt segmented encoding
cretindesalpes is offline   Reply With Quote
Reply

Tags
rgb decompose, yuv decompose

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 00:02.


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