OpenCV中 cv::Mat数据类型汇总以及多维矩阵元素访问(C++)

cv::Mat在SLAM经常用于存储图像数据以及相机位姿,其兼容的数据类型多种多样,使用此数据结构前要明确搞清楚当前矩阵元素是什么类型的,不然后面进行逐个元素访问或者计算时会经常出错。
1、数据类型查看方法:

cv::Mat T;
std::cout<<T.type()<<endl;

2、type()返回值与数据类型对应关系:

返回值C1C2C3C4
CV_8U081624
CV_8S191725
CV_16U2101826
CV_16S3111927
CV_32S4122028
CV_32F5132129
CV_64F6142230

3、使用at进行逐个元素访问:

std::cout<<T.at<float>(0,0)<<endl;

at括号中的关键字要与T的真实类型匹配,不然会出错,例如CV_8U要用T.at< unsigned char> 访问.
对应关系如下:

数据类型关键字占用字节范围
CV_8Uunsigned char1 字节0 到 255
CV_8Schar1 字节-128 到 127
CV_16Uunsigned short2 字节0 到 65,535
CV_16Sshort2 字节-32768 到 32767
CV_32Sint4 字节-2147483648 到 2147483647
CV_32Ffloat4 字节+/- 3.4e +/- 38 (~7 个数字)
CV_64Fdouble8 字节+/- 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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值