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

YU12转YUYV转换后图像出现噪点问题求助

问题排查与修复方案

核心原因:填充数据导致色彩平面偏移

640×480分辨率的YU12格式,理论总字节数为:

  • Y平面:640*480 = 307200 字节
  • U/V平面各为:(640/2)*(480/2) = 76800 字节
  • 总计:307200 + 76800*2 = 460800 字节,与v4l2-ctl查询结果一致。

你拿到的输入数据多了2048字节,这是V4L2设备为内存对齐自动添加的帧填充数据,通常附加在每帧末尾。你的原转换函数直接按理论长度截取Y/U/V平面,相当于把部分填充数据误纳入U/V平面,导致色彩采样错位,最终产生噪点。

修复方案

先截断多余的填充数据,只保留有效图像部分再进行转换,修改后的函数如下:

pub fn yu12_to_yuyv(resolution: Resolution, data: &[u8]) -> Vec<u8> {
    let width = resolution.width_x as usize;
    let height = resolution.height_y as usize;
    let y_size = width * height;
    let uv_plane_size = (width / 2) * (height / 2);
    let expected_total_size = y_size + uv_plane_size * 2;

    // 截断填充数据,仅保留有效图像字节
    let valid_data = if data.len() > expected_total_size {
        &data[0..expected_total_size]
    } else {
        data
    };

    // 提取正确的Y/U/V平面
    let y_plane = &valid_data[0..y_size];
    let u_plane = &valid_data[y_size..(y_size + uv_plane_size)];
    let v_plane = &valid_data[(y_size + uv_plane_size)..];

    let mut yuyv = Vec::with_capacity(y_size * 2);

    for y in 0..height {
        for x in (0..width).step_by(2) {
            let y_index1 = y * width + x;
            let y_index2 = y * width + x + 1;
            let uv_index = (y / 2) * (width / 2) + (x / 2);

            let y1 = y_plane[y_index1];
            let y2 = y_plane[y_index2];
            let u = u_plane[uv_index];
            let v = v_plane[uv_index];

            yuyv.extend_from_slice(&[y1, u, y2, v]);
        }
    }

    yuyv
}

额外验证建议

  • 确认转换后YUYV数据长度为640*480*2 = 614400字节,确保有效数据未丢失。
  • 若仍有问题,可在Droidcam设置中尝试强制输出无填充的YU12格式,减少裁剪操作的开销。

内容的提问来源于stack exchange,提问作者Ajay Pillay

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 00:53:09