Correct YUV422 to RGB conversion

僤鯓⒐⒋嵵緔 提交于 2019-12-03 16:02:48

Some clues to help you along:

You are confusing Cr with Cb.

Assuming UYVY/422

Y1 = data[j+0];
Cr = data[j+1];
Y2 = data[j+2];
Cb = data[j+3];

Your conversion calculation are wierd, and incorrect for HD.

For SD

R = max(0, min(255, 1.164(Y - 16) + 1.596(Cr - 128)));
G = max(0, min(255, 1.164(Y - 16) - 0.813(Cr - 128) - 0.391(Cb - 128)));
B = max(0, min(255, 1.164(Y - 16) + 2.018(Cr - 128)));

For HD

R = max(0, min(255, 1.164(Y - 16) + 1.793(Cr - 128)));
G = max(0, min(255, 1.164(Y - 16) - 0.534(Cr - 128) - 0.213(Cb - 128)));
B = max(0, min(255, 1.164(Y - 16) + 2.115(Cr - 128)));

You could simply use ConvertFrame which is a part of the Decklink SDK.

Your problem is that there are lots of YUV422 formats out there. You must find the exact one (the FOURCC index for the specific video you're using), and then figure out the correct way to decode it.

What you can do is to save some video from your board, open it in VLC, and look at the Codec details to find the exact FOURCC used.

http://www.fourcc.org/yuv.php

Assuming packed 422 I don't see any of your blocks sampling the input data correctly. In packed 422 the input data will go Y1U1Y2V1 Y3U2Y4V2 where the overall image is a Y (luma) image at full resolution and one each of U and V each at half horizontal resolution.

Here's where I would start: Unpack alternating values of the input and extract a grayscale image:

for (uint i = 0, j = 0; i < 1280 * 720 * 3; i += 3, j += 2) {
    m_RGB->imageData[i] = pData[j];
    m_RGB->imageData[i+1] = pData[j];
    m_RGB->imageData[i+2] = pData[j];
}

Once you have that tuned to produce a grayscale image then introduce U and V by looking at pData[j+1] and pData[j+3] (or, on even pixels, pData[j-1] and pData[j+1]). Simplifying that is why some algorithms do two YUV pixels at a time.

When that works consider extracting the U and V images and properly resampling them to full resolution to produce a 444 image. Simply duplicating U and V for adjacent pixels is like upscaling by duplicating pixels.

(Note that other arrangements like 420 have even more complicated co-siting)

I also struggled with the conversion

// Get the bytes
var u = bytes[0]; 
var y1 = bytes[1];
var v = bytes[2];
var y2 = bytes[3];

// Convert, cast to signed byte is important!
var r = y + (1.403 * (sbyte)v);
var g = y - (0.344 * (sbyte)u) - (0.714 * (sbyte)v);
var b = y + (1.770 * (sbyte)u);

if (r < 0)
    r = 0;
else if (r > 255)
    r = 255;

if (g < 0)
    g = 0;
else if (g > 255)
    g = 255;

if (b < 0)
    b = 0;
else if (b > 255)
    b = 255;

return Color.FromArgb((byte)r, (byte)g, (byte)b);

u and v are sbyte, and y is just a byte.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!