opencv-cv::Mat

 如果使用Mat类,我们得到的好处是:

不需要手动申请一块内存;
在不需要时不用再手动释放内存;
可以通过类的封装,方便的获取到数据的相关信息

Mat类分为两个部分:矩阵头和矩阵数据。如果我们在操作一副图像的数据量时,矩阵数据的大小很大(一般约有1M的数据量),那么拷贝和赋值函数所作的操作如果的深拷贝的话,效率会大大的降低。所以,Opencv的做法是只复制其矩阵头信息,而矩阵数据采用引用的方式,即多个Mat对象共享同一个矩阵数据,这里使用的原理类似c++11中的共享指针

    cv::Mat A = cv::imread("D:/bb/tu/ma.jpg");
    cv::Mat B(A);
    cv::Mat C = A;
    printf("A.data = %p
B.data = %p
C.data = %p
", A.data, B.data, C.data);

输出结果如下:

 如上我们可以看到,三个Mat类对象的矩阵数据的地址是一样的。那么释放内存的原则是怎样的呢。这个也是内部使用了引用计数的方法,类似共享指针,当引用计数变为0的时候才会真正的释放内存

Mat对象的创建

    cv::Mat M1(5, 4, CV_8UC4, cv::Scalar(0, 0, 0, 255));//创建2维矩阵对象
    /*
    参数1和参数2:行数和列数
    参数3:图像属性8UC4:
          第一位8:比特数 代表8bite,16bites,32bites,64bites,每一个像素点在内存空间所占的空间大小
          第二位U:S--代表---signed int---有符号整形
                 U--代表--unsigned int--无符号整形
                 F--代表--float-------单精度浮点型
          最后两位c4:通道数:1--灰度图片---是--单通道图像
                          2--RGB彩色图像---------是--3通道图像
                          3--带Alph通道的RGB图像--是--4通道图像
    参数4:每个像素点的颜色
*/

    std::cout << M1 << std::endl; //显示数据

    int r=M1.rows;   //返回行数
    int c=M1.cols;   //返回列数
    
    qDebug()<<r<<c;
    cv::Mat M1(5, 4, CV_8UC3);
    std::cerr<<M1<<std::endl;
    M1=cv::Scalar(10, 20, 30);//赋值
    std::cerr<<M1<<std::endl;
    int sz[2]={5,4};
    cv::Mat M(2, sz, CV_8UC4, cv::Scalar(0, 0, 0, 255));//创建n维矩阵对象
    /*
    参数1:矩阵的维数
    参数2:是个数组,表示行数和列数
    */

    std::cout << M << std::endl; 
    cv::Mat M;
    M.create(5, 4, CV_8UC4);//创建2维矩阵对象
    //注意:这种方法好像不能有第四个颜色参数,每个点的颜色随机

    std::cout << M << std::endl;
    cv::Mat M = cv::Mat::eye(4, 4, CV_32F);  //创建单位矩阵
    std::cout << M << std::endl;

    cv::Mat M = cv::Mat::ones(4, 4, CV_32F);  //创建全是1的矩阵
    std::cout << M << std::endl;

    cv::Mat M = cv::Mat::zeros(4, 4, CV_32F);  //创建全是0的矩阵
    std::cout << M << std::endl;

    cv::Mat M = (cv::Mat_<double>(3, 3) << 0, -10, 0, -11, 0, 0, 0, 88, 1);  //创建自定义数据的矩阵
    std::cout << M << std::endl;
    cv::Mat M = (cv::Mat_<double>(3, 3) << 0, -10, 0, -11, 0, 0, 0, 88, 1); 
    cv::Mat M5 = M.row(1).clone(); //M5中的数据就是M的第二行数据
    //通过克隆函数clone获取我们需要的某一行或列的数据,这里构建出来的矩阵是深拷贝出来的Mat类对象
    std::cout << M5 << std::endl;

Mat基本属性

    cv::Mat A = cv::imread("D:/bb/tu/ma.jpg",1);
    int i = A.type();//返回图像属性
    //具体对应值见下表
    std::cout<< i;
    
    cv::namedWindow("显示");
    imshow("显示",A);

    cv::Mat A = cv::imread("D:/bb/tu/ma.jpg",1);
    int i = A.channels();  //返回通道数
    int w=A.cols; //返回列数,即宽
    int h=A.rows; //返回行数,即高

    cv::namedWindow("显示");
    imshow("显示",A);

    qDebug()<<i<<w<<h;
cv::Mat sm(6, 5, CV_8UC3);

int d=sm.depth();//获取矩阵元素深度,其返回的其类型和Mat一致
/* 返回值对应的元素深度
CV_8U   = 0 - 8-bit unsigned integers ( 0..255 )
CV_8S   = 1 - 8-bit signed integers ( -128..127 )
CV_16U  = 2 - 16-bit unsigned integers ( 0..65535 )
CV_16S  = 3 - 16-bit signed integers ( -32768..32767 )
CV_32S  = 4 - 32-bit signed integers ( -2147483648..2147483647 )
CV_32F  = 5 - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN )
CV_64F  = 6 - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )
CV_USRTYPE1=7
*/

int c=sm.channels(); //返回矩阵通道数目
int dim=sm.dims;  //返回矩阵维度
int e=sm.elemSize();//返回每个元素占用的字节数大小(带通道)
int e1=sm.elemSize1();//返回单个元素值占用的字节数大小
int w=sm.step[0];  //第一级在矩阵内存中占据的字节的数量
//step[i]就是第i+1级在矩阵内存中占据的字节的数量
//资料看:https://blog.csdn.net/lanmeng_smile/article/details/47864615


int h=sm.step1(1);  //一个元素所占的字节数

std::cerr<<d<<std::endl;

原文地址:https://www.cnblogs.com/liming19680104/p/15368012.html