OPENCV+Python实现8/10比特YUV2RGB

本文主要介绍使用OPENCV和Python进行YUV到RGB的转换,以及制作heatmap的部分函数

参考文档:
applyColorMap for pseudocoloring in OpenCV ( C++ / Python )
YUV2RGB Opencv

YUV格式与8/10比特介绍

一般来说,视频数据中的YUV为420格式,可以简单理解为图像中,含有四个Y分量的点的正方形包含1个U分量和1个V分量。UV分量的位置在正方形内或者边上,具体取决于采样的方法。

以416x240大小的帧为例,首先是416x240个Y像素点,按行存储在YUV文件中,从开头每读取416个数据即读取了一行。然后是416x240/4个U分量,同样按行存储,不过每行只有416/2个点,一共有240/2行。然后是与U分量相同的V分量。

8比特时,1个byte就是一个像素的数值,反映在numpy中即为uint8, 在opencv中为8U;10比特时,2个byte表示一个像素值,numpy的格式变为uint16,opencv中也为16U

读取,转换YUV像素值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 首先打开YUV文件为fyuv

# 分别读取YUV3个通道的值,使用fyuv.read读取数据到buffer中,然后根据bitdepth转换到对应的类型,reshape
if bitdepth==8:
buffer=fyuv.read(framew*frameh)
Y=np.frombuffer(buffer,dtype='uint8').reshape(frameh,framew)
buffer=fyuv.read(framew*frameh//4)
U=np.frombuffer(buffer,dtype='uint8').reshape(frameh//2,framew//2)
buffer=fyuv.read(framew*frameh//4)
V=np.frombuffer(buffer,dtype='uint8').reshape(frameh//2,framew//2)

elif bitdepth==10:
buffer=fyuv.read(framew*frameh*2)
Y=np.frombuffer(buffer,dtype='uint16').reshape(frameh,framew)
buffer=fyuv.read(framew*frameh//2)
U=np.frombuffer(buffer,dtype='uint16').reshape(frameh//2,framew//2)
buffer=fyuv.read(framew*frameh//2)
V=np.frombuffer(buffer,dtype='uint16').reshape(frameh//2,framew//2)

# 上采样UV分量,合并为444的YUV格式,然后再执行转换操作
enlarge_U = cv2.resize(U, (0, 0), fx=2.0, fy=2.0, interpolation=cv2.INTER_CUBIC)
enlarge_V = cv2.resize(V, (0, 0), fx=2.0, fy=2.0, interpolation=cv2.INTER_CUBIC)
img_YUV = cv2.merge([Y, enlarge_U, enlarge_V])
rgb=cv2.cvtColor(img_YUV,cv2.COLOR_YUV2BGR)

heatmap构建,叠加

1
2
3
4
# 输入为单通道灰度图
im_color = cv2.applyColorMap(gray_img, cv2.COLORMAP_JET)
# 加权
final=cv2.addWeighted(im_color, 0.7, rgb, 0.3, 0)

需补充:如何制作热图的颜色-像素值对应关系