Reputation: 1265
I need to convert a RGB uint8 720x480x3 numpy array into a YUV422 uint8 720x480x2 array. How can I do this with OpenCV? If OpenCV doesn't support it, is there another Python framework that will?
Upvotes: 0
Views: 3897
Reputation: 32084
The RGB to YUV conversion formula you posted in your comment is not supported by OpenCV.
You may implement the conversion "manually" using NumPy:
float
.uint8
and convert to np.uint8
type.Here is a code sample:
import numpy as np
import cv2
# Prepare BGR input (OpenCV uses BGR color ordering and not RGB):
bgr = cv2.imread('chelsea.png')
bgr = cv2.resize(bgr, (150, 100)) # Resize to even number of columns
# Split channles, and convert to float
b, g, r = cv2.split(bgr.astype(float))
rows, cols = r.shape
# Compute Y, U, V according to the formula described here:
# https://developer.apple.com/documentation/accelerate/conversion/understanding_ypcbcr_image_formats
# U applies Cb, and V applies Cr
# Use BT.709 standard "full range" conversion formula
y = 0.2126*r + 0.7152*g + 0.0722*b
u = 0.5389*(b-y) + 128
v = 0.6350*(r-y) + 128
# Downsample u horizontally
u = cv2.resize(u, (cols//2, rows), interpolation=cv2.INTER_LINEAR)
# Downsample v horizontally
v = cv2.resize(v, (cols//2, rows), interpolation=cv2.INTER_LINEAR)
# Convert y to uint8 with rounding:
y = np.round(y).astype(np.uint8)
# Convert u and v to uint8 with clipping and rounding:
u = np.round(np.clip(u, 0, 255)).astype(np.uint8)
v = np.round(np.clip(v, 0, 255)).astype(np.uint8)
# Interleave u and v:
uv = np.zeros_like(y)
uv[:, 0::2] = u
uv[:, 1::2] = v
# Merge y and uv channels
yuv422 = cv2.merge((y, uv))
Upvotes: 4