如何将RAW10格式图像转换为cv::Mat?转换后出现灰色方块
RAW10转cv::Mat出现灰色方块的解决方法
你的问题核心是完全没正确解析RAW10格式——RAW10每个像素是10位数据,不是你代码里默认的8位单通道,直接把buffer按CV_8UC1处理必然会乱码,出现灰色方块是正常结果。
先明确RAW10的存储逻辑
标准RAW10的存储规则是每4个像素占5字节:
- 前4个字节分别存储4个像素的低8位
- 第5字节存储这4个像素的高2位(每个像素占2bit,按顺序排列)
举个具体例子:
Byte0 → 像素0的低8位
Byte1 → 像素1的低8位
Byte2 → 像素2的低8位
Byte3 → 像素3的低8位
Byte4 → (像素0高2位<<6) | (像素1高2位<<4) | (像素2高2位<<2) | (像素3高2位<<0)
修正后的代码步骤
- 先把RAW10的buffer解析成完整的16位Bayer格式数据(保留每个像素的10位信息)
- 将解析后的数据转换为cv::Mat
- 执行Bayer转RGB操作(注意匹配你的传感器实际Bayer排列)
- 缩放为8位格式后保存
代码示例:
#include <opencv2/opencv.hpp> #include <cstdint> #include <vector> void ConvertRAW10ToMat(unsigned char* buffer, unsigned int width, unsigned int height) { // 计算RAW10的总字节数:width*height*10bit = width*height*5/4字节 size_t totalBytes = width * height * 5 / 4; std::vector<uint16_t> bayerData(width * height); // 逐组解析4个像素的10位数据 for (size_t i = 0; i < width * height; i += 4) { unsigned char* pixelBytes = buffer + (i * 5 / 4); // 提取低8位 uint16_t p0 = pixelBytes[0]; uint16_t p1 = pixelBytes[1]; uint16_t p2 = pixelBytes[2]; uint16_t p3 = pixelBytes[3]; // 提取高2位并拼接成完整10位 uint8_t highBits = pixelBytes[4]; p0 |= ((highBits >> 6) & 0x3) << 8; p1 |= ((highBits >> 4) & 0x3) << 8; p2 |= ((highBits >> 2) & 0x3) << 8; p3 |= (highBits & 0x3) << 8; // 存入数组 bayerData[i] = p0; bayerData[i+1] = p1; bayerData[i+2] = p2; bayerData[i+3] = p3; } // 转换为OpenCV的16位单通道Mat cv::Mat bayerMat(height, width, CV_16UC1, bayerData.data()); // Bayer转RGB(注意:这里的COLOR_BayerGR2RGBA要和你的传感器实际Bayer格式匹配,比如BG/GB等) cv::Mat rgbMat; cv::cvtColor(bayerMat, rgbMat, cv::COLOR_BayerGR2RGBA); // 将10位数据(0~1023)缩放到8位范围(0~255) cv::Mat rgb8Bit; rgbMat.convertTo(rgb8Bit, CV_8UC4, 255.0 / 1023.0); // 保存最终图像 cv::imwrite("myimage.png", rgb8Bit); }
关键注意事项
- 确认传感器Bayer格式:如果用
COLOR_BayerGR2RGBA输出颜色不对,尝试COLOR_BayerBG2RGBA、COLOR_BayerGB2RGBA等其他排列 - 确保buffer的总字节数是
width*height*5/4,长度错误会导致解析失败 - 如果只想查看RAW单色数据,也可以直接将16位bayerMat缩放为8位保存,得到的是单色Bayer图而非彩色图
内容的提问来源于stack exchange,提问作者ZeusBios
相关产品推荐
相关产品推荐

