VideoHelp Forum
+ Reply to Thread
Results 1 to 24 of 24
Thread
  1. Hey, is there a way to convert pixels of a specific color to another one? I have recorded a program that has green (255G) text on a blue background which x264 keeps darkening significantly despite using an i444 profile. Even with crf=0 it darkens it to 215. So much for lossless. So I'd like to turn every green pixel into a white or black one. This hopefully will fix this problem.
    Quote Quote  
  2. You are probably doing some unintended color conversion. Post MediaInfo+Sample of the source as well as your commands and logs.
    Quote Quote  
  3. I'm doing no such thing, it fails even when I ConverttoRGB but does well on other 4:4:4 sources. Source and failed encode attached.
    Code:
    --output-depth 10 --tune animation --crf 1.0 --b-adapt 2 --qpmin 10 --qpmax 51 --merange 24 --me tesa --direct auto --subme 11 --partitions p8x8,p4x4,b8x8,i4x4 --no-8x8dct --trellis 2 --no-fast-pskip --profile high444 --input-csp i444 --output-csp i444
    Last edited by Aludin; 30th Jul 2019 at 11:51.
    Quote Quote  
  4. You have a playback problem. They're both the same colors when loaded into VirtaulDub2 (which uses rec.601 to convert YUV to RGB):

    Image
    [Attachment 49675 - Click to enlarge]


    For HD material you should use rec.709 to convert from RGB to YUV. You should also flag the video as rec.709.
    Last edited by jagabo; 29th Jul 2019 at 08:27.
    Quote Quote  
  5. Interesting, regular virtualdub via ffvideosource had false colors but virtualdub2 opened it correctly. How do I flag the video as rec.709 in Avisynth? ConvertToRGB(matrix="Rec.709") failed but I assume because virtualdub already opened it as 601 beforehand?

    Someone remind me what these numbers are about again? We already have RGB and YUV so what's up with these?
    Quote Quote  
  6. You perform the color conversion in AvISynth. For RGB to YUV 4:4:4 use ConvertToYV24(matrix="rec709"), conversely ConvertToRGB(matrix="rec709"). You flag the color matrix in the encoder. With x264 it's "--colormatrix=bt709".

    You will still have problems with some players because some always use rec.601, some always use rec.709. Some use rec.601 for SD, rec.709 for HD, but are unpredictable in between (ie, between 720x576 and 1280x720). Some will follow the matrix specified in the video. Using rec.709 for resolutions over 720 wide or 576 tall and flagging the matrix in the encoding gives you the best hope of having it played correctly.
    Quote Quote  
  7. I did both those things and no player except Virtualdub2 is displaying it right.

    What is up with these color matrices? Doesn't all the infinite combos of YUV and RGB already define the 'color matrix' without having these further complications?
    Quote Quote  
  8. Originally Posted by Aludin View Post
    Doesn't all the infinite combos of YUV and RGB already define the 'color matrix' without having these further complications?
    Unfortunately, no. There are several different rotations and scalings in use. The most common are limited range rec.601 (DVD, other SD video...) and rec.709 (Blu-Ray, HD TV, youtube...).
    Quote Quote  
  9. I used the following script to open your AVI file:

    Code:
    AviSource("greentimer2.avi") 
    ConvertToYV24(matrix="rec709")
    Then encoded with:

    Code:
    x264 --colorprim "bt709" --transfer "bt709" --colormatrix "bt709" --output-depth 10 --tune animation --crf 1.0 --b-adapt 2 --qpmin 10 --qpmax 51 --merange 24 --me tesa --direct auto --subme 11 --partitions p8x8,p4x4,b8x8,i4x4 --no-8x8dct --trellis 2 --no-fast-pskip --profile high444 --input-csp i444 --output-csp i444 --output "%~1.mkv" "%~1"
    I added the colorprim and transfer options but they don't effect playback colors in any player I've used, only colormatrix. And got this result that plays properly in MPCHC and MPCBE
    Image Attached Files
    Quote Quote  
  10. This is weird. Now everything (except my original) plays back just fine in every player. Upon experimenting, it seems ConverttoRGB(matrix="rec709") will fail but ConvertToYV24(matrix="rec709") works and it has to specifically be rec709, not Rec.709 despite Virtualdub opening both just fine.
    This is so confusing.

    Unfortunately, no. There are several different rotations and scalings in use. The most common are limited range rec.601 (DVD, other SD video...) and rec.709 (Blu-Ray, HD TV, youtube...).
    What do you mean rotations and scalings? From what I understand, 4:2:0 and 4:4:4 describes how large the pixel of each color channel is. What further details does the color matrix give us?
    Last edited by Aludin; 30th Jul 2019 at 11:51.
    Quote Quote  
  11. Originally Posted by Aludin View Post
    What do you mean rotations and scalings?
    The RGB colorspace is a subset of the YUV (more properly YCbCr) colorspace. RGB is rotated, transformed, and scaled to fit within a fairly small portion of YUV:

    Click image for larger version

