1

我有一个来自相机(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() 来转换图像。任何功能,任何其他库?如果我在每一帧中使用 RGB<->YUV 数学转换,这会导致 70%++ 的 CPU 使用率,所以我不想使用它们,我正在寻找一种更简单的 CPU 方法。

4

4 回答 4

4

如果您的输入格式是 YUY2,那么它实际上是 YUYV,我下面的示例假设了这一点。但是,如果您的格式确实是 UYVY,只需更改我的示例或颜色空间中的顺序(请参阅下面的注释)。

您可以通过 2 通道 Mat 数组将此 YUY2/YUYV422 数据呈现给 OpenCV。

有两种方法可以填充 Mat img:通过复制和通过引用。根据您的应用程序,您可以选择其中任何一种。

两者都假设您在 char 数组中有 yuv 数据image_yuv

1a。通过参考原始数据(没有内存分配;快速):

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);

注意:如果您的格式是 UYVY,请更改复制顺序或更改颜色空间(COLOR_YUV2BGR_UYVY 或 COLOR_YUV2GRAY_UYVY)。请参阅 OpenCV 源代码中的 imgproc.hpp。

于 2015-11-28T23:51:20.347 回答
0

IIRC openCV doesn't support interleaved YUV it only does planar YUV420/YUV422 where the Y data for the entire image is first followed by reduced resolution U and V (as used by JPEG)

You can either re-order the data into planes or simply generate the RGB data yourself using the formulae here or the faster integer version in this answer Converting YUV->RGB(Image processing)->YUV during onPreviewFrame in android?

于 2012-07-18T13:56:16.813 回答
0

我还发现此代码仅用于将 YUV 4:2:2 转换为 rgb,也许这可能有用.... 将 YUV422 转换为 RGB24(不,不是)但也许我发现的这个其他站点可能更有用。他没有提供任何将图像转换为 opencv 标准 RGB24 的代码,因此您必须了解 c 代码并将其改编为 opencv 标准: http ://wss.co.uk/pinknoise/yuv2rgb/

不知何故,我找不到任何好的解决方案....

于 2012-07-18T14:18:03.797 回答
0

我会为帧缓冲区制作一个 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 对象!

于 2012-07-18T13:21:42.987 回答