'Convert YUV2 (YUYV) frames to RGB without use of OpenCV

I am trying to convert YUV2 frames generated by V4l2 to RGB.
I was able to convert YUV2 to RGB cv2.cvtColor(im, cv2.COLOR_YUV2RGB_YUYV) using OpenCV.

Currently confuse :
how can I convert a YUV2 frames to RGB without OpenCV.
Also are there any examples out there?



Solution 1:[1]

Referring to this page, it looks like the samples are arranged like this:

start + 0:  Y'00    Cb00    Y'01    Cr00    Y'02    Cb01    Y'03    Cr01
start + 8:  Y'10    Cb10    Y'11    Cr10    Y'12    Cb11    Y'13    Cr11
start + 16: Y'20    Cb20    Y'21    Cr20    Y'22    Cb21    Y'23    Cr21
start + 24: Y'30    Cb30    Y'31    Cr30    Y'32    Cb31    Y'33    Cr31

That should mean, if your bytes are arranged in a Numpy array of this specification:

np.zeros((h,w), dtype=np.uint8)

you should be able to extract the Y, Cb and Cr values with:

# Y is every row, every 2nd sample starting at 0
Y  = im[:, 0::2]
# Cb is every row, every 4th sample, starting at 1
Cb = im[:, 1::4]
# Cr is every row, every 4th sample, starting at 3
Cr = im[:, 3::4]

Then you need to resize up the Cb, Cr samples to match the width of Y.

Then you need to do some maths.

Solution 2:[2]

YUY2 uses 4 bytes to store 2 adjacent pixels, where each pixel has a separate luminance information, but the colour information is shared between the two pixels.

There are multiple definitions for the actual conversion between YUV and RGB, e.g. Poynton

Here's an integer-arithmetic implementation that I've been using for years

# define Y_OFFSET   16
# define UV_OFFSET 128
# define YUV2RGB_11  298
# define YUV2RGB_12   -1
# define YUV2RGB_13  409
# define YUV2RGB_22 -100
# define YUV2RGB_23 -210
# define YUV2RGB_32  519
# define YUV2RGB_33    0


    while(pixelnum--) {
      int y, u, v;
      int uv_r, uv_g, uv_b;
      u=yuvdata[chU]-UV_OFFSET;
      v=yuvdata[chV]-UV_OFFSET;
      uv_r=YUV2RGB_12*u+YUV2RGB_13*v;
      uv_g=YUV2RGB_22*u+YUV2RGB_23*v;
      uv_b=YUV2RGB_32*u+YUV2RGB_33*v;

      // 1st pixel
      y=YUV2RGB_11*(yuvdata[chY0] -Y_OFFSET);
      pixels[chR] = CLAMP((y + uv_r) >> 8); // r
      pixels[chG] = CLAMP((y + uv_g) >> 8); // g
      pixels[chB] = CLAMP((y + uv_b) >> 8); // b
      pixels+=3;
      // 2nd pixel
      y=YUV2RGB_11*(yuvdata[chY1] -Y_OFFSET);
      pixels[chR] = CLAMP((y + uv_r) >> 8); // r
      pixels[chG] = CLAMP((y + uv_g) >> 8); // g
      pixels[chB] = CLAMP((y + uv_b) >> 8); // b
      pixels+=3;

      yuvdata+=4;
    }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mark Setchell
Solution 2 umläute