Дебайеринг изображения Canon CR2 с помощью OpenCV

Я пытаюсь прочитать RAW-файл.cr2 на моем Canon Rebel T5 1200D. Я могу загрузить и отобразить изображение, используя LibRaw и OpenCV, но изображение кажется слишком ярким и немного более желтым, чем при открытии файла в Windows. Сами изображения находятся внизу поста. Было задано несколько похожих вопросов:

Использование LibRaw для правильного декодирования изображения CR2?

Преобразование 12-битного изображения Байера в 8-битный RGB с использованием OpenCV

Сначала я опубликую весь свой код, а затем подробно расскажу о проблеме.

// 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-кратные значения [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]

Таким образом, в четных строках пиксели Red и Green1 имеют альтернативно ненулевые значения, а в нечетных строках пиксели Blue и Green2 имеют альтернативно нулевые значения. Значения кажутся 12-битными, хотя я не на 100% в этом.

Глядя на описание функции OpenCV cvtColor

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

А также описание этого человека некоторых цветовых форматов cr2:

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

Указывает на то, что у меня есть изображение Bayered разновидности "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 и разлагаю его, используя CV_BayerBG2RGB.

Тем не менее, просмотр значений пикселей, которые я распечатал, показывает, что значения, вероятно, 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

Я чувствую себя так близко, но изображение, которое я получаю, слишком яркое и немного не в цвете. Настройки на моей камере - экспорт изображений в формате RAW с использованием формата sRGB, поэтому я был уверен, что применение гамма-коррекции к интенсивности изображения поможет, но я не могу вывести правильное изображение.

Я пробовал разные матрицы Байера (т. Е. RG), разные преобразования глубины в битах, реорганизацию, когда я выполняю преобразование глубины в битах (до и после дебейринга), но ни одна из них не позволяет правильно отобразить изображение.

Кто-нибудь признает этот вид обесцвечивания? И если да, могут ли они помочь мне найти ошибку в моем коде?

Спасибо за чтение,

Джон

PS Я знаю, что здесь много текста, я не был уверен, какой формат был для такого поста. Я просто хотел предоставить всю информацию, с которой я работаю.

РЕДАКТИРОВАТЬ: как Марк Рэнсом предложил ниже, я думаю, что это связано с неправильным балансом белого. Я был направлен в сторону цветового конвейера цифровой камеры, и расшифровка изображения - это гораздо больше, чем просто шаг дебайера.

Из статьи в Википедии:

Типичные компоненты включают в себя коррекцию датчика изображения (включая "распад" или применение фильтра Байера), уменьшение шума, масштабирование изображения, гамма-коррекцию, улучшение изображения, преобразование цветового пространства (между форматами, такими как RGB, YUV или YCbCr), субсэмплирование цветности, преобразование частоты кадров, сжатие изображений / сжатие видео (например, JPEG) и хранение данных на компьютере / передача данных.

0 ответов

Другие вопросы по тегам