Понимание, почему это не копирует правильно, используя memcpy - PullRequest
1 голос
/ 09 июня 2019

У меня есть некоторые недоразумения по поводу OpenCV 4.1.0 и memcpy в C ++. Вопрос в том, почему изображение сильно увеличено? Я читаю изображение как это:

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 Ответ

2 голосов
/ 09 июня 2019
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 - строки, столбцы, тип данных. Похоже, вы переключили ширину и высоту, хотя, поскольку ваше входное изображение выглядит квадратным (т.е. width == height), это не имело значения.


Правильный способ выделить второе Mat будет

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