使用 OpenCV 从 BGR 转换为 YUYV Python

Conversion from BGR to YUYV with OpenCV Python

我一直在尝试将 BGR 捕获的帧转换为 YUYV 格式。

在 OpenCV Python 中,我可以使用 COLOR_YUV2BGR_YUY2 转换代码将 YUYV 转换为 BGR,但我无法执行此操作的反向操作(此操作没有转换代码,我试过 COLOR_BGR2YUV 但它没有正确转换)。我很好奇如何将3通道BGR帧转换为2通道YUYV帧

在这里您可以看到我用来更改相机模式以捕获 YUYV 并将其转换为 BGR 的代码,我正在寻找 cap.set(cv2.CAP_PROP_CONVERT_RGB, 0) 的替代品以便我可以捕获 BGR 并将其转换为没有 cap.set(cv2.CAP_PROP_CONVERT_RGB, 0) 的 YUYV(因为它是一个可选的捕获设置并且 Windows DirectShow 忽略此标志)

import cv2
import numpy as np

cap = cv2.VideoCapture(4)
_, frame = cap.read()
cap.set(cv2.CAP_PROP_CONVERT_RGB, 0)  # How to replace this line with another BGR to YUYV conversion?
_, frame_rgb_off = cap.read()
bgr_cvt = cv2.cvtColor(frame_rgb_off, cv2.COLOR_YUV2BGR_YUY2)

这里是显示帧内容的调试器输出:

Link to the screenshot

我试图了解 YUYV 格式,但它只有 2 个通道,下采样过程非常复杂。我已经检查了 YUYV 到 BGR 的转换方法,但我找不到数学转换方法(解决方案通常是从命令行使用 ffmpeg 实用程序,但我认为我需要用 numpy 数组进行数学转换)

您可以使用以下代码将图像转换为 YUV,然后从 YUV 创建 YUYV。 在此示例中,图像作为程序的输入:

import cv2
import numpy as np

# Load sample image
img_bgr = cv2.imread("home.jpg")
cv2.imshow("original", img_bgr)
cv2.waitKey(0)

# Convert from BGR to YUV
img_yuv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2YUV)

# Converting directly back from YUV to BGR results in an (almost) identical image
img_bgr_restored = cv2.cvtColor(img_yuv, cv2.COLOR_YUV2BGR)
cv2.imshow("converted", img_bgr_restored)
cv2.waitKey(0)
diff = img_bgr.astype(np.int16) - img_bgr_restored
print("mean/stddev diff (BGR => YUV => BGR)", np.mean(diff), np.std(diff))

# Create YUYV from YUV
y0 = np.expand_dims(img_yuv[...,0][::,::2], axis=2)
u = np.expand_dims(img_yuv[...,1][::,::2], axis=2)
y1 = np.expand_dims(img_yuv[...,0][::,1::2], axis=2)
v = np.expand_dims(img_yuv[...,2][::,::2], axis=2)
img_yuyv = np.concatenate((y0, u, y1, v), axis=2)
img_yuyv_cvt = img_yuyv.reshape(img_yuyv.shape[0], img_yuyv.shape[1] * 2, 
int(img_yuyv.shape[2] / 2))

# Convert back to BGR results in more saturated image.
img_bgr_restored = cv2.cvtColor(img_yuyv_cvt, cv2.COLOR_YUV2BGR_YUYV)
cv2.imshow("converted", img_bgr_restored)
cv2.waitKey(0)

diff = img_bgr.astype(np.int16) - img_bgr_restored
print("mean/stddev diff (BGR => YUV => YUYV => BGR)", np.mean(diff), np.std(diff))