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

YCBCR_420_888转RAW10的正确方法及RAW10尺寸计算咨询

YCbCr420_888转RAW10的可行性与问题修正

一、核心问题:转换可行性

YCbCr420_888是经过色彩插值、白平衡、伽马校正等后期处理的成品色彩格式,而RAW10是相机传感器直接输出的原始数据——每个像素对应传感器拜耳阵列上的一个单色感光单元,存储的是未经过任何色彩处理的光电信号。

两者本质完全不同:你无法从成品YCbCr还原出真实的RAW10数据,因为YCbCr已经丢失了传感器原始信息(比如拜耳阵列的单通道感光值、原生增益、暗电流等)。你能做的只是模拟一个符合RAW10文件格式的文件,但这和真实相机输出的RAW不是一回事。

二、RAW10的正确尺寸计算

RAW10采用紧凑打包存储:每4个10bit像素打包成5个字节(4×10bit=40bit=5字节),总字节数的正确计算方式为:

// 方法1:按总比特数向上取整转字节
size_t total_bytes = ((width * height * 10) + 7) / 8;
// 方法2:按4像素打包的规则计算(更精准)
size_t total_bytes = ((width * height) + 3) / 4 * 5;

你之前的计算都不符合RAW10的存储规则:

  • width * height:仅为8bit单通道的字节数,RAW10每个像素占1.25字节,完全错误
  • width * height * 5 / 2:每个像素按2.5字节计算,是RAW10的2倍
  • width * height * sizeof(uint16_t):按16bit/像素存储,浪费了6bit空间,不是RAW10的紧凑格式

三、你的转换函数的错误分析

  1. 存储结构完全错误:RAW10是拜耳阵列的单通道10bit像素打包,而非Y/Cb/Cr通道分离存储,你直接把Y按8bit、Cb/Cr按16bit拼接,完全不符合RAW10格式规范。
  2. 色彩模型混淆:RAW10没有Y/Cb/Cr的概念,硬塞三个通道的数据必然导致色彩错位(你看到的紫丁香色就是Cb/Cr通道错位的结果)。
  3. 尺寸分配错误:未按RAW10的正确字节数初始化dst_raw,导致数据溢出或空白区域。

四、模拟生成RAW10格式文件的正确思路

如果只是需要生成符合RAW10格式的文件(而非真实传感器RAW),可以按以下步骤操作:

  1. 将YCbCr420转换为RGB:使用标准YCbCr转RGB公式:
    uint8_t y = yPlane[y_idx * width + x_idx];
    uint8_t cb = cbPlane[(y_idx/2) * (width/2) + (x_idx/2)];
    uint8_t cr = crPlane[(y_idx/2) * (width/2) + (x_idx/2)];
    int r = y + 1.402 * (cr - 128);
    int g = y - 0.344136 * (cb - 128) - 0.714136 * (cr - 128);
    int b = y + 1.772 * (cb - 128);
    // 钳位到0-255
    r = std::clamp(r, 0, 255);
    g = std::clamp(g, 0, 255);
    b = std::clamp(b, 0, 255);
    
  2. 模拟拜耳阵列排列:选择常见的拜耳模式(比如RGGB),每个像素位置取对应的RGB通道值,扩展为10bit(8bit值左移2位,高2位补0):
    uint16_t raw_val;
    if ((y_idx % 2 == 0 && x_idx % 2 == 0) || (y_idx % 2 == 1 && x_idx % 2 == 1)) {
        // G通道位置
        raw_val = (uint16_t)g << 2;
    } else if (y_idx % 2 == 0 && x_idx % 2 == 1) {
        // R通道位置
        raw_val = (uint16_t)r << 2;
    } else {
        // B通道位置
        raw_val = (uint16_t)b << 2;
    }
    
  3. 按RAW10规则打包字节:每4个10bit像素打包为5个字节:
    // 初始化dst_raw为正确尺寸
    dst_raw.resize(total_bytes, 0);
    size_t byte_idx = 0;
    std::vector<uint16_t> raw_values(width * height);
    // 先填充raw_values数组(省略拜耳填充逻辑)
    for (int i = 0; i < width * height; i += 4) {
        // 获取4个连续的10bit值
        uint16_t p0 = raw_values[i];
        uint16_t p1 = (i+1 < width*height) ? raw_values[i+1] : 0;
        uint16_t p2 = (i+2 < width*height) ? raw_values[i+2] : 0;
        uint16_t p3 = (i+3 < width*height) ? raw_values[i+3] : 0;
        
        // 打包成5个字节
        dst_raw[byte_idx++] = (p0 >> 2) & 0xFF; // p0高8位
        dst_raw[byte_idx++] = (p1 >> 2) & 0xFF; // p1高8位
        dst_raw[byte_idx++] = (p2 >> 2) & 0xFF; // p2高8位
        dst_raw[byte_idx++] = (p3 >> 2) & 0xFF; // p3高8位
        dst_raw[byte_idx++] = ((p0 & 0x03) << 6) | ((p1 & 0x03) << 4) | ((p2 & 0x03) << 2) | (p3 & 0x03);
    }
    

注意事项

  • 模拟的RAW10文件仅能满足格式兼容需求,无法达到真实相机RAW的动态范围和色彩还原能力。
  • 部分RAW10格式要求行对齐(比如每行字节数为16的倍数),需要在每行末尾补充填充字节。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 16:30:55