Name:	0EF01A88-F874-4ECB-B2B6-3ADC38636CD4-imageId=FE9BEAD5-12E5-4244-80E1-E61EB8211A76.jpg
Views:	103
Size:	29.5 KB
ID:	49687

    That's from "RGB Colors Cube in the YCbCr Space" at https://software.intel.com/en-us/node/503873.

    Originally Posted by Aludin View Post
    What further details does the color matrix give us?
    The colormatrix specifies the rotation, translation, and scaling.

    Originally Posted by Aludin View Post
    From what I understand, 4:2:0 and 4:4:4 describes how large the pixel of each color channel is.
    Yes, it describes the subsampling of the U and V channels. 4:4:4: means for every four Y samples there are four U and four V samples. 4:1:1 and 4:2:0 mean there is only one U and V value for every four Y values.

    http://avisynth.nl/index.php/YUV

    But it's more than just the subsampling, it's the location of the U and V samples relative to the Y samples (though this is often ignored):

    http://vektor.theorem.ca/graphics/ycbcr/Chroma_subsampling_notation.pdf
    Last edited by jagabo; 30th Jul 2019 at 16:17.
    Quote Quote  
  12. Member Cornucopia's Avatar
    Join Date
    Oct 2001
    Location
    Deep in the Heart of Texas
    Search PM
    4:1:1 and 4:2:0 mean there is only one U and V value for each Y value.
    I think you meant "4:1:1 and 4:2:0 mean there is only one U and V value for every 4 Y values".

    Scott
    Quote Quote  
  13. Originally Posted by Cornucopia View Post
    4:1:1 and 4:2:0 mean there is only one U and V value for each Y value.
    I think you meant "4:1:1 and 4:2:0 mean there is only one U and V value for every 4 Y values".
    Oops, yes. I'll fix it...
    Quote Quote  
  14. I've seen that cube before but it's always been greek to me. I don't get it. How do I interpret it?

    The idea that RGB is a subset of YCbCr is also news to me. You're telling me that in the same bitspace, YUV offers more shades/colors than RGB? Isn't RGB the building block for all digital display?

    The colormatrix specifies the rotation, translation, and scaling.
    Meaning what? What's being rotated?

    But it's more than just the subsampling, it's the location of the U and V samples relative to the Y samples (though this is often ignored):
    That I do know.
    Quote Quote  
  15. Originally Posted by Aludin View Post
    I've seen that cube before but it's always been greek to me. I don't get it. How do I interpret it?

    The idea that RGB is a subset of YCbCr is also news to me. You're telling me that in the same bitspace, YUV offers more shades/colors than RGB? Isn't RGB the building block for all digital display?
    When color TV was first invented they needed a way to transmit a signal that was compatible with all the existing black and white TVs. The solution was to rotate the RGB colorspace so that all the greys fell on one axis (Y) and the other two axis (Pb and Pr) represented colors that were added or subtracted from that greyscale value. Black and white TVs would show the greyscale image but ignore the chroma channels. Color TVs would use all three channels to reconstruct the full RGB picture. This was all done with analog components, of course.

    The rest of this description relates to the digital representation of that analog signal -- the limited range rec.601 or rec.709 schemes, YCbCr.

    Since both RGB and YUV are three dimensional color spaces they can be represented by a three dimensional graph. Sice they are bounded (0 to 255) they can be represented by finite cubes. The image I posted shows the full RGB colorspace within the full YCbCr colorspace. All valid RGB colors (with values of 0 to 255) are represented by the inner cube. All possible YCbCr values are represented by the outer cube.

    A straight line from the black corner of the RGB cube (0,0,0) to the white corner (255,255,255) represents all pure grey values. You can see that the RGB cube is rotated within the YUV cube so that the black corner is at its bottom and the white corner is at its top. It is shifted (translated) within the YCbCr cube so that the greyscale axis isn't at Cb=Cr=0 but rather Cb=Cr=128. And it is scaled so that the RGB 0 to 255 range fits within 16 to 235 on the Y axis. Values outside the inner cube represent RGB values that don't fall within the specified RGB range of 0 to 255. So the YUV cube represents a wider gamut of colors than that inner RGB cube. For example, Y=0 Cb=Cr=128 would require negative values for R, G and B (about -18) -- your monitor would have to suck photons out of your eyes for you to "see" it.

    Since the RGB cube is shrunken within the YCbCr cube, and both cubes represent 16 million possible combinations (as 8 bit values), multiple RGB values end up mapping to the same YCbCr value. In fact, on average, each YUV value maps to about 6 nearby RGB colors. This is why banding is much more of a problem with digital YUV.
    Quote Quote  
  16. Carla Ramirez
    Join Date
    Jul 2019
    Location
    Argentina
    Search Comp PM
    They're both the same colors when loaded into VirtaulDub2
    Quote Quote  
  17. So an updated system basically had to pander to the already-existing inferior system because nobody wanted to start from scratch? I'm not surprised. Seems to be common practice with everything.

    But if we used 48-bit instead of 24-bit color, that is 65536 shades for each RGB color, would that be enough for all possible YUV values?

    And it is scaled so that the RGB 0 to 255 range fits within 16 to 235 on the Y axis.
    So basically 220 shades in a range of 256? I think I've come across this noticeable banding in YV12. But why would they shift this so it only occupies 85% of the total 8-bit shades? I understand using 2x2 chroma pixels in 4:2:0 because it's rarely noticeable but cutting off so much of the luma that it creates banding seems a dick move.
    Quote Quote  
  18. Originally Posted by Aludin View Post

    But if we used 48-bit instead of 24-bit color, that is 65536 shades for each RGB color, would that be enough for all possible YUV values?
    No ; higher bit depth such as 48bit (16 bit per channel) only increase the precision (fewer rounding errors) . There are still those areas that lie outside the cube (areas defined by YUV color model, that have no RGB coverage) .

    But if you use float values with negative RGB values, then you can cover all . And as it happens, it's used in higher end visual effects and post production - the openEXR format supports half and full float at 16bit, 32bit per channel (and higher) RGB and other color models


    So basically 220 shades in a range of 256?
    For a standard range conversion . Full range "maps" 0-255 Y' to 0,0,0 - 255,255,255 RGB (or vice versa when going the other way). But you still have areas outside the cube (you need negative RGB values to "solve")
    Quote Quote  
  19. No ; higher bit depth such as 48bit (16 bit per channel) only increase the precision (fewer rounding errors) . There are still those areas that lie outside the cube (areas defined by YUV color model, that have no RGB coverage).
    So it's not an issue of having enough shades of R G and B but the conversion of an obsolete analog YUV signal to RGB?

    For a standard range conversion . Full range "maps" 0-255 Y' to 0,0,0 - 255,255,255 RGB (or vice versa when going the other way). But you still have areas outside the cube (you need negative RGB values to "solve")
    I'm gonna need schematics (other than the cube) to visualize this before I can understand. Because I still don't get why using the highest quality color format (YUV 4:4:4) still made a pure green 0,255,0 pixel to 0,215,0. I mean, if translating YUV to RGB with one color matrix has a limit of 220 shades, that would be a jump of 1 every 6 shades or so, not 40 shades darker.

    Also, even though you guys taught me how to avoid this issue, I still wanna avoid it altogether by converting the green text to white (or black), that way even YV12 won't mess it up. Is there a way to use a mask only for green? Thanks.
    Quote Quote  
  20. Originally Posted by Aludin View Post
    No ; higher bit depth such as 48bit (16 bit per channel) only increase the precision (fewer rounding errors) . There are still those areas that lie outside the cube (areas defined by YUV color model, that have no RGB coverage).
    So it's not an issue of having enough shades of R G and B but the conversion of an obsolete analog YUV signal to RGB?

    Technically it's Y'CbCr, and it's all digital (YUV is technically analog), and they are discrete values. But people use those terms YUV and Y'CbCr interchangably.

    Simply , there are values that do no "map", regardless of the precision or number of shades . You cannot solve the equation (unless you have negative values).




    Because I still don't get why using the highest quality color format (YUV 4:4:4) still made a pure green 0,255,0 pixel to 0,215,0.
    I mean, if translating YUV to RGB with one color matrix has a limit of 220 shades, that would be a jump of 1 every 6 shades or so, not 40 shades darker.
    This has less to do with the "number of shades", but the wrong matrix (wrong equations)

    subsampling (eg, 4:2:0, 4:2:2, 4:4:4) , bit depth (e.g. 8bit per channel vs. 10bit per channel), and matrix conversion (how YUV <=> RGB conversions back and forth are done, the equation e.g ITU Rec 601, vs. 709, vs 2020, etc..) are different concepts

    You were using the wrong matrix equation. Think of matrix as the set of equations used to inter convert RGB and YUV back and forth. If you mess up 601, vs. 709, vs. 2020 vs. whatever - you get different values, different colors. By convention 601 is for SD, 709 is for HD . If you use the same matrix back and forth, you get the same colors (approximately, you don't often because of precision rounding losses, and not all YUV values are contained in RGB) . But starting with 8bit RGB to 10bit YUV should almost be perfect if the conversion back to RGB is done correctly (that 10bit precision should be enough for almost perfect colors 99.9% , there might be a few values, you might actually need 11bit). The reverse isn't necessarily true if you start with YUV (because the RGB color cube is smaller)

    If you use 709 to convert RGB to YUV (the first conversion; if you didn't specify in the script, and let x264 do it, it will use 601 - that's probably why it looked correct in vdub), you have to "reverse" YUV back to RGB with the same 709. Anything else will give you wrong colors.

    When you "see" something on a display, it has been converted back to RGB . Identiyfing where and how matrix conversions were done important. It can occur in software decoder, in renderer, in GPU, etc...


    Also, even though you guys taught me how to avoid this issue, I still wanna avoid it altogether by converting the green text to white (or black), that way even YV12 won't mess it up. Is there a way to use a mask only for green? Thanks.
    There will always be potential to mess things up.

    If you stick with RGB, that's almost foolproof , but the compression is significantly lower, and compatibility is lower (e.g. most devices won't support AVC as RGB) . RGB is RGB, nothing has to be converted back to display, fewer steps, so less chance of a matrix error. (BUT - some programs actually convert it to YUV 422 first as an intermediate, don't ask me why)
    Quote Quote  
  21. I get it, in theory. Is there a map that shows which RGB values correspond to YUV? I need to see how this works in practice.

    Also, I figured out how to make the green pixels white but a more sensible method is always welcome. You say it can still be messed up but white on blue text is way harder to mess up than green on blue. Even on YV12 it doesn't look bad. I kept getting the 601 and 709 confused because they both look the same on virtualdub but one was messed up upon looking at the encode. So if different players/editors/encoders are all gonna use their own combo at will then it's better to deprive it of the opportunity altogether.

    Code:
    v=import("M:\Frostrecording0025.avi.avs").converttoYV24
    g=v.greyscale
    c=subtract(v,g)
    m=c.Limiter(min_chroma=34,max_chroma=56,show="chroma_grey").tweak(cont=2).greyscale.tweak(bright=-105).tweak(cont=2).tweak(bright=-100).tweak(cont=1.85).tweak(bright=-95).tweak(cont=2).converttoRGB32
    Overlay(v,m,mask=m, mode="blend", opacity=1)
    Quote Quote  
  22. Originally Posted by Aludin View Post
    I get it, in theory. Is there a map that shows which RGB values correspond to YUV? I need to see how this works in practice.
    The Intel link I gave in post 11 gives the equations used to convert between RGB and limited range YCbCr.
    Quote Quote  
  23. Originally Posted by Aludin View Post
    a more sensible method is always welcome

    1) Another commonly used way to change a chosen color range to something else is to color key (chroma key) . Avisynth isn't the greatest at this , but should work ok for simple , small ranges of color RGB input . ColorScreenMask in avisynth, but I think it's x86 only. There are other free/open source tools that a better keyers (e.g natron, blender), but probably overkill for what you're doing here

    EDIT:

    For "simple" RGB colors, the built in ColorKeyMask is probably "easiest"
    http://avisynth.nl/index.php/Layer#ColorKeyMask


    e.g using image in post #4 .

    (RGB 0,255,0 is $00FF00 in hex)

    Code:
    orig=ImageSource("compare.png")
    
    orig.ConvertToRGB32()
    colorkeymask($00FF00)
    showalpha()
    invert()
    msk=last
    
    overlay(orig, msk, mask=msk)
    #ConvertToYV24(matrix="rec709") # if you want YUV444  using 709
    If you have "off colors" (e.g. Windows sometimes has antialiasing or font smoothing - that can result in edges that are not 100% the same color), you might need to adjust the tolerance ranges (tolB, tolG, tolR)

    You have the option to use something other than white (in the example above, the "white" of the mask is also used as the replacement color)
    Last edited by poisondeathray; 5th Aug 2019 at 01:14.
    Quote Quote  
  24. Carla Ramirez
    Join Date
    Jul 2019
    Location
    Argentina
    Search Comp PM
    Hello poisondeathray, I will try to use your solution, I think is very nice
    All is possible!
    I watch movies
    Quote Quote  



Similar Threads

Visit our sponsor! Try DVDFab and backup Blu-rays!