Mat::at operator with single index
Although the OpenCV documents say:
Mat::at
the variants with a single index (i) can be used to access elements of single-row or single-column 2-dimensional arrays
we can use Mat::at with a single index for usual MxN matrix.
e.g.
cv::Mat m(3,3,CV_32F);
float *p1(m.at<float[3]>(0));
p1[0]=...; p1[1]=...; p1[2]=...;
cv::Vec3f &p2(m.at<cv::Vec3f>(1));
p2[0]=...; p2[1]=...; p2[2]=...;
This way is useful to me. My question is: Is this not a regular way? If OpenCV changes the implementation and restricts the above style, then I would have a trouble.
Edited:
What I want to do is getting a row without a big overhead. I'm seeking a way lighter than m.row(i)
(which takes cv::Mat overhead). I am assuming a case where the number of columns is known, like above case (3). In such a case, I think we could get a pointer to an array block (float[3]
or cv::Vec3f
) at i-th row.
for
cv::Vec3f &p2(m.at<cv::vec3f>(1)); p2[0]=...; p2[1]=...; p2[2]=...;
That's not a regular way. Code check size before get ptr to line. Hence there is an execption in your code because size of vec3f is 3*4 byte and element size your mat is 4 byte
Mat::at returns a reference, not a pointer.
did you ,mean Mat::ptr ?
LBerger, I understand that when we use Mat::at, we have to know the element type and size (above, it's float, 4 byte). So I wrote like
m.at<cv::vec3f>
since I knew the type and the size.berak, with
m.at<float[3]>
, I am trying to get a row, which will returnfloat[3]
. So I stored it into a pointerfloat*
.akhiko, then the short answer is: no, both of your attempts are wrong, and you should not do it this way.
please check with a DEBUG build, your code should throw an exception (which is suppressed in RELEASE)
again, for a
Mat m(3,3,CV_32F)
you can havefloat v=m.at<float>(r,c)
orfloat *p = m.ptr<float>(r,c)
anything else is illegal. (and will break on edge cases, like ROI, padding or multi-dim Mats)
berak, let's make the reason clear. OpenCV does NOT guarantee a continuous memory allocation. When the memory is not allocated continuously, a low-level block access like
m.at<float[3]>(i)
orm.at<cv::Vec3f>(i)
is dangerous and should be avoided as you say. However OpenCV provides Mat::isContinuous to check if the memory allocation is continuous or not. So when the memory allocation is continuous, those block accesses could be acceptable. Are there other points?hmm, i fail to see your point there. either you "play by the rules" (and use at() and ptr() correctly) or you could just retrieve the address of the 1st elem with
float* p = ptr<float>(0)
and use p according to your own scheme (and risk)in other words, i don't see, why you want to "bend" at() or ptr() beyond scope.