MAT
本博文介绍了Mat的使用,基本上是参照opencv_tutorials翻译的,可能存在一些理解上的偏差,欢迎指正。
OpenCV在2001年开始起使用。那时候库文件是用C的接口写的,用一个IplImage的C结构存储图像,在老版本的教科书和说明书中你仍可以看到。这种方式导致了内存管理方面的问题,用户不得不自己去释放内存空间。不过为方便使用,现在opencv已经开发了C++接口。
关于Mat结构首先必须知道的一点是不需要自己分配和释放内存。Mat是包含两个数据部分的类:矩阵头(包含矩阵的一些信息,包括矩阵的size,存储的方式,矩阵数据存储的地址等),一个指向数据的指针。值得注意的一点是Mat的矩阵头的大小是固定的,不随Mat的size变化。
下面看程序:
Mat A,C;//定义了矩阵头
A = imread(“ ”,CV_LOAD_IMAGE_COLOR);//矩阵导入
Mat B(A);//采用拷贝构造函数,创建B
C = A;//赋值操作,将A的数据指针赋给C
上面这个例子中的所有矩阵,最后都指向了同样的数据。不过文件头是不一样的。对其中任何一个Mat结构的数据进行处理就是对其他的Mat进行处理。
比较有趣的一点是可以创建矩阵,其包含的矩阵数据只是全部数据的一个子集。
上代码:
Mat D(A,Rect(10,10,100,100));//取A的一部分
Mat E = A(Range::all(),Range(1,3));//采用行列限定,类似于matlab
下面介绍copy和clone
Mat F = A.clone();
Mat G;
A.copyTo(G);
现在修改G和F就不会影响A了。
至此,关于opencv有几个地方需要记住:
1. opencv函数的输出图像回收是自动的(除特别说明)
2. 在C++接口下不需要考虑内存分配
3. 赋值操作符和拷贝构造函数只能拷贝文件头
4. 真正需要复制矩阵数据要用到copyto()和clone()
显式地创建mat对象
Mat M(2,2,CV_8UC3,Scalar(0,0,255));
运行结果如下:
解释一下CV_8UC3: 采用uchar类型的8位,每个像素有三个这种数据来创建三个通道。也就是表示如下图
如何创建多维数组?
Int sz[3] = {2,2,2};
Mat L(3,sz,CV_8UC(1),Scalar::all(0));
上例展示了三维数组的构建,第一个参数是数组的维数,第二个是数组每一维度的尺寸(2行2列共2层),后面与二维数组是一样的了。
采用已有的Iplimage结构生成mat
Iplimage * img = cvloadimage(“ ”,1);
Mat mtx(img);
采用create()函数
Mat m;
m.create(4,4,CV_8UC(2));
还可以用类似于matlab中的对角、零矩阵、全一矩阵等。
Mat E = Mat::eye(4,4,CV_64F);
Mat E = Mat::ones(4,4,CV_64F);
Mat E = Mat::zeros(4,4,CV_64F);
还可以用randu()生成随机数的数组