矩阵包含了所有像素点的强度值。
在计算机世界里所有图像都可以简化为数值矩以及矩阵信息。
关于 Mat ,首先要知道的是你不必再手动地(1)为其开辟空间(2)在不需要时立即将空间释放。但手动地做还是可以的:大多数OpenCV函数仍会手动地为输出数据开辟空间。当传递一个已经存在的 Mat 对象时,开辟好的矩阵空间会被重用。也就是说,我们每次都使用大小正好的内存来完成任务。
就是还是要自己管理内存?
Mat 是一个类 (两部分)
1. 矩阵头(包含矩阵尺寸(常数),存储方法,存储地址等信息)
2. 一个指向存储所有像素值的矩阵(根据所选存储方法的不同矩阵可以是不同的维数)的指针
矩阵本身的尺寸依图像不同而不同 通常比矩阵头的尺寸大数个数量级,因此,当在程序中传递图像并创建拷贝时,大的开销是由矩阵造成的,而不是信息头。
为了搞定这个问题,OpenCV使用引用计数机制。其思路是让每个 Mat 对象有自己的信息头,但共享同一个矩阵。这通过让矩阵指针指向同一地址而实现。而拷贝构造函数则 只拷贝信息头和矩阵指针 ,而不拷贝矩阵。
1 2 3 4 5 6 | Mat A, C; // 只创建信息头部分 A = imread(argv[1], CV_LOAD_IMAGE_COLOR); // 这里为矩阵开辟内存 Mat B(A); // 使用拷贝构造函数 C = A; // 赋值运算符 |
以上代码中的所有Mat对象最终都指向同一个也是唯一一个数据矩阵。虽然它们的信息头不同,但通过任何一个对象所做的改变也会影响其它对象。实际上,不同的对象只是访问相同数据的不同途径而已。这里还要提及一个比较棒的功能:你可以创建只引用部分数据的信息头。比如想要创建一个感兴趣区域( ROI ),你只需要创建包含边界信息的信息头:
1 2 | Mat D (A, Rect(10, 10, 100, 100) ); // using a rectangle Mat E = A(Range:all(), Range(1,3)); // using row and column boundaries |