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

Я пытаюсь использовать OpenCV 2.3.1 для преобразования 12-разрядного изображения Bayer в 8-битное изображение RGB. Кажется, что это должно быть довольно просто с помощью функции cvCvtColor, но функция генерирует исключение, когда я вызываю его с помощью этого кода:

int cvType = CV_MAKETYPE(CV_16U, 1);
cv::Mat bayerSource(height, width, cvType, sourceBuffer);
cv::Mat rgbDest(height, width, CV_8UC3);
cvCvtColor(&bayerSource, &rgbDest, CV_BayerBG2RGB);

Я думал, что я пропустил конец sourceBuffer, так как входные данные 12-бит, и мне пришлось передать 16-битный тип, потому что OpenCV не имеет 12-битного типа. Таким образом, я разделил ширину и высоту на 2, но cvCvtColor все еще выдавал исключение, в котором не было никакой полезной информации (сообщение об ошибке было "Неизвестное исключение" ).

Был опубликован несколько месяцев назад аналогичный вопрос, на который никогда не отвечали, но поскольку мой вопрос более конкретно касается 12-разрядных данных Bayer, я думал, что это достаточно различны, чтобы заслужить новый вопрос.

Спасибо заранее.

Изменить: мне что-то не хватает, потому что я не могу заставить функцию cvCvtColor работать с 8-битными данными:

cv::Mat srcMat(100, 100, CV_8UC3);
const cv::Scalar val(255,0,0);
srcMat.setTo(val);
cv::Mat destMat(100, 100, CV_8UC3);
cvCvtColor(&srcMat, &destMat, CV_RGB2BGR);

Ответ 1

Ответ Gillfish технически работает, но во время преобразования он использует меньшую структуру данных (CV_8UC1), чем вход (который является CV_16UC1), и теряет некоторую информацию о цвете.

Я бы предложил сначала декодировать байерскую кодировку, но оставаться в 16 бит на канал (от CV_16UC1 до CV_16UC3), а затем преобразовать в CV_8UC3.

Измененный код Gillfish (при условии, что камера дает изображение в 16-битной кодировке Bayer):

// Copy the data into an OpenCV Mat structure
cv::Mat mat16uc1_bayer(height, width, CV_16UC1, inputBuffer);

// Decode the Bayer data to RGB but keep using 16 bits per channel
cv::Mat mat16uc3_rgb(width, height, CV_16UC3);
cv::cvtColor(mat16uc1_bayer, mat16uc3_rgb, cv::COLOR_BayerGR2RGB);

// Convert the 16-bit per channel RGB image to 8-bit per channel
cv::Mat mat8uc3_rgb(width, height, CV_8UC3);
mat16uc3_rgb.convertTo(mat8uc3_rgb, CV_8UC3, 1.0/256); //this could be perhaps done more effectively by cropping bits

Ответ 2

Я смог преобразовать свои данные в 8-разрядный RGB, используя следующий код:

// Copy the data into an OpenCV Mat structure
cv::Mat bayer16BitMat(height, width, CV_16UC1, inputBuffer);

// Convert the Bayer data from 16-bit to to 8-bit
cv::Mat bayer8BitMat = bayer16BitMat.clone();
// The 3rd parameter here scales the data by 1/16 so that it fits in 8 bits.
// Without it, convertTo() just seems to chop off the high order bits.
bayer8BitMat.convertTo(bayer8BitMat, CV_8UC1, 0.0625);

// Convert the Bayer data to 8-bit RGB
cv::Mat rgb8BitMat(height, width, CV_8UC3);
cv::cvtColor(bayer8Bit, rgb8BitMat, CV_BayerGR2RGB);

Я ошибочно предположил, что 12-битные данные, которые я получал с камеры, были плотно упакованы, так что два 12-битных значения содержались в 3 байтах. Оказывается, каждое значение содержалось в 2 байтах, поэтому мне не нужно было распаковывать, чтобы мои данные попадали в 16-разрядный массив, поддерживаемый OpenCV.

Изменить: См. улучшенный ответ @petr, который преобразуется в RGB перед преобразованием в 8 бит, чтобы не потерять информацию о цвете во время преобразования.