Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

initialize an OpenCV Mat with an 2D array

Tags:

opencv

In my application, I want to create a OpenCV Mat A (2-Dimensions) having some values and then pass it to another OpenCV function using A as input.

Currently, I'm trying:

// 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);   

in case of 1D array, the value passing is OK. But this does not work for 2D array, which is even more a common case. How can I solve this in OpenCV??

like image 600
TSL_ Avatar asked Aug 27 '12 09:08

TSL_


2 Answers

Originally, I used the mnemonic from OpenCV online guides:

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

But I didn't understand what the document meant by size_t step=AUTO_STEP. And this means that I can omit the step argument with which OpenCV will automatically choose AUTO_STEP

I've tried and this works:

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

for the 2D Mat initialized from array

like image 152
TSL_ Avatar answered Nov 08 '22 20:11

TSL_


While your answer is correct for your situation, it's good to know what step and AUTO_STEP mean

Usually, images are stored in continuous blocks of memory. Each row follows after the previous one, so you can access the data by pointer with a simple

data = dataPtr[currentCol + width * currentRow]; 

Where width is the row width in bytes (not in pixels!)

But this is not always the case - sometimes you access a submatrix, and the data is continuous on each row, but to go the next row you have to jump a sequence of bytes.

This is where the step (also known as stride) comes in. It represents the distance, in bytes, between two consecutive rows. In continuous matrices, its value is sizeof(pixel)*rowWidth, but it may have custom values in special situations. When you pass AUTO_STEP to the Mat constructor, it knows that the data is continuous and calculates the step with the above formula. So now, the more correct approach to reading pixel values is

data = dataPtr[currentCol + step * currentRow]; 

Which is working for all kinds of images.

Last, but not least, do not forget that step is measured in bytes, not pixels. So if you have a 3-channel uchar RGB image, step will be 3*number of pixels, and if you have a 3 channel int image, step = 3(channels)*(4=sizeof(int))*(number rows)

like image 44
Sam Avatar answered Nov 08 '22 21:11

Sam