Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

The final image is a single channel image of CV_8U. The size is rows = input.rows*3/2 cols = input.cols.

The first input.rows is the Y. This has full fidelity, the same as if you extracted the first channel from the BGR2YUV.

The next input.rows/4 is the V. This is downsampled by 2 in both the vertical and horizontal. So the first half of output.row(input.rows) is the first row of V, the second half is the second row of V.

Then is the U, which is packed the same way as the V, just in the last input.rows/4 rows of the output.

Make sense? Here's an image that should help. Those are the even rows and the odd rows.

image description

A not particularly efficient but easy to understand way of converting back is to do this. (assuming the original image size is divisible by four)

Mat YUV(mesh.rows * 2 / 3, mesh.cols, CV_8UC3);
insertChannel(mesh(Rect(0, 0, YUV.cols, YUV.rows)), YUV, 0);

Mat U = mesh(Rect(0, YUV.rows, YUV.cols, YUV.rows / 4));
imshow("U1", U);
U = U.reshape(1, YUV.rows / 2);
imshow("U2", U);
resize(U, U, Size(YUV.cols, YUV.rows));
insertChannel(U, YUV, 2);

Mat V = mesh(Rect(0, YUV.rows + YUV.rows/4, YUV.cols, YUV.rows / 4));
V = V.reshape(1, YUV.rows / 2);
resize(V, V, Size(YUV.cols, YUV.rows));
insertChannel(V, YUV, 1);

cvtColor(YUV, YUV, COLOR_YUV2BGR);
imshow("Restored", YUV);

It's a good thing I tested this. I originally had the U and V backwards.

The final image is a single channel image of CV_8U. The size is rows = input.rows*3/2 cols = input.cols.

The first input.rows is the Y. This has full fidelity, the same as if you extracted the first channel from the BGR2YUV.

The next input.rows/4 is the V. This is downsampled by 2 in both the vertical and horizontal. So the first half of output.row(input.rows) is the first row of V, the second half is the second row of V.

Then is the U, which is packed the same way as the V, just in the last input.rows/4 rows of the output.

Make sense? Here's an image that should help. Those are the even rows and the odd rows.

image description

A not particularly efficient but easy to understand way of converting back is to do this. (assuming the original image size is divisible by four)

Mat YUV(mesh.rows * 2 / 3, mesh.cols, CV_8UC3);
insertChannel(mesh(Rect(0, 0, YUV.cols, YUV.rows)), YUV, 0);

Mat U = mesh(Rect(0, YUV.rows, YUV.cols, YUV.rows / 4));
imshow("U1", U);
U = U.reshape(1, YUV.rows / 2);
imshow("U2", U);
resize(U, U, Size(YUV.cols, YUV.rows));
insertChannel(U, YUV, 2);

Mat V = mesh(Rect(0, YUV.rows + YUV.rows/4, YUV.cols, YUV.rows / 4));
V = V.reshape(1, YUV.rows / 2);
resize(V, V, Size(YUV.cols, YUV.rows));
insertChannel(V, YUV, 1);

cvtColor(YUV, YUV, COLOR_YUV2BGR);
imshow("Restored", YUV);

It's a good thing I tested this. I originally had the U and V backwards.

Except my reference is saying that U is first, then V. Hell, just try it. If it doesn't work _YV12 is the other way around.