1

I have a data stream coming from a Camera(PAL) The data type I got from callback function is in a format like U0-Y0-V0-Y1 U2-Y2-V2-Y3 U4-Y4-V4-Y5 ......

I need to change the color format to RGB (or BGR) by using OpenCV's cvCvtColor() function. Usage of the function is cvCvtColor(YCrCb, dst, CV_YCrCb2BGR); Now here(actually before) comes the problem, dst is a 3 channel 8U image, thats OK, but how can I store the data coming from callback function in an IplImage directly ? If I can store it correctly, I can use cvCvtColor() to convert the image. Any function, any other libraries? If I use RGB<->YUV mathematical conversion in every frame, that results in 70%++ CPU usage so I don't want to use them, I'm looking for a more easier way for CPU.

Yunus Yurtturk
  • 509
  • 1
  • 8
  • 26

4 Answers4

4

If your input format is YUY2, then it is actually Y-U-Y-V and my example below assumes that. However, if your format is indeed U-Y-V-Y, just change the order in my example or color space (see notes below).

You can present this YUY2/YUYV422 data to OpenCV via a 2-channel Mat array.

There are two ways you can fill the Mat img: By copy and by reference. Depending on your application, you can choose either.

Both assume you have yuv data in a char array image_yuv.

1a. By reference to original data (without mem alloc; fast):

Mat img(height, width, CV_8UC2, img_yuv);

1b. By copying data into 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
    }
}

Now that you have your data in Mat img, you can use cvtColor to convert it to other color spaces:

2a. Change to BGR:

cvtColor(img, img_p, COLOR_YUV2BGR_YUY2);
imshow("window", img_p);

2b. Change to grayscale:

cvtColor(img, img_p, COLOR_YUV2GRAY_YUY2);
imshow("window", img_p);

Note: If your format is U-Y-V-Y, either change the copy order, or change color space (COLOR_YUV2BGR_UYVY or COLOR_YUV2GRAY_UYVY). See imgproc.hpp in OpenCV source code.

  • Why the CV_8UC2 were used? – Crawl.W Jun 30 '21 at 06:25
  • YUV2 (YUYV422) is a two plane format in OpenCV. First is the Y plane, and second is the U & V interleaved plane. My code unpacks and packs OP's incoming data from `U0-Y0-V0-Y1 U2-Y2-V2-Y3 ...` format to two-plan YUV2 OpenCV format, and hence, the use of `CV_8UC2`. – Kiran Maheriya Jul 01 '21 at 15:51
0

I would make a Iplimage header for the frame buffer like this:

    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;

You can now use the Iplimage header as a normal Iplimage hope that was it. For the conversion you will maybe need to allocate a new IplImage object!

jamk
  • 836
  • 1
  • 10
  • 24
  • Your solution work for RGB image, if bufferLength is 40 (in YUY2), that means lenght of RGB would be 60 bytes. But your code directly assigns YUY2 data to RGB image by assuming YUY2 is 60Bytes length. Because widthStep = widthStep*3 doesn't work for YUY2. I can find widthStep with a few calculation but then channel length(3) will be another problem. I read some sayings like OpenCV doesn't support YUY format's directly. One need to do conversion by himself :/ – Yunus Yurtturk Jul 18 '12 at 13:42
  • hmm sorry now I understand your problem... I think opencv will not have any standard solution for you data flow. If i see right the sensor outputs 50% Y 25% U and 25% V (looks like yuv 4:2:2 Chroma subsampling). This means you will have also to do some signal demosaicing for the data. That kind of things isn t implemented in opencv (I don t know the functions). This signal knows for every pixel only Y(50%) or U(25%) or V(25%) so you have to reinterpolate the other from neighbors. You will have to do some engeneer job here ;). – jamk Jul 18 '12 at 14:01
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?

Community
  • 1
  • 1
Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
0

I also found this code for just transforming YUV 4:2:2 to rgb maybe this could be usefull.... convert YUV422 to RGB24 (no this not) But maybe this other site I found could be more useful. He doesn t give any code for converting the image to opencv standard RGB24 so you will have to understand the c code and adapt it for opencv standard: http://wss.co.uk/pinknoise/yuv2rgb/

somehow I can t find any good solution....

Community
  • 1
  • 1
jamk
  • 836
  • 1
  • 10
  • 24