这次来记一下自己对Mat类的理解,供交流

  • 首先,使用Mat就不需要为其手动分配内存大小,最后也不需要手动释放它。但是我们在使用openCV函数的时候,还是要手动分配其输入数据。
  • 第二点,Mat本质是由两部分数据组成的类,矩阵头(header)和指针Pointer,矩阵头主要是包含矩阵的大小,存储方式,存储地址等信息,指针中存储了指向存储图像像素值矩阵的指针。
  • 一个常用的Mat类的构造函数,但是要知道,Mat类的有很多重载的构造函数
int main()
{
    Mat M(2, 2, CV_8UC3, cv::Scalar::all(1));
    //前两个参数时指矩阵的行数和列数,
    //第3个参数时重点,表示矩阵的数据类型,接下来会详细讲解
    //第4个是对每个像素值赋初值,这个代码就是把每个通道的像素值都
    //都赋值1.,如果是Scalsr(255,0,0),就是将255,0,0分别赋予每个像素点的3个通道。
    cout << "M=" << endl << M << endl;
    system("pause");
    return 0;
}
  • 阵列的数据类型说明
    阵列的数据类型定义了为阵列的每个元素(图片中的像素)通道数和每个通道上表示像素值得比特数(位数)。任何阵列的元素都应该有下面数据类型的一种:
    单通道阵列
    CV_8U:
    CV_8U (8 bit 无符号整数)
    CV_8S (8 bit 有符号整数)
    CV_16U(16 bit 无符号整数)
    CV_16S (16 bit 有符号整数)
    CV_32S (32 bit 有符号整数)
    CV_32F (32 bit 浮点数)
    CV_64F (64 bit 浮点数)
    举例来说:下图展示了一个使用8 bit无符号整数的单通道阵列。因为数据类型是8 bit无符号整数,因此这个阵列的每个元素为0-255的值
    对应存储图为
  • opencv 离群点删除 opencv清空mat数据_无符号整数

  • 多通道阵列(最大支持512个通道)
    CV_8UC1 (单通道阵列,8 bit 无符号整数)
    CV_8UC2 (2通道阵列,8 bit 无符号整数)
    CV_8UC3 (3通道阵列,8 bit 无符号整数)
    CV_8UC4 (4通道阵列,8 bit 无符号整数)
    CV_8UC(n) (n通道阵列,8 bit 无符号整数 (n 可以从 1 到 512) )
    下图展示了一个使用8 bit 无符号整数的3通道阵列。因为数据类型是8 bit无符号整数,因此这个阵列的每个元素为0-255的值。由于是3通道阵列,所以阵列由带有3个元素的元组组成,第一个元组是{54, 0, 34},第二个元组是 {58, 78, 185} ,以此类推。

opencv 离群点删除 opencv清空mat数据_数据_02

对上面的数据类型使用举例

Mat image(3,5,CV_32F); 
 Mat image(3,5CV_64FC(5)); 
 Mat image(Size(100,200),CV16UC2);

-还可能会遇到这个表达,IPlImage*,这个表达式C语言操作OPENCV的数据结构,地位相当于Mat。
Mat(const IplImage* img, bool copyData=false);
可以很好的将IplImage*转换为Mat
还有一种定义也可以转换

IplImage* img = cvLoadImage("greatwave.png", 1);
Mat mtx(img); // convert IplImage* -> Mat
  • 还要注意Mat类使用了引用技术机理,简单讲,就是在拷贝Mat类的对象的时候,只是将矩阵头和指针复制,而复制后两个对象指针还是指向同一块矩阵数据区。如果要将数据矩阵也复制,必须使用copyTo()或者clone()函数。
    可以用下图来帮助理解
Mat A,C;
A=imread("1.jpg",type);
Mat B(A);//拷贝构造函数
C=A;//直接是赋值运算

代码中的所有Mat对象最终都指向同一个也是唯一一个数据矩阵。虽然它们的信息头不同,但通过任何一个对象所做的改变也会影响其它对象。实际上,不同的对象只是访问相同数据的不同途径而已。
如果要将数据区一起赋值,就要这样,如下

Mat F=A.clone();
Mat G;
A.copyTo(G);

现在改变 F 或者 G 就不会影响 Mat 信息头所指向的矩阵。