YUV2 数据的 Channel 和 Bit 值
Posted
技术标签:
【中文标题】YUV2 数据的 Channel 和 Bit 值【英文标题】:Channel and Bit values of a YUV2 data 【发布时间】:2012-07-18 12:49:57 【问题描述】:我有一个来自相机(PAL)的数据流 我从回调函数中得到的数据类型是 U0-Y0-V0-Y1 U2-Y2-V2-Y3 U4-Y4-V4-Y5 ......
我需要使用 OpenCV 的 cvCvtColor() 函数将颜色格式更改为 RGB(或 BGR)。该函数的用法是 cvCvtColor(YCrCb, dst, CV_YCrCb2BGR); 现在这里(实际上是之前)出现了问题,dst 是一个 3 通道 8U 图像,没关系,但是如何将来自回调函数的数据直接存储在 IplImage 中?如果我可以正确存储它,我可以使用 cvCvtColor() 来转换图像。任何功能,任何其他库? 如果我在每一帧中使用 RGBYUV 数学转换,这会导致 70%++ 的 CPU 使用率,所以我不想使用它们,我正在寻找更简单的 CPU 方法。
【问题讨论】:
【参考方案1】:如果您的输入格式是 YUY2,那么它实际上是 Y-U-Y-V,我下面的示例假设了这一点。但是,如果您的格式确实是 U-Y-V-Y,只需更改我示例中的顺序或颜色空间(请参阅下面的注释)。
您可以通过 2 通道 Mat 数组将此 YUY2/YUYV422 数据呈现给 OpenCV。
有两种方法可以填充 Mat img:通过复制和通过引用。根据您的应用程序,您可以选择其中任何一个。
两者都假设您在 char 数组 image_yuv
中有 yuv 数据。
1a。通过引用原始数据(没有 mem alloc;快速):
Mat img(height, width, CV_8UC2, img_yuv);
1b。通过将数据复制到 Mat 中:
Mat img(height, width, CV_8UC2);
uchar *pix = img.ptr<uchar>(r); // first byte of the row in image
for (int r = 0, b=0; r < height; r++)
for (int c = 0; c < width; c+=4)
*pix++ = image_yuv[b++]; // y
*pix++ = image_yuv[b++]; // u
*pix++ = image_yuv[b++]; // y
*pix++ = image_yuv[b++]; // v
现在您已经在 Mat img 中拥有了数据,您可以使用 cvtColor 将其转换为其他颜色空间:
2a。更改为 BGR:
cvtColor(img, img_p, COLOR_YUV2BGR_YUY2);
imshow("window", img_p);
2b。改为灰度:
cvtColor(img, img_p, COLOR_YUV2GRAY_YUY2);
imshow("window", img_p);
注意:如果您的格式是 U-Y-V-Y,请更改复制顺序或更改颜色空间(COLOR_YUV2BGR_UYVY 或 COLOR_YUV2GRAY_UYVY)。请参阅 OpenCV 源代码中的 imgproc.hpp。
【讨论】:
为什么使用 CV_8UC2? YUV2 (YUYV422) 是 OpenCV 中的双平面格式。首先是 Y 平面,其次是 U & V 交错平面。我的代码将 OP 的传入数据从U0-Y0-V0-Y1 U2-Y2-V2-Y3 ...
格式解包并打包为两计划 YUV2 OpenCV 格式,因此使用了CV_8UC2
。【参考方案2】:
我会像这样为帧缓冲区制作一个 Iplimage 标头:
IplImage* header = cvCreateImageHeader(cvSize(width,height), IPL_DEPTH_8U, 3);
headercopy->widthStep = width*3;//I hope this will right for you... :)
headercopy->imageData = (char*) bufferstart;
您现在可以将 Iplimage 标头用作普通的 Iplimage 希望就是这样。 对于转换,您可能需要分配一个新的 IplImage 对象!
【讨论】:
您的解决方案适用于 RGB 图像,如果 bufferLength 为 40(在 YUY2 中),则表示 RGB 的长度为 60 字节。但是您的代码通过假设 YUY2 的长度为 60 字节,直接将 YUY2 数据分配给 RGB 图像。因为 widthStep = widthStep*3 不适用于 YUY2。我可以通过一些计算找到widthStep,但是通道长度(3)将是另一个问题。我读过一些说法,例如 OpenCV 不直接支持 YUY 格式。需要自己进行转换:/ hmm 抱歉,现在我了解您的问题了...我认为 opencv 不会为您的数据流提供任何标准解决方案。如果我没看错,传感器输出 50% Y、25% U 和 25% V(看起来像 yuv 4:2:2 色度子采样)。这意味着您还必须对数据进行一些信号去马赛克处理。那种东西在opencv中没有实现(我不知道这些功能)。该信号仅知道每个像素的 Y(50%) 或 U(25%) 或 V(25%),因此您必须从邻居中重新插入另一个。你将不得不在这里做一些工程工作;)。【参考方案3】:IIRC openCV 不支持交错 YUV,它只支持平面 YUV420/YUV422,其中整个图像的 Y 数据首先是降低分辨率的 U 和 V(JPEG 使用)
您可以将数据重新排序到平面中,也可以使用formulae here 或此答案Converting YUV->RGB(Image processing)->YUV during onPreviewFrame in android? 中更快的整数版本自己生成 RGB 数据
【讨论】:
【参考方案4】:我还发现这段代码只是将 YUV 4:2:2 转换为 rgb 也许这可能有用.... convert YUV422 to RGB24(不是这个不是) 但也许我发现的这个其他网站可能更有用。他没有给出将图像转换为 opencv 标准 RGB24 的任何代码,因此您必须了解 c 代码并将其调整为 opencv 标准: http://wss.co.uk/pinknoise/yuv2rgb/
不知怎的,我找不到任何好的解决方案....
【讨论】:
以上是关于YUV2 数据的 Channel 和 Bit 值的主要内容,如果未能解决你的问题,请参考以下文章
netty4在channel.writeAndFlush为啥还阻塞延迟