5

Is there a way to convert from RGB to YUYV (YUY 4:2:2) format? I noted that OpenCV has reverse operation, but not RGB to YUYV for some reason. Maybe someone can point to code which does that (even outside of OpenCV library)?

UPDATE

I found libyuv library which may work for this purpose by doing BGR to ARGB conversion and then ARGB to YUY2 format (hopefully this is the same as YUYV 4:2:2). But it doesn't seem to work. Do you happen to know what yuyv buffer dimensions/type should look like? What its stride?

To clarify YUYV and YUY2 are the same formats if it helps.

UPDATE 2 Here is my code of using libyuv library:

  Mat frame;
  // Convert original image im from BGR to BGRA for further use in libyuv
  cvtColor(im, frame, CVX_BGR2BGRA);
  // Actually libyuv requires ARGB (i.e. reverse of BGRA), so I swap channels here
  int from_to[] = { 0,3, 1,2, 2,1, 3,0 };
  mixChannels(&frame, 1, &frame, 1, from_to, 4);
  // This is the most confusing part. Not sure what argb_stride suppose to be - length of a row in bytes or size of single value in the array?
  const uint8_t* argb_data = frame.data;
  int argb_stride = 8;

  // Also it is not clear what size of yuyv frame should be since we duplicate one Y 
  Mat yuyv(frame.rows, frame.cols, CVX_8UC2);
  uint8_t* yuyv_data = yuyv.data;
  int yuyv_stride = 16;
  // Do actual conversion
  libyuv::ARGBToYUY2(argb_data, argb_stride, yuyv_data, yuyv_stride, 
  frame.cols, frame.rows);
  // Then I feed yuyv_data to video stream buffer and see green or purple image instead of video stream.

UPDATE 3

  Mat frame;
  cvtColor(im, frame, CVX_BGR2BGRA);

  // ARGB
  int from_to[] = { 0,3, 1,2, 2,1, 3,0 };
  Mat rgba(frame.size(), frame.type());
  mixChannels(&frame, 1, &rgba, 1, from_to, 4);
  const uint8_t* argb_data = rgba.data;
  int argb_stride = rgba.cols*4;

  Mat yuyv(rgba.rows, rgba.cols, CVX_8UC2);
  uint8_t* yuyv_data = yuyv.data;
  int yuyv_stride = width * 2;
  int res = libyuv::ARGBToYUY2(argb_data, argb_stride, yuyv_data, yuyv_stride, rgba.cols, rgba.rows);

enter image description here

Pavel Podlipensky
  • 8,201
  • 5
  • 42
  • 53
  • I don't guarantee, but [here](http://study.marearts.com/2012/11/yuv-color-format-444-422-411-simple.html) – Miki Oct 05 '16 at 14:57
  • @Miki do you know what the size/type of output array should be? What is the value of img_stride from example you've provided? – Pavel Podlipensky Oct 05 '16 at 17:59
  • I _suppose_ that the size and type is the same. The type should be 3 `uint8/uchar`, which is OpenCV is `Vec3b`. The stride is the length between the beginning of two consecutive rows, basically the number of columns if the data is continuous (you may need to multiply by 3 if you have 3 channels). – Miki Oct 05 '16 at 18:14
  • What's wrong with libyuv? Would you like to share your way to use it? – Alex Cohn Oct 05 '16 at 19:33
  • @AlexCohn please see update on my post - added code – Pavel Podlipensky Oct 05 '16 at 21:04
  • Stride should be 4*width and 2*width, respectively, unless your images have row padding. – Alex Cohn Oct 05 '16 at 21:34
  • @AlexCohn thanks, that helps, but now I get bluish image (see updated code listing and screenshot) – Pavel Podlipensky Oct 07 '16 at 00:57
  • @AlexCohn it seems like it got only blue channel for some reason – Pavel Podlipensky Oct 07 '16 at 01:03
  • 2
    I would check the original first. Maybe your assumption about ordering of channels there is incorrect. Another suspect is your display procedure: maybe it does not interpret YUY2 correctly. – Alex Cohn Oct 07 '16 at 04:16
  • 1
    It appears that although method is called ARGBToYUY2 it requires BGRA order of channels (not reverse). @AlexCohn thank you so much for support and ideas! – Pavel Podlipensky Oct 07 '16 at 16:57

1 Answers1

1

It appears that although method is called ARGBToYUY2 it requires BGRA order of channels (not reverse).

Pavel Podlipensky
  • 8,201
  • 5
  • 42
  • 53