在c++中将YUV转换为RGB(Android-NDK)

3
我正在开发Android应用程序,并且想要将摄像头预览回调中的字节数组,该数组是以YUV格式表示的,转换为RGB格式。

我已经使用了这个答案提供的函数:在Android上获取视频图像帧

它在Java中运行得非常完美,但我的问题是我想要在C++中实现此函数(我正在使用NDK,并不太熟悉C++)。

我已经尝试在C++中创建这个函数,但它总是产生奇怪的结果(例如,图片全部都是绿色的)。

有没有人拥有类似的函数或者这个函数在C++中能够正常运行?

谢谢。


在另一篇帖子中发布您对该函数的C++转换。我非常成功地使用了用户“Codevalley”的答案。 - weston
2个回答

9

C++中从YUYV到RGB的转换:

unsigned char* rgb_image = new unsigned char[width * height * 3]; //width and height of the image to be converted

int y;
int cr;
int cb;

double r;
double g;
double b;

for (int i = 0, j = 0; i < width * height * 3; i+=6 j+=4) {
    //first pixel
    y = yuyv_image[j];
    cb = yuyv_image[j+1];
    cr = yuyv_image[j+3];

    r = y + (1.4065 * (cr - 128));
    g = y - (0.3455 * (cb - 128)) - (0.7169 * (cr - 128));
    b = y + (1.7790 * (cb - 128));

    //This prevents colour distortions in your rgb image
    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;

    rgb_image[i] = (unsigned char)r;
    rgb_image[i+1] = (unsigned char)g;
    rgb_image[i+2] = (unsigned char)b;

    //second pixel
    y = yuyv_image[j+2];
    cb = yuyv_image[j+1];
    cr = yuyv_image[j+3];

    r = y + (1.4065 * (cr - 128));
    g = y - (0.3455 * (cb - 128)) - (0.7169 * (cr - 128));
    b = y + (1.7790 * (cb - 128));

    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;

    rgb_image[i+3] = (unsigned char)r;
    rgb_image[i+4] = (unsigned char)g;
    rgb_image[i+5] = (unsigned char)b;
}

这种方法假定你的yuyv_image也是unsigned char*类型。
更多关于YUYV的信息可以在这里找到。
想要了解YUYV --> RGB的更多细节,请查看这里

1
我认为有一种更好的方法来防止颜色失真:我知道的解决方案是将输入范围限制在Y、Cb和Cr的有效范围内。Y的有效范围是[16, 235],Cb、Cr的有效范围是[16, 240]。将输入夹紧:y = max(min(y, 235), 16); Cb = max(min(y, 240), 16); Cr = max(min(y, 240), 16); - Rotem
你的YUV图像为什么有(3 * width * height)字节的数据? 难道它不应该有(1.5 * width * height)像素吗? - user972014
这段代码不完整且存在错误。需要排除类似 rgb_image[+1] 这样的问题。 - Force Gaia
看起来这里的一个缩放因子不正确。对于红色通道,这里使用的是1.4065,但与其他来源进行交叉检查表明正确的数字应该是1.4075。所有其他数字都与引用自数千个其他来源的数字完全匹配,但是这个数字略有不同,表明它被错误地复制了。 - Roger Sanders
1
这太令人印象深刻了,而且运行得非常顺畅。OpenCV变得很烦人,所以我直接从OpenBSD的v4l层抓取了网络摄像头的镜头。这个转换是缺失的一部分。另外,你是凭记忆打出来的吗?(for循环中i+=6 j+=4之间缺少逗号,这表明是这样)。所以这更加令人印象深刻 ;) - Karsten Pedersen

1
看这个: http://pastebin.com/mDcwqJV3 从YUYV到RGB24的定点转换
此外,一些相机以“UYVY”字节顺序返回原始图像,因此在转换函数中进行相应的更改。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接