'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 |