简体   繁体   中英

OpenCV C++ 3 Dimensional Mat Data Access Wrong Values

I am using C++ OpenCV DNN to get results into a Mat. Here, dnnResult is the output Mat. The output values are float. I want extract 66 values into 3 separate arrays or a 3 x 66 matrix.

dnnResult.size[0] = 3
dnnResult.size[1] = 1
dnnResult.size[2] = 66
dnnResult.dims = 3

I tried looping like this to get value, but the results are wrong. There is no error for accessing out of bound data from 3d Mat.

for(int m = 0; m < 3; m++){
    for(int n = 0; n < 66; n++){
        myNetOutput2d[m][n] = dnnResult.at<double>(m, 0, n);    
    }
}

I also tried following How to access a 3 dimensional Matrix elements? ,

typedef Vec<double, 66> Vec66d;
for(int m = 0; m < 3; m++){
    for(int n = 0; n < 66; n++){
        Vec66d tmp_vec66d = dnnResult.at<double>(0, m);
        myNetOutput2d[m][n] = tmp_vec66d.val[n];

    }
}

I am trying to get python equivalent of assigning values of size 66 into 3 separate arrays,

arr1, arr2, arr3 = dnnResult

change dnnResult.at<double>(..) to dnnResult.at<float>(..)

+ more information about cv::Mat::at

template<typename _Tp> inline
_Tp& Mat::at(int i0, int i1, int i2)
{
    CV_DbgAssert( elemSize() == sizeof(_Tp) );
    return *(_Tp*)ptr(i0, i1, i2);
}

inline
const uchar* Mat::ptr(int i0, int i1, int i2) const
{
    CV_DbgAssert(dims >= 3);
    CV_DbgAssert(data);
    CV_DbgAssert((unsigned)i0 < (unsigned)size.p[0]);
    CV_DbgAssert((unsigned)i1 < (unsigned)size.p[1]);
    CV_DbgAssert((unsigned)i2 < (unsigned)size.p[2]);
    return data + i0 * step.p[0] + i1 * step.p[1] + i2 * step.p[2];
}

cv::Mat holds data with a raw pointer, and cv::Mat::at<_Tp> access its data with casting a pointer to _Tp* . The index is not out of bound, but the actual data is got from out bounds because double is 64 bit , while the float is 32 bit in OpenCV.

So, you have to know you're cv::Mat 's correct type when accessing to it.

If you want to cast the data do double , you have to cast after getting the correct data.

myNetOutput2d[m][n] = (double)dnnResult.at<float>(m, 0, n);

or, convert the dnnResult 's type to double before accessing to it.

dnnResult.convertTo(dnnResult, CV_64F); 
...
myNetOutput2d[m][n] = dnnResult.at<double>(m, 0, n);

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