使用OpenCV将YU12格式摄像头帧转换为RGB失败求助
解决OpenCV读取YU12编码摄像头帧异常及转RGB报错问题
首先咱们拆解下问题的核心根源:
- OpenCV的
VideoCapture.read()默认会自动将摄像头原始格式转换为BGR(3通道),但如果摄像头输出的是YU12(YV12)这类平面YUV格式,自动转换过程会出错,导致你拿到的raw_frame既不是正确的BGR,也不是原始的YU12单通道格式——这就是直接保存画面怪异、转RGB时通道数不匹配报错的原因。 - 从mplayer的输出来看,你的摄像头实际输出可能是
YUY2格式(mplayer识别为rawyuy2),它是自行转换为YV12显示的,这也能解释OpenCV自动转换失败的问题。
解决方案:强制读取原始帧+匹配格式转换
下面是修正后的代码,我会逐段说明关键改动:
import os import sys import cv2 videoSource = 0 def getFrame(): cv_cam_0 = cv2.VideoCapture(videoSource) if not cv_cam_0.isOpened(): raise Exception(f'video source: {videoSource} could not be opened') # 关键:禁止OpenCV自动转RGB/BGR,直接读取摄像头原始输出帧 cv_cam_0.set(cv2.CAP_PROP_CONVERT_RGB, 0) # 获取并打印摄像头实际fourcc编码,确认输出格式 codec_char_code = int(cv_cam_0.get(cv2.CAP_PROP_FOURCC)) a = chr(codec_char_code & 0xFF) b = chr((codec_char_code >> 8) & 0xFF) c = chr((codec_char_code >> 16) & 0xFF) d = chr((codec_char_code >> 24) & 0xFF) print(f'codec 4 char code: {a+b+c+d}') ret, raw_frame = cv_cam_0.read() if not ret: raise Exception('Failed to read frame') # 打印原始帧形状验证格式:YU12是单通道,1280x720的话形状应为(1080, 1280)(H*3//2, W) print(f'Raw frame shape: {raw_frame.shape}') # 根据实际编码选择对应转换方式 codec = a+b+c+d if codec == 'YV12' or codec == 'YU12': # YU12/YV12是平面4:2:0格式,用对应转换码 rgbFrame = cv2.cvtColor(raw_frame, cv2.COLOR_YUV2RGB_YV12) elif codec == 'YUY2': # 对应mplayer识别的YUY2格式 rgbFrame = cv2.cvtColor(raw_frame, cv2.COLOR_YUY2RGB) else: raise Exception(f'Unsupported codec: {codec}') # 原始YUV帧直接保存会显示异常(平面格式特性),转换后的RGB帧可正常显示 cv2.imwrite('/tmp/test0.jpg', raw_frame) cv2.imwrite('/tmp/testConvert.jpg', rgbFrame) # 释放摄像头资源 cv_cam_0.release() def main(args): getFrame() sys.exit() if __name__ == "__main__": main(sys.argv)
关键改动说明
- 禁止自动格式转换:通过
cv2.CAP_PROP_CONVERT_RGB = 0让OpenCV直接读取摄像头原始输出,避免自动转换导致的格式错乱。 - 确认实际编码:打印fourcc编码,明确摄像头输出格式(是YU12还是YUY2),对应选择正确的转换常数。
- 匹配颜色空间转换:
- 对于YU12/YV12,使用
cv2.COLOR_YUV2RGB_YV12(注意YU12是Y-V-U平面顺序,和I420的Y-U-V顺序不同,不能混用转换码); - 对于YUY2,使用
cv2.COLOR_YUY2RGB。
- 对于YU12/YV12,使用
之前报错的原因
你之前的代码中,OpenCV尝试自动将原始YUV转换为BGR但失败,导致raw_frame变成了错误的3通道数组。而cv2.COLOR_YUV2RGB_I420要求输入是单通道的平面YUV帧,因此抛出了Invalid number of channels in input image的错误。
内容的提问来源于stack exchange,提问作者EgOPhil
相关产品推荐
相关产品推荐

