Подтвердить что ты не робот

Инициализировать Matrix OpenCV с помощью 2D-массива

В моем приложении я хочу создать макет A (2-мерности) OpenCV, имеющий некоторые значения, а затем передать его другой функции OpenCV с использованием A в качестве входного.

В настоящее время я пытаюсь:

// float data[2][5] = {{1,2,3,4,5},{7,8,9,10,11}}; 
// OR
float data[10] = {1,2,3,4,5,7,8,9,10,11};

// and then
//  A = Mat(1, 5, CV_32FC1, &data, 2);   // init from float 1D - array
// OR 
    A = Mat(2, 5, CV_32FC1, &data, 2);  

в случае 1D-массива, передача значений в порядке. Но это не работает для 2D-массива, что является еще более распространенным случаем. Как я могу решить это в OpenCV?

4b9b3361

Ответ 1

orginally, я использовал мнемонику из онлайн-руководств OpenCV:

Mat::Mat(Size size, int type, void* data, size_t step=AUTO_STEP)

Но я не понял, что означает документ с помощью "size_t step = AUTO_STEP". И это означает, что я могу отказаться от аргумента "step", с помощью которого OpenCV автоматически выбирает AUTO_STEP

Я пробовал, и это работает:

A = Mat(2, 5, CV_32FC1, &data);

для 2D-мата, инициализированного из массива

Ответ 2

Пока ваш ответ правильный для вашей ситуации, хорошо знать, что означают step и AUTO_STEP

Обычно изображения хранятся в непрерывных блоках памяти. Каждая строка следует за предыдущей, поэтому вы можете получить доступ к данным по указателю с помощью простого

data = dataPtr[currentCol + width * currentRow];

Где ширина - ширина строки в байтах (не в пикселях!)

Но это не всегда так: иногда вы получаете доступ к подматрице, а данные непрерывны в каждой строке, но чтобы перейти к следующей строке, вы должны пересканировать последовательность байтов.

Здесь находится шаг (также известный как шаг). Он представляет расстояние в байтах между двумя последовательными строками. В непрерывных матрицах его значение sizeof(pixel)*rowWidth, но оно может иметь пользовательские значения в особых ситуациях. Когда вы передаете AUTO_STEP в конструктор Mat, он знает, что данные непрерывны и вычисляет шаг с приведенной выше формулой. Итак, более правильный подход к чтению значений пикселей -

data = dataPtr[currentCol + step * currentRow];

который работает для всех видов изображений.

Наконец, не забудьте, что этот шаг измеряется в байтах, а не пикселях. Итак, если у вас есть 3-канальное изображение RGB uchar, шаг будет 3*number of pixels, и если у вас есть 3-канальный внутренний образ, step = 3(channels)*(4=sizeof(int))*(number rows)

Ответ 3

В дополнение к вышеуказанным ответам есть еще один вариант.

Для меньших данных я бы предпочел следующее:

Mat A = (Mat_<float>(2, 5) << 1, 2, 3, 4, 5, 7, 8, 9, 10, 11);

Вы можете легко получить желаемый результат без необходимости определять дополнительную переменную "данные".

Ответ 4

Так как data - это 2D-массив - все data, &data, *data, data[0], &data[0] и &data[0][0] указывают на базу массива. Любое из приведенного выше представления можно было бы выбрать, чтобы правильно построить Mat вместо X в

A = Mat(2, 5, CV_32FC1, X );

Имейте спокойствие, поскольку данные приняты по OpenCV как void*, а доступ к данным через OpenCV аналогичен . Я предпочитаю такой же синтаксис для построения Мата из одиночных или многомерных массивов.

A = Mat(1, 10, CV_32FC1, data ); //for 1D array
A = Mat(2, 5, CV_32FC1, data ); //for 2D array

Вернемся к запросу. Обратите внимание: неправильная конструкция Mat даже из массива 1D. Параметр шага упоминается как 2. Он просто сработал, поскольку OpenCV переопределяет предоставленный параметр шага, если количество строк равно 1. Для более высокие размерные массивы, OpenCV отбрасывает debug утверждение для неверного параметра шага, который вы получили.