理解为什么它不能使用 memcpy 正确复制

Understanding why it doesn't copy correctly using 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);

在此之后我有 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));

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 的半兆字节内存。这可能以段错误结束,或者一些很难找到的错误(以防您覆盖其他数据结构使用的一些内存)。


更新: 我还漏掉了另一个问题(感谢@Micka 发现了这个问题)。 cv::Mat constructor 的参数顺序是行、列、数据类型。看起来你切换了宽度和高度,尽管因为你的输入图像看起来是正方形的(即 width == height),所以这并不重要。


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

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