简体   繁体   中英

accessing element (x,y) in cv::Mat with c++ api

i'm aware of a lot of post about this argument and i've read a lot of them but i'm still confused. the problem are the types ( ohu, damn, this is c, i have to deal with with data types! ;-) ).

i'm using new supercool templated c++ api function at :

Mat mat32f(3, 3, CV_32F);
for(int i=0; i<3; i++) 
    for(int j=0; j<3; j++)
        mat32f.at<float>(i,j) = i;
cout << "Matrix of type: " << mat32f.type() << endl;
cout << mat32f << endl;
cout << mat32f.at<float>(1,2) << endl;

ok, here are float with 1 channel, no problem, the output is clear:

Matrix of type: 5
[0, 0, 0;
  1, 1, 1;
  2, 2, 2]
1

now just make some filter:

Mat mask;
inRange(mat32f, 1, 1, mask);
cout << "Mask of type: " << mask.type() << endl;
cout << mask << endl;

for here, alles klar, the output is just what i want:

Mask of type: 0
[0, 0, 0;
  255, 255, 255;
  0, 0, 0]

now i want to check if a certain point (mouse click? whatever) is inside the range.

int value2 = mask.at<char>(1,2);
cout << value2 << endl; 
unsigned int value3 = mask.at<unsigned int>(1,2);
cout << value3 << endl;

i remember from the first computer science class that a char is of the same size of an unsigned int (because of my mask type is 0 == CV_8U ) so use a char. but cout grab it for a char and so show me some useless non-ascii symbol, so store it in an int .

here the ouput:

-1
256

what happened? a big mess. why -1?? or, again, why 256?? what happend?

The comments from OpenCV::Basic Structures state this about Mat::at<>() methods:

// template methods for read-write or read-only element access.
// note that _Tp must match the actual matrix type -
// the functions do not do any on-fly type conversion

So what you are getting from a Mat<float> when you use at<char> or at<unsigned int> is likely undefined behavior (either from C++ or the Open library).

Your statement that "that a char is of the same size of an unsigned int" is also almost always not correct. I believe it is technically possible for sizeof(char) == sizeof(unsigned int) in C++ but I'm not aware of platforms/implementations where this is true. Even if it was true in your case it would be dangerous to use this assumption as it may not true on all systems your code may run on.

More Detail

According to the OpenCV v2.4 Source the Mat::at() looks like (less debug code):

template<typename _Tp> inline const _Tp& Mat::at(int i0, int i1) const
{
    return ((const _Tp*)(data + step.p[0]*i0))[i1];
}

If you try to access the wrong type of data you are casting the raw array to the wrong type which only leads to no good.

As for why you would specify the data type into Mat::at(), can't you just do:

mat32f.at(i,j) = i;

and let the compiler automatically choose the correct template type?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM