OpenCV的基本数据类型
点(Point)
Point 是图像中的点,其中Point_为2d(x,y),Point3_为3d(x,y,z)
类模板
1 | template<typename _Tp //类型 |
成员函数
- dot()与ddot() - 点乘与高精度点乘
- cross()
- 二维:a.cross(b) = a.x * b.y - a.y * b.x
- 三维:a.cross(b) = Point3_(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.y)
- inside(m) - 仅用于二维点,判断是否在矩形m内
特性
二维 Point 可以强转为二维 Vec,三维 Point 可以强转为三维 Vec
尺寸(Size)
Size 是图像或者矩阵的宽和高
类模板
1 | template<typename _Tp //类型 |
成员函数
- area() - 面积
- aspectRatio() - 计算斜率(width / height)
- empty() - 是否为空
矩形(Rect)
Rect 构造一个矩形,设置位置以及宽高
类模板
1 | template<typename _Tp //类型 |
成员函数
- area() - 矩形面积
- size() - 返回 Size(width, height)
- tl() - 返回左上的点
- br() - 返回右上的点
- empty() - 是否为空
颜色(Scalar)
Scalar 为画布的颜色通道值
类模板
1 | template<typename _Tp |
特性
其中颜色顺序为 Blue,Green,Red
向量(Vec)
Vec 是多通道 Mat 的基础
类模板
1 | template<typename _Tp, //类型 |
元素访问
(g) 与 [g] 访问 g 处的元素
通道分离与合并
分离(split)
1 | /* |
实例
1 | Mat mat = (Mat_<Vec3f>(2, 2) << Vec3f(1,11,111),Vec3f(2,22,222),Vec3f(3,33,333), Vec3f(4,44,444)); |
分离后的三个通道为[1, 2; 3, 4] [11, 22; 33, 44] [111, 222; 333, 444]
合并(merge)
1 | /* |
实例
1 | Mat mat1 = (Mat_<int>(2, 2) << 1, 11, 111, 1111); |
合并后的 mat 为 [1, 2, 3; 11, 22, 33;
111, 222, 333; 1111, 2222, 3333]
范围(Range)
Range 可以用来表示矩阵多个连续的列或者行
Range表示的范围为一个从 start 到 end 的左闭右开的空间
且提供一个静态方法 all() 来表示所有的行和列
矩阵(Mat)
特点
1. 不再需要手动分配其内存,并在不需要时立即释放它
虽然这样做仍然是可能的,但大多数 OpenCV 函数会自动分配其输出数据。如果你传递一个已经存在的 Mat 对象,它已经为矩阵分配了所需的空间,这将是一个很好的奖励,它将被重用。换句话说,我们始终只使用执行任务所需的内存。
2. Mat 基本上是一个包含两个数据部分的类
1. 矩阵头(包含矩阵的大小、用于存储的方法、存储矩阵的地址等信息)
2. 指向包含矩阵的指针像素值(取任何维度取决于选择的存储方法)
矩阵头的大小是恒定的,但是矩阵本身的大小可能因图像而异,并且通常会大几个数量级。
3. 通过制作不必要的可能的大图像副本进一步降低程序的速度
为解决这个问题,OpenCV 使用引用计数系统。这个想法是每个 Mat 对象都有自己的头,但是通过使它们的矩阵指针指向相同的地址,矩阵可以在它们的两个实例之间共享。 此外,复制运算符只会复制头和指向大矩阵的指针,而不是数据本身
1 | Mat A,C; |
所有上述对象都指向同一个数据矩阵,使用它们中的任何一个进行修改也会影响所有其他对象。 在实践中,不同的对象只是向相同的底层数据提供不同的访问方法。然而,他们的头部不一样。真正有趣的部分是您可以创建仅引用完整数据的小节的标题。例如,要在图像中创建感兴趣区域(ROI),您只需创建一个新边界的新标题:
1 | Mat D (A, Rect(10, 10, 100, 100)); //使用矩形构造 |
每当一个对象复制Mat对象的头部时,矩阵的计数器就会增加。每当清理该对象时,此计数器就会减少。当计数器达到零时,矩阵被释放。
当想要复制矩阵本身时,就要用到 cv::Mat::clone() 和 cv::Mat::copyTo()
1 | Mat F = A.clone(); |
现在修改F或G不会影响A的标题指向的矩阵。但需谨记:
- OpenCV 函数的输出图像分配是自动的(除非另有说明);
- 无需考虑使用 OpenCV 的 C++ 接口的内存管理;
- 赋值运算符和复制构造函数只复制标头;
- 可以使用cv::Mat::clone()和cv::Mat::copyTo()函数复制图像的底层矩阵。
成员变量及函数
- rows - 矩阵行数
- cols - 矩阵列数
- dims - 矩阵维数
- step - step[0]表示一行的长度,step[1]表示每一个数值的长度
- size() - 矩阵尺寸
- channels() - 矩阵通道数
- total() - 矩阵面积
- at()
- 单通道:at<类型>(r,c),访问r行c列的值
- 多通道:at
(r,c),访问r行c列处的向量
- ptr() - 可以获得每一行地址的指针
- isContinuous() - 矩阵在存储时如果每一行在内存中没有间隔则返回true
- data() - 返回第一个数值的指针
- row() - 取某行
- col() - 取某列
- rowRange() - 取某个范围内的行
- colRange() - 取某个范围内的列