Izak
Izak

Reputation: 317

Create a 2 dimensional matrix from array in OpenCV

I am completely new to OpenCV and I have troubles creating a matrix. I read the docs, browsed similar questions on stackoverflow and for the love of me I cannot figure out what I'm doing wrong.

I'm using Visual Studio 2017 and OpenCV version 4.4.0

I'm trying to create an 8x8 matrix and fill it from an array. The dimensions were not correct nor was the data so I tried doing the same with the smallest matrix possible to see what I'm doing wrong.

So now I try to create a 2x2 matrix. Simple enough, right? Well, not exactly. This is the code I use:

double data[2][2] = { {1.0, 2.0}, {3.0, 4.0} };
double data2[4] = { 1.0, 2.0, 3.0, 4.0 };
Mat *M = new Mat(2, 2, CV_64FC4, data);

I tried doing it with 2 dimensional array, I tried doing it with one dimensional array and the problem is always the same. This is the output I get if I print the matrix with

std::cout << "M = " << *M << std::endl << std::endl;
H = [1, 2, 3, 4, 9.844067014090074e-312, 4.639954332214191e-310, 9.84406421008967e-312, 4.639543499923437e-310;
 9.844064273725325e-312, 9.844064194674822e-312, 9.844064050407653e-312, 9.844064042739754e-312, 9.844064050407653e-312, 9.844064050407653e-312, 9.844064050407653e-312, 9.844064050407653e-312]

You can see the dimensions are 2x8 and the contents are some random numbers.

I also tried doing it without the pointer

Mat M(2, 2, CV_64FC4, data);

but that doesn't even compile, giving an error of Expected a type identifier.

What exactly am I doing wrong here?

Upvotes: 0

Views: 1454

Answers (2)

pptaszni
pptaszni

Reputation: 8218

You tried to use CV_64FC4 pixel type that has 4 channels, so it expects 4 double values per element. To create n x m cv::Mat with single value per element, use CV_64F type:

cv::Mat M(n, m, CV_64F, data);

Upvotes: 3

ypnos
ypnos

Reputation: 52317

There is many proper ways to initialize a cv::Mat in C++. Simplest is if you just present the data in flat form and then reshape the matrix accordingly. This example is actually from the OpenCV docs:

std::vector<Point3f> vec;
...
Mat pointMat = Mat(vec)    // convert vector to Mat, O(1) operation
               .reshape(1) // make Nx3 1-channel matrix out of Nx1 3-channel.
                           // Also, an O(1) operation
               .t();       // finally, transpose the Nx3 matrix.
                           // This involves copying all the elements

Source

In your case:

std::vector<double> data = { 1.0, 2.0, 3.0, 4.0 };
Mat ret = Mat(data).reshape(2, 2);

Note: This way, ret is a wrapper around data. If you would like to copy the data instead, use Mat(data, true).

Upvotes: 2

Related Questions