模拟YUV420流供OpenCV读取,如何获取原始YUV420格式?
如何从UDP流获取原始YUV420p格式图像(而非OpenCV默认的BGR)
问题根源
你当前的流程里有两个关键环节导致拿到的是3通道BGR图像:
- FFmpeg推流时的自动编码:使用
-f mpegts推流时,FFmpeg会默认将原始YUV数据编码为MPEG-TS容器兼容的编码格式(通常是MPEG-2),而非直接传输原始YUV字节。 - OpenCV的默认解码行为:
VideoCapture读取流时,会调用FFmpeg解码器将编码后的视频解码为BGR格式(OpenCV的默认输出格式),因此得到(540, 960, 3)的形状。
解决方案
方案1:推原始YUV420p UDP流(推荐)
直接传输无封装的原始YUV数据,避免FFmpeg自动编码:
ffmpeg -stream_loop -1 -f rawvideo -s 960x540 -r 30 -pix_fmt yuv420p -i output.yuv -f rawvideo udp://127.0.0.1:23000
OpenCV读取时,需要手动指定原始视频参数(因为rawvideo没有元数据),并转换回YUV420p格式:
import cv2 # 配置视频参数 width = 960 height = 540 # 打开UDP流,指定FFmpeg后端 cap = cv2.VideoCapture('udp://127.0.0.1:23000', cv2.CAP_FFMPEG) # 设置宽高、帧率和像素格式标识 cap.set(cv2.CAP_PROP_FRAME_WIDTH, width) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height) cap.set(cv2.CAP_PROP_FPS, 30) cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('Y', 'U', 'V', '1')) while cap.isOpened(): ret, bgr_frame = cap.read() if not ret: break # 将BGR转换为YUV420p原始格式 yuv420p_frame = cv2.cvtColor(bgr_frame, cv2.COLOR_BGR2YUV_I420) print(yuv420p_frame.shape) # 输出(810, 960),符合预期的540*3/2 x 960 # 分离Y/U/V分量(可选) y = yuv420p_frame[:height, :] u = yuv420p_frame[height:height+height//2:2, ::2] v = yuv420p_frame[height+1:height+height//2:2, ::2] cap.release()
方案2:强制MPEG-TS封装原始YUV(兼容性较差)
如果必须使用MPEG-TS容器,可指定-c:v rawvideo让FFmpeg直接封装原始YUV,不做编码:
ffmpeg -stream_loop -1 -f rawvideo -s 960x540 -r 30 -pix_fmt yuv420p -i output.yuv -c:v rawvideo -f mpegts udp://127.0.0.1:23000
OpenCV读取时同样需要手动设置参数,流程和方案1一致,但部分环境下可能因为容器兼容性问题无法正常读取。
内容的提问来源于stack exchange,提问作者Ivan
相关产品推荐
相关产品推荐

