Ask Your Question
0

How to get Y, U, V from image

asked 2016-08-12 08:37:58 -0600

electron gravatar image

I use OpenCV 3.0 in Python3.4. I have BGR image converted to YUV420:

out_image = cv2.cvtColor(in_image, cv2.COLOR_BGR2YUV_I420)

How to get Y, U, V values from out_image?

edit retag flag offensive close merge delete

Comments

do you really need BGR2YUV_I420, or would BGR2YUV do ? (mucho easier case !!)

berak gravatar imageberak ( 2016-08-12 10:14:13 -0600 )edit
1

I need YUV420, not YUV. so BGR2YUV_I420, not BGR2YUV

electron gravatar imageelectron ( 2016-08-12 10:15:57 -0600 )edit

thanks for the clarification, but count me out then, - no idea how it's packed (or even padded) into bytes.

berak gravatar imageberak ( 2016-08-12 10:19:50 -0600 )edit
1

btw i don't sure that convertion works properly because saved on disc out_image looks strange

electron gravatar imageelectron ( 2016-08-12 10:20:56 -0600 )edit
1

not sure, if that format is even meant to be used as an image. (it's probably more something like : compress it to go over some wire, decompress back on the other side)

berak gravatar imageberak ( 2016-08-12 10:26:32 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
2

answered 2016-08-12 17:30:06 -0600

Tetragramm gravatar image

updated 2016-08-12 17:32:22 -0600

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.

edit flag offensive delete link more

Comments

thanks! i will try it

electron gravatar imageelectron ( 2016-08-14 15:58:28 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2016-08-12 08:37:58 -0600

Seen: 7,953 times

Last updated: Aug 12 '16