首页 > 解决方案 > uint8_t 缓冲区到 cv::Mat 转换导致图像失真

问题描述

我有一个 Mipi 相机,它可以捕获帧并将它们存储到您可以在下面看到的结构缓冲区中。存储帧后,我想将其转换为 cv::Mat,问题是 Mat 最终看起来像第一张照片。

var buf.index 只是 V4L2 API 的一部分,有助于了解我正在使用哪个缓冲区。

//The structure where the data is stored
struct buffer{
    void *start;
    size_t length;
};

struct buffer *buffers;

//buffer->mat
cv::Mat im = cv::Mat(cv::Size(width, height), CV_8UC3, ((uint8_t*)buffers[buf.index].start));

在此处输入图像描述

起初我认为数据可能已损坏,但使用 lodepng 存储图像会产生没有任何失真的漂亮图像。

unsigned char* out_buf = (unsigned char*)malloc( width * height * 3);

for(int pix = 0; pix < width*height; ++pix) {
    memcpy(out_buf + pix*3, ((uint8_t*)buffers[buf.index].start)+4*pix+1, 3);
}
lodepng_encode24_file(filename, out_buf, width, height);

在此处输入图像描述

我敢打赌这真的很愚蠢。

标签: c++opencv

解决方案


您发布的图片具有奇怪的彩色像素,并且图案看起来比每像素 24 位的信息更多。

检查数据后,V4L 似乎为每个像素提供了四个字节,第一个字节始终为 0xFF(我们称之为 X)。此外,通道顺序似乎是 XRGB。

创建一个 cv::Mat8UC4用于包含数据。

要在 OpenCV 中使用图片,您需要 BGR 命令。cv::split将接收到的数据放入其四个颜色平面中,即 X、R、G、B。用于cv::merge将 B、G、R 平面重新组装成 OpenCV 可以处理的图片,或重新组装成 R、G、B 以创建用于其他目的的 Mat(您似乎使用的其他库)。


推荐阅读