70

I want to dump the values of a matrix in OpenCV to the console using cout. I quickly learned that I do not understand OpenvCV's type system nor C++ templates well enough to accomplish this simple task.

Would a reader please post (or point me to) a little function or code snippet that prints a Mat?

Regards, Aaron

PS: Code that uses the newer C++ Mat interface as opposed to the older CvMat interface is preferential.

ahoffer
  • 6,347
  • 4
  • 39
  • 68

5 Answers5

110

See the first answer to Accessing a matrix element in the "Mat" object (not the CvMat object) in OpenCV C++
Then just loop over all the elements in cout << M.at<double>(0,0); rather than just 0,0

Or better still with the C++ interface:

cv::Mat M;
cout << "M = " << endl << " "  << M << endl << endl;
Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
  • 3
    Brilliant. I should haves shoved a Mat to cout in the first place just to see if someone had implemented <<. A little more experimentation and trust would have payed off for me. – ahoffer Nov 03 '11 at 19:31
  • I have just asked [a question about this](http://stackoverflow.com/questions/10011797/opencv-2-1-where-is-ostream-operator-for-cvmat). Is the ostream operator<< available in 2.1 and where is this stuff documented? – juanchopanza Apr 04 '12 at 15:09
  • @ahoffer, funny you mentioned that: https://docs.opencv.org/4.1.0/dc/d84/group__core__basic.html#ga3557054d1f0f079cf5e60a44851e4c70 – Anže May 21 '19 at 08:52
  • 3
    One thing to add: Make sure you include `#include ` and not `#include ` as the operator is overloaded elsewhere. – Matthias Güntert Jan 23 '20 at 13:34
10

If you are using opencv3, you can print Mat like python numpy style:

Mat xTrainData = (Mat_<float>(5,2) << 1, 1, 1, 1, 2, 2, 2, 2, 2, 2);

cout << "xTrainData (python)  = " << endl << format(xTrainData, Formatter::FMT_PYTHON) << endl << endl;

Output as below, you can see it'e more readable, see here for more information.

enter image description here

But in most case, there is no need to output all the data in Mat, you can output by row range like 0 ~ 2 row:

#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

#include <iostream>
#include <iomanip>

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
    //row: 6, column: 3,unsigned one channel
    Mat image1(6, 3, CV_8UC1, 5);

    // output row: 0 ~ 2
    cout << "image1 row: 0~2 = "<< endl << " "  << image1.rowRange(0, 2) << endl << endl;

    //row: 8, column: 2,unsigned three channel
    Mat image2(8, 2, CV_8UC3, Scalar(1, 2, 3));

    // output row: 0 ~ 2
    cout << "image2 row: 0~2 = "<< endl << " "  << image2.rowRange(0, 2) << endl << endl;

    return 0;
}

Output as below:

enter image description here

Jayhello
  • 5,931
  • 3
  • 49
  • 56
4

I think using the matrix.at<type>(x,y) is not the best way to iterate trough a Mat object! If I recall correctly matrix.at<type>(x,y) will iterate from the beginning of the matrix each time you call it(I might be wrong though). I would suggest using cv::MatIterator_

cv::Mat someMat(1, 4, CV_64F, &someData);;
cv::MatIterator_<double> _it = someMat.begin<double>();
for(;_it!=someMat.end<double>(); _it++){
    std::cout << *_it << std::endl;
}
jeffdill2
  • 3,968
  • 2
  • 30
  • 47
Dima Maligin
  • 1,386
  • 2
  • 15
  • 30
3
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

#include <iostream>
#include <iomanip>

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
    double data[4] = {-0.0000000077898273846583732, -0.03749374753019832, -0.0374787251930463, -0.000000000077893623846343843};
    Mat src = Mat(1, 4, CV_64F, &data);
    for(int i=0; i<4; i++)
        cout << setprecision(3) << src.at<double>(0,i) << endl;

    return 0;
}
Dmoonleo
  • 76
  • 2
0

Additionally to the above excellent answers, you can print out Mat values by FileStorage, of course if your case considers utilizing a file

// create our writer 
FileStorage fs("test.yml", FileStorage::WRITE);
fs << "Result" << Mat::eye(5,5, CV_64F);
// release the file 
fs.release();

// read file
FileStorage fs2("test.yml", FileStorage::READ);

Mat r2;
fs2["Result"] >> r2;
std::cout << r2 << std::endl;

fs2.release();
27P
  • 1,183
  • 16
  • 22