我希望使用openCV读取一个YUV视频,该视频分辨率为1920*1080,采用YUV422格式(我已尝试使用yuviewer读取此视频且成功)。我正在使用Python3.6.4和Anaconda环境下的OpenCV 3.3.1。
最初我尝试了这个脚本https://dev59.com/enE95IYBdhLWcg3wn_Rr#47815385,但是这行代码:
当我尝试将Y444或Y420转换为RGB、RGBA或GREY时,也遇到了这个错误。 在Google或Stackoverflow上没有找到完全相同的错误。 我尝试重新安装opencv包,但它没有起作用。 在我的脚本中,每个cvtColor都有效,除了最后一个。我所说的有效是指它显示了图像,但颜色不正确。
最初我尝试了这个脚本https://dev59.com/enE95IYBdhLWcg3wn_Rr#47815385,但是这行代码:
cv2.cvtColor(yuv, cv2.COLOR_YUV2BGR_Y422)
出现了这个错误。
File "read-yuv-video.py", line 29, in <module>
bgr = cv2.cvtColor(yuv, cv2.COLOR_YUV2BGR_UYVY)
cv2.error: C:\ci\opencv_1512688052760\work\modules\imgproc\src\color.cpp:11228: error: (-215) scn == 2 && depth == 0 in function cv::cvtColor
当我尝试将Y444或Y420转换为RGB、RGBA或GREY时,也遇到了这个错误。 在Google或Stackoverflow上没有找到完全相同的错误。 我尝试重新安装opencv包,但它没有起作用。 在我的脚本中,每个cvtColor都有效,除了最后一个。我所说的有效是指它显示了图像,但颜色不正确。
import numpy as np
import cv2
# filename = r'C:\myPath\voile.yuv'
filename = r'C:\myPath\credits.yuv'
yuv_file = open(filename, 'rb')
frame_len = 1920 * 1080 * 3/2
shape = (int(1080 * 1.5), 1920)
raw = yuv_file.read(int(frame_len))
yuv = np.frombuffer(raw, dtype=np.uint8)
yuv = yuv.reshape(shape)
yuv = cv2.resize(yuv, (0, 0), fx=0.5, fy=0.5)
cv2.imshow("raw yuv", yuv)
cv2.waitKey(0)
bgr = cv2.cvtColor(yuv, cv2.COLOR_YUV2BGR_NV21)
cv2.imshow("YUV2BGR_NV21", bgr)
cv2.waitKey(0)
bgr = cv2.cvtColor(yuv, cv2.COLOR_YUV2BGR_NV12)
cv2.imshow("YUV2BGR_NV12", bgr)
cv2.waitKey(0)
bgr = cv2.cvtColor(yuv, cv2.COLOR_YUV2BGR_I420)
cv2.imshow("YUV2BGR_I420", bgr)
cv2.waitKey(0)
bgr = cv2.cvtColor(yuv, cv2.COLOR_YUV2BGR_Y422)
cv2.imshow("YUV2BGR_Y422", bgr)
cv2.waitKey(0)
编辑
scn == 2 表示该函数需要一张包含两个通道的图像。 我更改了以下这些行:
frame_len = 1920 * 1080 * 2 # 4 Bytes for 2 pixels
shape = (height, width, 2) # To have a 2 channels image (not really working obviously)
现在cv2.cvtColor没有报错了,但仍然不能正常工作。我认为我的reshape完全错误。
我的结果:
我手动查看了numpy.array并与YUView比较了像素值和形状,符合我的预期(先是Y值,然后是U再是V),但这不是opencv显示的。
为什么在原始帧的Y矩阵下面有4个图像?
更准确地说,在我的情况下,输入cv2.cvtColor函数的数据应该是什么形状?
scn
表示“源图像的通道数”。| 不同的YUV变体使用不同数量的位来表示一个像素。例如,Y422每2个像素使用4字节,因此OpenCV期望一个2通道图像。显然情况并非如此,因为当您加载数据时,您加载了1.5字节/像素,并将其视为单通道。同样,Y444使用3字节/像素,因此如果输入图像实际上使用该格式,则会丢失一半的数据。 - Dan Mašek