You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

模拟YUV420流供OpenCV读取,如何获取原始YUV420格式?

如何从UDP流获取原始YUV420p格式图像(而非OpenCV默认的BGR)

问题根源

你当前的流程里有两个关键环节导致拿到的是3通道BGR图像:

  1. FFmpeg推流时的自动编码:使用-f mpegts推流时,FFmpeg会默认将原始YUV数据编码为MPEG-TS容器兼容的编码格式(通常是MPEG-2),而非直接传输原始YUV字节。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 09:26:35