4

I'm trying to print an image using OpenCV defining a 400x400 Mat:

plot2 = cv::Mat(400,400, CV_8U, 255);

But when I try print the points, something strange happens. The y coordinate only prints to the first 100 values. That is, if I print the point (50,100), it does not print it in the 100/400th part of the columns, but at the end. Somehow, 400 columns have turned into 100.

For example, when running this:

for (int j = 0; j < 95; ++j){
    plot2.at<int>(20, j) = 0;
}
cv::imshow("segunda pared", plot2);

Shows this (the underlined part is the part corresponding to the code above):

IMAGE

A line that goes to 95 almost occupies all of the 400 points when it should only occupy 95/400th of the screen.

What am I doing wrong?

Berriel
  • 12,659
  • 4
  • 43
  • 67
user6375350
  • 95
  • 1
  • 8

1 Answers1

6

When you defined your cv::Mat, you told clearly that it is from the type CV_8U:

plot2 = cv::Mat(400,400, CV_8U, 255);

But when you are trying to print it, you are telling that its type is int which is usually a signed 32 bit not unsigned 8 bit. So the solution is:

for (int j = 0; j < 95; ++j){
    plot2.at<uchar>(20, j) = 0;
}

Important note: Be aware that OpenCV uses the standard C++ types not the fixed ones. So, there is no need to use fixed size types like uint16_t or similar. because when compiling OpenCV & your code on another platform both of them will change together.


BTW, one of the good way to iterate through your cv::Mat is:

for (size_t row = 0; j < my_mat.rows; ++row){
    auto row_ptr=my_mat.ptr<uchar>(row);
    for(size_t col=0;col<my_mat.cols;++col){
         //do whatever you want with  row_ptr[col]  (read/write)
    }
}
Humam Helfawi
  • 19,566
  • 15
  • 85
  • 160
  • Are you sure about the "Important note" section? Can you provide a source for this information? Are you saying that if you create an image as `plot2 = cv::Mat(400,400, CV_16U, 255);` accessing with `plot2.at(20, j) = 0;` would be wrong? I don't think so. – Antonio May 27 '16 at 12:34
  • Yes pretty sure. I do not have OpenCV code in my hand now. and searching for part of the code online is hard. see this for now http://stackoverflow.com/a/32663709/4523099 I will try to bring some clear reference for my note later. – Humam Helfawi May 27 '16 at 12:50
  • Thanks a lot for pointing this out! I have done some research, I have posted my results as an additional answer [there](http://stackoverflow.com/a/37484930/2436175). I think your answer could be a little bit more precise: it's true one shouldn't use `uint16_t`, but it's not clear what one should actually use (probably unsigned short would be fine, but at that point I would prefer the approach mentioned in my answer). – Antonio May 27 '16 at 13:41
  • "one of the good way to iterate" - and even better is not to iterate at all if you can help it, but rather use matrix expressions or existing OpenCV functions. E.g. in this case select a ROI using `rowRange`,`colRange` and friends, and then just assign the scalar to it. This will often result in better performance, as the OpenCV code tends to be better optimized than often naive iteration over the matrix. – Dan Mašek May 27 '16 at 15:56
  • There is no doubt in that. But when there is no pre built function, you have to do it like this or even better usin LUT if avail or tbb parllel etc... – Humam Helfawi May 27 '16 at 17:29