我正试图通过python使用OpenCV 4.1.0版将平面YUV 4:2:0图像转换为RGB,并且正在努力理解如何格式化数组以传递给cvtColor
函数。我将所有3个通道作为单独的阵列,并尝试将它们合并以与cv2.cvtColor
一起使用。我正在使用cv2.cvtColor(yuv_array, cv2.COLOR_YUV420p2RGB)
。我知道yuv_array
应该是原始图像的1.5倍高(这就是使用cv2.COLOR_RGB2YUV_YV12
的cvtColor
的yuv阵列的样子),我应该将UV组件放入yuv_array
的下半部分,将Y通道放入阵列的顶部
我似乎不知道U和V通道应该如何在这个数组的底部格式化。我试着把它们交错放在一起,然后把它们两个连在一起。在这两种方法中,我都试着先放U,然后放V,反之亦然。所有方法都会导致结果图像中出现瑕疵。以下是我的代码和示例图像:
import os
import errno
import numpy as np
import cv2
fifo_names = ["/tmp/fifos/y_fifo", "/tmp/fifos/u_fifo", "/tmp/fifos/v_fifo"]
#teardown; delete fifos
import signal, sys
def cleanup_exit(signal, frame):
print ("cleaning up!")
for fifo in fifo_names:
os.remove(fifo)
sys.exit(0)
signal.signal(signal.SIGINT, cleanup_exit)
signal.signal(signal.SIGTERM, cleanup_exit)
#make fifos
for fifo in fifo_names:
try:
os.mkfifo(fifo);
except OSError as oe:
if oe.errno == errno.EEXIST:
os.remove(fifo)
os.mkfifo(fifo)
else:
raise()
#make individual np arrays to store Y,U, and V channels
#we know the image size beforehand -- 640x360 pixels
yuv_data = []
frame_size = []
fullsize = (360, 640)
halfsize = (180, 320)
for i in range(len(fifo_names)):
if (i == 0):
size = fullsize
else:
size = halfsize
yuv_data.append(np.empty(size, dtype=np.uint8));
frame_size.append(size)
#make array that holds all yuv data for display with cv2
all_yuv_data = np.empty((fullsize[0] + halfsize[0], fullsize[1]), dtype=np.uint8)
#continuously read yuv images from fifos
print("waiting for fifo to be written to...")
while True:
for i in range(len(fifo_names)):
fifo = fifo_names[i]
with open(fifo, 'rb') as f:
print("FIFO %s opened" % (fifo))
all_data = b''
while True:
data = f.read()
print("read from %s, len: %d" % (fifo,len(data)))
if len(data) == 0: #then the fifo has been closed
break
else:
all_data += data
yuv_data[i] = np.frombuffer(all_data, dtype=np.uint8).reshape(frame_size[i])
#stick all yuv data in one buffer, interleaving columns
all_yuv_data[0:fullsize[0],0:fullsize[1]] = yuv_data[0]
all_yuv_data[fullsize[0]:,0:fullsize[1]:2] = yuv_data[1]
all_yuv_data[fullsize[0]:,1:fullsize[1]:2] = yuv_data[2]
#show each yuv channel individually
cv2.imshow('y', yuv_data[0])
cv2.imshow('u', yuv_data[1])
cv2.imshow('v', yuv_data[2])
#convert yuv to rgb and display it
rgb = cv2.cvtColor(all_yuv_data, cv2.COLOR_YUV420p2RGB);
cv2.imshow('rgb', rgb)
cv2.waitKey(1)
上面的代码正在尝试按列交错U和V信息
我还尝试使用以下方法将U和V通道信息放入all_yuv_data
数组中:
#try back-to-back
all_yuv_data[0:fullsize[0],0:fullsize[1]] = yuv_data[0]
all_yuv_data[fullsize[0]:,0:halfsize[1]] = yuv_data[1]
all_yuv_data[fullsize[0]:,halfsize[1]:] = yuv_data[2]
该图像是通过libav从另一个程序获得的视频帧。框架的格式为AV_PIX_FMT_YUV420P
,described as“平面YUV 4:2:0,12bpp,(每2x2y样本1个Cr&Cb样本)”
以下是以灰度显示的示例图像的yuv通道:
Y频道:
U频道:
V频道:
以及相应的RGB转换(这是使用上述交错方法得出的,使用“背对背”方法时可以看到类似的伪影):
带有瑕疵的RGB图像:
我应该如何将u和v通道信息放置在all_yuv_data
中
由Mark Setchell在此点之后编辑
我相信预期的结果是:
此函数调用中
yuv_array
底部存储的u和v通道信息:cv2.cvtColor(yuv_array, cv2.COLOR_YUV420p2RGB)
预期的格式如下所示:
yuv_data
的右侧插槽中,依此类推李>以下是将MarkSetchnell放置在原始程序中时生成预期图像的连接代码:
以下是所有_yuv_数据的灰度图像,以确保清晰:
以及调用
cv2.cvtColor(all_yuv_data, cv2.COLOR_YUV420p2RGB)
后的结果 :如果YUV标准与OpenCV
COLOR_YUV2BGR_I420
转换公式相匹配,则可以将帧作为一个块读取,并将其重塑为高度*1.5行应用转换以下代码示例:
COLOR_YUV2BGR_I420
将其转换为BGR。颜色不正确李>
COLOR_YCrCb2BGR
转换来重复该过程。注意:OpenCV使用BGR颜色格式(非RGB)李>
代码如下:
结果:
相关问题 更多 >
编程相关推荐