可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am trying to use OpenCV 2.3.1 to convert a 12-bit Bayer image to an 8-bit RGB image. This seems like it should be fairly straightforward using the cvCvtColor function, but the function throws an exception when I call it with this code:
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);
I thought that I was running past the end of sourceBuffer, since the input data is 12-bit, and I had to pass in a 16-bit type because OpenCV doesn't have a 12-bit type. So I divided the width and height by 2, but cvCvtColor still threw an exception that didn't have any helpful information in it (the error message was "Unknown exception").
There was a similar question posted a few months ago that was never answered, but since my question deals more specifically with 12-bit Bayer data, I thought it was sufficiently distinct to merit a new question.
Thanks in advance.
Edit: I must be missing something, because I can't even get the cvCvtColor function to work on 8-bit data:
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:
The Gillfish's answer technically works but during the conversion it uses smaller data structure (CV_8UC1) than the input (which is CV_16UC1) and loses some color information.
I would suggest first to decode the Bayer encoding but stay in 16-bits per channel (from CV_16UC1 to CV_16UC3) and later convert to CV_8UC3.
The modified Gillfish's code (assuming the camera gives image in 16bit Bayer encoding):
// 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:
I was able to convert my data to 8-bit RGB using the following code:
// 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);
I had mistakenly assumed that the 12-bit data I was getting from the camera was tightly packed, so that two 12-bit values were contained in 3 bytes. It turns out that each value was contained in 2 bytes, so I didn't have to do any unpacking to get my data into a 16-bit array that is supported by OpenCV.
Edit: See @petr's improved answer that converts to RGB before converting to 8-bits to avoid losing any color information during the conversion.