What is the fastest way to convert a C++ array into an 2D opencv Mat object?
Brute force method would be to loop over all entries of the 2D mat and fill them with values of the array.
Is there a better / faster way to do that?
Could I somehow just give pointer of the array to the 2D matrix?
(I'm using opencv 2.4.8)
The Mat class of OpenCV library is used to store the values of an image. It represents an n-dimensional array and is used to store image data of grayscale or color images, voxel volumes, vector fields, point clouds, tensors, histograms, etc.
That is, image of type CV_64FC1 is simple grayscale image and has only 1 channel: image[i, j] = 0.5. while image of type CV_64FC3 is colored image with 3 channels: image[i, j] = (0.5, 0.3, 0.7) (in C++ you can check individual pixels as image.at<double>(i, j) ) CV_64F is the same as CV_64FC1 .
CV_8UC3 - 3 channel array with 8 bit unsigned integers. CV_8UC4 - 4 channel array with 8 bit unsigned integers. CV_8UC(n) - n channel array with 8 bit unsigned integers (n can be from 1 to 512) )
ScalarRepresents a 4-element vector. The type Scalar is widely used in OpenCV for passing pixel values. In this tutorial, we will use it extensively to represent BGR color values (3 parameters). It is not necessary to define the last argument if it is not going to be used.
Yes there is, in the documentation of cv::Mat
you can see how it can be achieved.
Specifically in this line
C++: Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP)
This means that you can do something like
double x[100][100];
cv::Mat A(100, 100, CV_64F, x);
This will not copy the data to it. You have to also remember that OpenCV data is row major, which means that it has all the columns of one rows and then the next row and so on. So your array has to match this style for it to work.
About how fast it is, the documentation also talks about it:
data – Pointer to the user data. Matrix constructors that take data and step parameters do not allocate matrix data. Instead, they just initialize the matrix header that points to the specified data, which means that no data is copied. This operation is very efficient and can be used to process external data using OpenCV functions. The external data is not automatically deallocated, so you should take care of it.
It will work quite fast, but it is the same array, if you modified it outside of the cv::Mat
, it will be modified in the cv::Mat
, and if it is destroyed at any point, the data
member of cv::Mat
will point to a non-existant place.
UPDATE:
I forgot to also say, that you can create the cv::Mat
and do std::memcpy. This way it will copy the data, which may be slower, but the data will be owned by the cv::Mat
object and destroyed upon with the cv::Mat
destroyer.
double x[100][100];
cv::Mat A(100,100,CV_64F);
std::memcpy(A.data, x, 100*100*sizeof(double));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With