4

我要做的是读取我的佳能 Rebel T5 1200D 上拍摄的 .cr2 RAW 文件。我可以使用 LibRaw 和 OpenCV 加载和显示图像,但是与我在 Windows 中打开文件时相比,图像看起来有点太亮并且更黄。图片本身在帖子的底部。有人问了几个类似的问题:

使用 LibRaw 正确解码 CR2 图像?

使用 OpenCV 将 12 位拜耳图像转换为 8 位 RGB

我将首先发布我的所有代码,然后进入问题的细节。

// Open the CR2 file with LibRaw, unpack, and create image
LibRaw lrProc;
assert( LIBRAW_SUCCESS == lrProc.open_file( "001.cr2" ) );
assert( LIBRAW_SUCCESS == lrProc.unpack() );
assert( LIBRAW_SUCCESS == lrProc.raw2image() );

// Get image dimensions
int width = lrProc.imgdata.sizes.iwidth;
int height = lrProc.imgdata.sizes.iheight;

// Create a buffer of ushorts containing the pixel values of the "BG Bayered" image
std::vector<ushort> vBayerData;
for ( int y = 0; y < height; y++ )
{
    for ( int x = 0; x < width; x++ )
    {
        // Get pixel idx
        int idx = y * width + x;

        // Each pixel is an array of 4 shorts rgbg
        ushort * uRGBG = lrProc.imgdata.image[idx];

        // Even rows are RGRGRG..., odd are GBGBGB...
        // For even rows, get either red or green, store in vec
        if ( y % 2 == 0 )
        {
            bool red = x % 2 == 0;
            vBayerData.push_back( uRGBG[red ? 0 : 1] );
        }
        // For odd rows, get either blue or green
        else
        {
            bool green = x % 2 == 0;
            vBayerData.push_back( uRGBG[green ? 3 : 2] );
        }
    }
}

// Get rid of libraw image, construct openCV mat
lrProc.recycle();
cv::Mat imgBayer( height, width, CV_16UC1, vBayerData.data() );

// Debayer image, get output
cv::Mat imgDeBayer;
cv::cvtColor( imgBayer, imgDeBayer, CV_BayerBG2RGB );

// The pixel color values were 12 bit, but our data is 16 bit
// transform the range [0, 4095] to [0:65535] (multiply by 16)
imgDeBayer *= 16;

// Display image
cv::namedWindow( "CR2 File", CV_WINDOW_FREERATIO );
cv::imshow( "CR2 File", imgDeBayer );
cv::waitKey();

我首先使用 LibRaw 打开并解压缩原始图像文件。这个例子在 LibRaw 的网站 http://www.libraw.org/docs/API-overview-eng.html

表示我将留下一个“图像”,其中每个像素是实际的 4 个 ushort 值 [Red, Green1, Blue, Green2] 代表该像素处的拜耳颜色。当我打印出值时(使用以下代码)

// Print the first 4 values of the first 4 rows
for ( int y = 0; y < 4; y++ )
{
    for ( int x = 0; x < 4; x++ )
    {
        int idx = y * width + x;
        ushort * uRGBG = lrProc.imgdata.image[idx];
        printf( "[%04d, %04d, %04d, %04d]  ", uRGBG[0], uRGBG[1], uRGBG[2], uRGBG[3] );
    }
    printf( "\n" );
}

我得到以下结果:

[2253, 0000, 0000, 0000]  [0000, 2166, 0000, 0000]  [2183, 0000, 0000, 0000]  [0000, 2195, 0000, 0000]
[0000, 0000, 0000, 2207]  [0000, 0000, 2175, 0000]  [0000, 0000, 0000, 2099]  [0000, 0000, 2122, 0000]
[2246, 0000, 0000, 0000]  [0000, 2240, 0000, 0000]  [2287, 0000, 0000, 0000]  [0000, 2182, 0000, 0000]
[0000, 0000, 0000, 2251]  [0000, 0000, 2103, 0000]  [0000, 0000, 0000, 2195]  [0000, 0000, 2155, 0000]

因此,在偶数行上,红色和绿色 1 像素交替具有非零值,而在奇数行上,蓝色和绿色 2 像素交替具有非零值。这些值似乎是 12 位的,尽管我不是 100% 的。

看OpenCV的cvtColor函数的描述

http://docs.opencv.org/2.4/modules/imgproc/doc/miscellaneous_transformations.html#cvtcolor

以及这个人对一些cr2颜色格式的描述:

http://lclevy.free.fr/cr2/#interpol

向我表明我有一个“BG”品种的拜耳图像(按照 OpenCV 文档中使用的术语。)

因此,为了将该图像传递给 cvtColor,我必须从解压缩的原始图像中获取每个像素值,并创建一个无符号短裤的连续图像。// 获取像素 idx int idx = y * width + x;

// Each pixel is an array of 4 shorts rgbg
ushort * uRGBG = lrProc.imgdata.image[idx];

// For even rows, get either red or green, store in vec
if ( y % 2 == 0 )
{
    bool red = x % 2 == 0;
    vBayerData.push_back( uRGBG[red ? 0 : 1] );
}
// For odd rows, get either blue or green
else
{
    bool green = x % 2 == 0;
    vBayerData.push_back( uRGBG[green ? 3 : 2] );
}

一旦我得到了一个连续的短裤缓冲区(vBayerData),我就构建了一个opencv mat并使用CV_BayerBG2RGB对其进行debayer。

然而,看看我打印出来的像素值告诉我​​这些值可能是 12 位的(虽然我不完全确定。)所以我必须从 12 位范围到 16 位范围,我相信相当于将这些值乘以 16。

// Construct bayer image from data
cv::Mat imgBayer( height, width, CV_16UC1, vBayerData.data() );

// Debayer image, get output
cv::Mat imgDeBayer;
cv::cvtColor( imgBayer, imgDeBayer, CV_BayerBG2RGB );

// The pixel color values were 12 bit, but our data is 16 bit
// transform the range [0, 4095] to [0:65535] (multiply by 16)
imgDeBayer *= 16;

毕竟,这是我留下的图像: OpenCV 输出

然而,这是我的眼睛看到的(抱歉缩放,颜色才是最重要的):

我在 Windows 中看到的

我觉得我离这里很近,但我得到的图像有点太亮而且颜色有点偏。我的相机上的设置是使用 sRGB 格式导出 RAW 图像,所以我确信对图像强度应用某种伽玛校正会有所帮助,但我似乎无法得到正确的图像。

我尝试了不同的拜耳矩阵(即 RG)、不同的位深度转换、在进行位深度转换时重新排列(在 DeBayering 之前和之后),但似乎都没有使图像正确显示。

有人认识这种变色吗?如果是这样,他们可以帮助我找到我的代码中的错误吗?

感谢您的阅读,

约翰

PS 我知道这里有很多文字,我不确定这种帖子的最佳格式是什么。我只是想提供我正在使用的所有信息。

编辑:正如 Mark Ransom 下面建议的那样,我认为这是由于白平衡不正确造成的。我被指出了数码相机颜色管道的方向,解码图像不仅仅是 debayer 步骤。

来自维基百科文章:

典型组件包括图像传感器校正(包括“去拜耳”或应用拜耳滤镜)、降噪、图像缩放、伽马校正、图像增强、色彩空间转换(在 RGB、YUV 或 YCbCr 等格式之间)、色度二次采样、帧率转换、图像压缩/视频压缩(如JPEG),计算机数据存储/数据传输。

4

0 回答 0