mcExchange
mcExchange

Reputation: 6497

How to convert C++ array to opencv Mat

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)

Upvotes: 15

Views: 50466

Answers (2)

api55
api55

Reputation: 11420

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

Upvotes: 36

Display Name
Display Name

Reputation: 15121

#include <opencv2/opencv.hpp>

int main()
{
    // First row contains 3 white pixels
    // Second row contains 3 black pixels
    uchar temp[2][3] = {{255, 255, 255}, {0, 0, 0}};

    cv::Mat mat = cv::Mat(2, 3, CV_8UC1);
    // The first element of temp decays to int* data.
    // It means that mat.data tracks temp.
    mat.data = temp[0];

    // Change the upper left pixel to black from temp,
    // the change affects mat.
    temp[0][0] = uchar(0);

    cv::namedWindow("title", cv::WINDOW_NORMAL);
    cv::imshow("title", mat);
    cv::waitKey();
    return 0;
}

Upvotes: 1

Related Questions