Ask Your Question

YUV422 Packed format scaling

asked 2016-09-13 13:30:08 -0500

Srujan gravatar image

updated 2016-09-13 14:13:10 -0500

I am writing a scaling algorithm for YUV422 packed format images (without any intermediate conversions to RGB or grayscale or what have you). As can be seen in the below image from MSDN, the 4:2:2 format has 2 Luma bytes for each chroma byte. My test bench involves procuring images from the iSight camera using OpenCV APIs, converting them to YUV (CV_BGR2YUV) and then resizing them. The questions I have are:

  1. I am posting sample data (from OpenCV's Mat's pointer to raw data) for reference below straight from the memory dump, how do I identify by looking at the data as to what is the Y component and what the UV components are? 15 8B 7A 17 8A 7A 18 8A 7B 17 89 7A 19 89 79 19
  2. Is this bilinear interpolation algorithm correct? Let's say, my box is TOP ROW: Y00, U00, Y01, Y02, V00, Y03; BOTTOM ROW: Y10, U10, Y11, Y12, V10, Y13. Then the final pixels would be interpolated from: (Y00, Y01, Y10, Y11), (U00, U10, 0, 0), (Y02, Y03, Y12, Y13), (0, 0, V00, V10). That forms my first two YUYV pixels of 32 bits.

Any references to principles of performing bilinear interpolation on YUYV images would be very helpful! Thanks in advance.


edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted

answered 2016-09-13 20:00:35 -0500

Tetragramm gravatar image

Take a look at THIS ANSWER, which explains how the YUV image is stored in memory. You need to use the Mat constructor that takes a pointer to access each component separately, then resize them individually into an appropriately sized buffer.

For a 100 Rows, 100 Cols of RGB, you would have 150 Rows, 100 Cols of YUV422. So to double the size, you need a 300x200 buffer. Example code for a doubling of size is below. Note that I'm not sure which is U and which is V, but since you're just resizing, it doesn't matter.

Mat oldImg;
Mat newImg(300, 200, CV_8UC1);

Mat Y_in(100, 100, CV_8UC1, oldImg.ptr<uchar>(0));
Mat Y_out(200, 200, CV_8UC1, newImg.ptr<uchar>(0));
resize(Y_in, Y_out, Size(200, 200), 0, 0, INTER_LINEAR);

Mat U_in(50, 50, CV_8UC1, oldImg.ptr<uchar>(100));
Mat U_out(100, 100, CV_8UC1, newImg.ptr<uchar>(200));
resize(U_in, U_out, Size(100, 100), 0, 0, INTER_LINEAR);

Mat V_in(50, 50, CV_8UC1, oldImg.ptr<uchar>(125));
Mat V_out(100, 100, CV_8UC1, newImg.ptr<uchar>(250));
resize(V_in, V_out, Size(100, 100), 0, 0, INTER_LINEAR);

You get example code because I had to test it to make sure I wasn't giving you bad advice, and since it's already written...

edit flag offensive delete link more


Thanks a lot for your answer.

100x100 RGB image effectively has 3x100x100 bytes which when converted to YUV results in 3x100x100 bytes. Instead when this is converted to YUV2 (aka YUYV), this results in 4x100x100 bytes. And doubling the size of this image horizontally and vertically requires 4x(2x100)x(2x100). How do you get 150x100 and consequently 300x200?

Also, how do you plot this newImg?

Srujan gravatar imageSrujan ( 2016-09-14 00:28:12 -0500 )edit

Oh, I thought you were using the 4:2:2 packed YUV.

If you're using the 4:4:4 packed YUV, then it's just Y in the first channel, U in the second, and V in the third. Just use the resize function, and it will interpolate each channel separately.

You plot using the imshow function. Have you looked at the tutorials and documentation? They tell you a lot of this basic stuff.

Tetragramm gravatar imageTetragramm ( 2016-09-14 17:52:29 -0500 )edit

Question Tools

1 follower


Asked: 2016-09-13 13:30:08 -0500

Seen: 3,098 times

Last updated: Sep 13 '16