简体   繁体   English

将 Bayer 编码 (RGGB) 和 16 位深度的 RAW 图像转换为 RGB:最终图像太暗并且偏绿 (Rust)

[英]Convert RAW-image in Bayer-encoding (RGGB) and 16 bit depth to RGB: Final image is too dark and has a greenish cast (Rust)

I use a Rust library to parse raw ARW images (Sony Raw Format).我使用 Rust 库来解析原始 ARW 图像(索尼原始格式)。 I get a raw buffer of 16 bit pixels, it gives me the CFA (Color Filter Array) (which is RGGB), and the data buffer contains height * width pixels in bayer encoding.我得到一个 16 位像素的原始缓冲区,它为我提供了 CFA(滤色器阵列)(即 RGGB),并且数据缓冲区包含拜耳编码中的高度 * 宽度像素。 Each pixel is stored as 16 bit (however, I think the camera only uses 12 or 14 of the 16 bits for each pixel).每个像素存储为 16 位(但是,我认为相机每个像素只使用 16 位中的 12 或 14 位)。

I'm using a Bayer library for the demosaicing process.我正在使用拜耳库进行去马赛克处理。 Currently, my final image is too dark and has a greenish cast after the demosaic process.目前,我的最终图像太暗,在去马赛克过程后呈现绿色。 I guess the error is that before I pass the data to the bayer library, I try to transform each 16 bit value to 8 bit by dividing it by u16::max and multiplying it with u8::max .我猜错误是在我将数据传递给拜耳库之前,我尝试通过将每个 16 位值除以u16::max并将其与u8::max相乘来将其转换为 8 位。 However, I don't know if this is the right approach.但是,我不知道这是否是正确的方法。

I guess I need to perform additional steps between the parsing of the raw file and passing it to the bayer library.我想我需要在解析原始文件和将其传递给拜耳库之间执行额外的步骤。 May I have any advice, please?请问我有什么建议吗?

I can ensure that at least some demosaicing works.我可以确保至少有一些去马赛克效果。 Here's a screenshot of the resulting image:这是结果图像的屏幕截图:

去马赛克尝试(深色和太多绿色)

Current Code当前代码

The libraries I'm using are rawloader and bayer我使用的库是rawloaderbayer

let decoded_raw = rawloader::decode_file(path).unwrap();
let decoded_image_u16 = match &decoded_raw.data {
    RawImageData::Integer(data) => data,
    RawImageData::Float(_) => panic!("not supported yet"),
};

// u16 to u8 (this is probably wrong)
let mut decoded_image_u8 = decoded_image_u16
    .iter()
    .map(|val| {
        // todo find out how to interpret the u16!
        let val_f32 = *val as f32;
        let u16_max_f32 = u16::MAX as f32;
        let u8_max_f32 = u8::MAX as f32;
        (val_f32 / u16_max_f32 * u8_max_f32) as u8
    })
    .collect::<Vec<u8>>();

// prepare final RGB buffer
let bytes_per_pixel = 3; // RGB
let mut demosaic_buf = vec![0; bytes_per_pixel * decoded_raw.width * decoded_raw.height];
let mut dst = bayer::RasterMut::new(
    decoded_raw.width,
    decoded_raw.height,
    bayer::RasterDepth::Depth8,
    &mut demosaic_buf,
);

// DEMOSAIC
// adapter so that `bayer::run_demosaic` can read from the Vec
let mut decoded_image_u8 = ReadableByteSlice::new(decoded_image_u8.as_slice());

bayer::run_demosaic(
    &mut decoded_image_u8,
    bayer::BayerDepth::Depth8,
    // RGGB is definitely right for my AWR file
    bayer::CFA::RGGB,
    bayer::Demosaic::Linear,
    &mut dst,
)
.unwrap();

I'm not sure if this is connected to the actual problem, but your conversion is way overkill.我不确定这是否与实际问题有关,但您的转换太过分了。

To convert from the full range of a u16 to the full range of a u8 , use:要从u16的整个范围转换为u8的整个范围,请使用:

(x >> 8) as u8
fn main() {
    let convert = |x: u16| (x >> 8) as u8;

    println!("{} -> {}", 0, convert(0));
    println!("{} -> {}", 30000, convert(30000));
    println!("{} -> {}", u16::MAX, convert(u16::MAX));
}
0 -> 0
30000 -> 117
65535 -> 255

I might be able to help you further if you post the input image, but without being able to reproduce your problem I don't think there will be much else here.如果您发布输入图像,我可能会进一步帮助您,但如果无法重现您的问题,我认为这里不会有太多其他问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM