了解为什么使用memcpy无法正确复制

时间:2019-06-09 12:40:29

标签: c++ image opencv memcpy

我对C ++中的OpenCV 4.1.0和memcpy有一些误解。问题是为什么图像放大很多? 我读了这样的图像:

Mat img = imread("lena512.bmp", 1); // Black and White Image
namedWindow("Display window", WINDOW_AUTOSIZE);
imshow("Display window", img);

Input Image

在此之后,我有2个字节的数组:

int inputSize = width * height * channels;
byte* pixels = new byte[width * height * channels];
byte* out = new byte[width * height * channels];

我将img复制到像素数组:

memcpy(pixels, img.data, inputSize * sizeof(byte));

然后我要检查检索图像是否与输入相同:

Mat image = Mat(width, height , CV_8U);
memcpy(image.data, out, inputSize * sizeof(byte));

Retreived Image

1 个答案:

答案 0 :(得分:2)

Mat img = imread("lena512.bmp", 1); // Black and White Image

这就是问题所在,注释是一个谎言,并且通过使用幻数而不是命名常量,您无法轻易得知是这种情况。 1在此上下文中表示IMREAD_COLOR-即始终将图像读取为3通道BGR图像。

但是,在使用memcpy和原始指针的恶作剧之后,您可以通过以下方式创建新的Mat

Mat image = Mat(width, height , CV_8U);

请注意,CV_8U等效于CV_8UC1。因此,您创建了一个通道(灰度)Mat,但将其分配为3通道数据。

因此,获取垃圾是较小的问题。更为严重的问题是,您复制的数据量是目标像素缓冲区可以容纳的3倍-基本上,您破坏了不属于Mat的0.5 MB内存。要么以段错误结束,要么确实很难发现错误(以防您覆盖其他数据结构使用的某些内存)。


更新:我还错过了另一个问题(感谢@Micka抓住了这个问题)。 cv::Mat constructor的参数顺序为行,列,数据类型。似乎您切换了宽度和高度,尽管由于您输入的图像看起来是正方形(即width == height),所以没关系。


分配第二个Mat的正确方法是

Mat image = Mat(height, width, CV_8UC3);