cv::Mat在SLAM经常用于存储图像数据以及相机位姿,其兼容的数据类型多种多样,使用此数据结构前要明确搞清楚当前矩阵元素是什么类型的,不然后面进行逐个元素访问或者计算时会经常出错。
1、数据类型查看方法:
cv::Mat T;
std::cout<<T.type()<<endl;
2、type()返回值与数据类型对应关系:
返回值 | C1 | C2 | C3 | C4 |
---|---|---|---|---|
CV_8U | 0 | 8 | 16 | 24 |
CV_8S | 1 | 9 | 17 | 25 |
CV_16U | 2 | 10 | 18 | 26 |
CV_16S | 3 | 11 | 19 | 27 |
CV_32S | 4 | 12 | 20 | 28 |
CV_32F | 5 | 13 | 21 | 29 |
CV_64F | 6 | 14 | 22 | 30 |
3、使用at进行逐个元素访问:
std::cout<<T.at<float>(0,0)<<endl;
at括号中的关键字要与T的真实类型匹配,不然会出错,例如CV_8U要用T.at< unsigned char> 访问.
对应关系如下:
数据类型 | 关键字 | 占用字节 | 范围 |
---|---|---|---|
CV_8U | unsigned char | 1 字节 | 0 到 255 |
CV_8S | char | 1 字节 | -128 到 127 |
CV_16U | unsigned short | 2 字节 | 0 到 65,535 |
CV_16S | short | 2 字节 | -32768 到 32767 |
CV_32S | int | 4 字节 | -2147483648 到 2147483647 |
CV_32F | float | 4 字节 | +/- 3.4e +/- 38 (~7 个数字) |
CV_64F | double | 8 字节 | +/- 1.7e +/- 308 (~15 个数字) |
4、出错现象总结
(1)访问和赋值时数据类型不对时Mat里面就开始乱存数据了,但不会报错,很难找
Mat Tcw = Mat::zeros(4, 4, CV_32FC1);
for(int i=0; i<3; i++)
for(int j=0; j<3; j++)
Tcw.at<double>(i, j) = rotation_matrix1(i, j);
(2)不同数据类型矩阵相乘也会出错,这个错误在编译时是会报出的
Mat Tcw = Mat::zeros(4, 4, CV_32FC1);
cv::Mat t(4,1,CV_64F);
t = Tcw * t;
5、多维矩阵元素访问
const int histSize[] = {N, N, N};
cv::Mat mColorHist;
mColorHist.create(3, histSize, CV_32F);
cv::Mat_<cv::Vec3b>::iterator it = mColorHist.begin<cv::Vec3b>();
cv::Mat_<cv::Vec3b>::iterator it_end = mColorHist.end<cv::Vec3b>();
for(; it != it_end; ++it)
{
const cv::Vec3b& pix = *it;
cout<<mColorHist.at<float>(pix[0], pix[1], pix[2])<<" ";
}
6、图片像素访问
一、.png格式
png格式图片有四个通道,读取顺序为rgba:
cv::imPNG =cv::imread("1.png",CV_LOAD_IMAGE_UNCHANGED); //CV_8UC4 bgra
for ( int m=0; m<kf->imPNG.rows; m+=4 )
{
for ( int n=0; n<kf->imPNG.cols; n+=4 )
{
pcl::PointXYZRGBA p;
// p.r = imPNG.ptr<uchar>(m)[n*4+0];
// p.g = imPNG.ptr<uchar>(m)[n*4+1];
// p.b = imPNG.ptr<uchar>(m)[n*4+2];
// p.a = imPNG.ptr<uchar>(m)[n*4+3];
p.r = imPNG.at<cv::Vec4b>(m,n)[0];
p.g = imPNG.at<cv::Vec4b>(m,n)[1];
p.b = imPNG.at<cv::Vec4b>(m,n)[2];
p.a = imPNG.at<cv::Vec4b>(m,n)[3];
tmp->points.push_back(p);
}
}
二、.jpg格式
jpg格式图片有三个通道,读取顺序为bgr:
cv::imJPG =cv::imread("1.png",CV_LOAD_IMAGE_UNCHANGED); //CV_8UC4 bgra
for ( int m=0; m<kf->imJPG.rows; m+=4 )
{
for ( int n=0; n<kf->imJPG.cols; n+=4 )
{
pcl::PointXYZRGBA p;
// p.r = imJPG.ptr<uchar>(m)[n*3+0];
// p.g = imJPG.ptr<uchar>(m)[n*3+1];
// p.b = imJPG.ptr<uchar>(m)[n*3+2];
p.r = imJPG.at<cv::Vec3b>(m,n)[0];
p.g = imJPG.at<cv::Vec3b>(m,n)[1];
p.b = imJPG.at<cv::Vec3b>(m,n)[2];
tmp->points.push_back(p);
}
}
注:Vec3b - for uchar, Vec3i - for int, Vec3f - for float, Vec3d - for double
参考博客:
https://www.runoob.com/cplusplus/cpp-data-types.html
https://blog.csdn.net/weixin_35695879/article/details/85948011
http://cn.voidcc.com/question/p-yxesasxj-th.html
https://blog.csdn.net/qq_30815237/article/details/86656631