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. |
![]() |
#1 | Link |
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) ![]() |
![]() |
![]() |
![]() |
#3 | Link |
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. |
![]() |
![]() |
![]() |
#4 | Link |
Retried Guesser
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) |
![]() |
![]() |
![]() |
#6 | Link | |||
Registered User
Join Date: Mar 2012
Location: Texas
Posts: 1,640
|
Quote:
Quote:
Thanks raffriff42, that's nice. Quote:
--------- 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... |
|||
![]() |
![]() |
![]() |
#8 | Link |
͡҉҉ ̵̡̢̛̗̘̙̜̝̞̟̠͇̊̋̌̍̎̏̿̿
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 |
![]() |
![]() |
![]() |
#9 | Link |
Retried Guesser
Join Date: Jun 2012
Posts: 1,373
|
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)) \ ) */ |
![]() |
![]() |
![]() |
#10 | Link | |
Registered User
Join Date: Mar 2012
Location: Texas
Posts: 1,640
|
Quote:
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? |
|
![]() |
![]() |
![]() |
#11 | Link | |
͡҉҉ ̵̡̢̛̗̘̙̜̝̞̟̠͇̊̋̌̍̎̏̿̿
Join Date: Feb 2009
Location: No support in PM
Posts: 712
|
Quote:
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 youre 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 |
|
![]() |
![]() |
![]() |
Tags |
rgb decompose, yuv decompose |
Thread Tools | Search this Thread |
Display Modes | |
|
|