我正在尝试使用OpenCV 2.3.1将12位拜耳图像转换为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仍然抛出了一个没有任何有用信息的异常(错误信息是“Unknown exception”)。
几个月前发布的similar question从未被回复过,但由于我的问题更具体地涉及12位拜耳数据,我认为这个问题非常明显,值得一个新问题。
提前致谢。
编辑:我必须遗漏一些东西,因为我甚至无法使用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);
答案 0 :(得分:14)
我可以使用以下代码将数据转换为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个字节中,因此我不必进行任何解包以将我的数据转换为OpenCV支持的16位数组。
编辑:请参阅@ petr在转换为8位之前转换为RGB的改进答案,以避免在转换过程中丢失任何颜色信息。
答案 1 :(得分:4)
Gillfish的答案在技术上有效,但在转换过程中它使用比输入(CV_16UC1)更小的数据结构(CV_8UC1)并丢失了一些颜色信息。
我建议首先解码拜耳编码,但每通道保持16位(从CV_16UC1到CV_16UC3),然后转换为CV_8UC3。
修改后的Gillfish代码(假设相机以16位拜耳编码方式提供图像):
// 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 :(得分:0)
对于任何为此苦苦挣扎的人,上述解决方案仅在您的图像实际以16bit出现的情况下才有效,正如注释所建议的那样,您应该将4个最低有效位切掉。我做到了这一点。它不是很干净,但是可以。
unsigned short * image_12bit = (unsigned short*)data;
char out[rows * cols];
for(int i = 0; i < rows * cols; i++) {
out[i] = (char)((double)(255 * image_12bit[i]) / (double)(1 << 12));
}
cv::Mat bayer_image(rows, cols, CV_8UC1, (void*)out);
cv::cvtColor(bayer_image, *res, cv::COLOR_BayerGR2BGR);