0

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?

6
  • 2
    Because pixel type CV_64FC4 has 4 channels, so it expects 4 double values per pixel. Try CV_64F Commented Aug 18, 2020 at 8:58
  • @pptaszni You gave an answer, not a comment? Commented Aug 18, 2020 at 9:02
  • @ypnos yeah, because I don't have the environment to try it right now. Let's wait for OP to confirm it works and I can copy it as an answer. Commented Aug 18, 2020 at 9:05
  • Well that's awkward. Both the answer and that comment work. I guess this comment is a bit more appropriate since my solution would work if I used the correct type. Commented Aug 18, 2020 at 9:16
  • 1
    @Izak: Just be careful what you do. In your code example, you allocate the array on the stack. So if it gets out of scope, your matrix contents will get corrupted. Maybe you only use the matrix within a function which is fine. But then it would be better to also create the matrix object on the stack to signify this. Or if your numbers are fixed, use a static array (can be within the function as well, perfectly fine). Commented Aug 18, 2020 at 10:02

2 Answers 2

3

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);
Sign up to request clarification or add additional context in comments.

Comments

2

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.