Преобразование 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);
2 ответов
ответ Gillfish технически работает, но во время преобразования он использует меньшую структуру данных (CV_8UC1), чем вход (который является CV_16UC1), и теряет некоторую цветовую информацию.
Я бы предложил сначала декодировать кодировку Bayer, но оставаться в 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
я смог преобразовать свои данные в 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.
Edit: см. улучшенный ответ @petr, который преобразуется в RGB до преобразования в 8 бит, чтобы избежать потери информации о цвете при конвертации.