目录
openCV的数据类型
基础类型
固定向量类cv::Vec<>
固定矩阵类 cv::Matx<>
cv::Point<>类
cv::Scalar<>
Size类
cv::Rect类
cv::RotatedRect类
复数类
OpenCV有很多数据类型,他们都基于一些重要视觉概念的抽象而设计,以此提供相对简单、直观的表示和处理。
OpenCV的基础数据类型主要分为三类:
第一类是直接从C++原语中继承的基础数据类型(如int和float等)。
第二类是辅助对象:这些对象代表更抽象的概念,比如垃圾收集指针类、用于数据切片的范围对象(range objects)以及抽象的终止条件等。
第三类可以称为大型数组类型。这些对象原本目的是涵盖数组或一些其他的原语、程序集或更常见的基础数据类型。代表:cv::Mat
OpenCV还使用了很多标准模板库(STL)。OpenCV相当依赖vector类,许多OpenCV库函数在参数列表中有vector模板类。
最简单的基础数据类型是模板类cv::Vec<>,它是一个原语的容器类,即固定向量类。
固定向量类是从固定矩阵类派生出来的,固定向量模板cv::Vec 是列为 1 的cv::Matx<>
cv::Vec<>是一个适用任何类型的容器。
虽然cv::Vec<>是模板,但一般使用它的别名(typedef)以便用于通用的实例。任何有着cv::Vec{2, 3, 4, 6}{b, w, s, i, f, d}形式的生命,对于2-6个维度的6种数据类型的任何组合都是有效的。
例如:
名称 | 对应解释 |
---|---|
cv::Vec2i | 2个元素的整型向量 |
cv::Vec3i | 3个元素的整型向量 |
cv::Vec4d | 4个元素的双精度浮点向量 |
6种数据类型的对应:
缩写 | 数据类型 |
---|---|
b | unsigned char |
w | unsigned short |
s | short |
i | int |
f | float |
d | double |
cv::Vec 支持的操作
操作 | 示例 |
---|---|
默认构造函数 | cv::Vec2s v2s; |
复制构造函数 | cv::Vec3f u3f(v3f); |
值构造函数 | cv::Vec6d v6d(x0, x1, x2, x3, x4, x5); |
成员访问 | u3f[i]; u3f(j); ( ()和[] 操作符都可以使用) |
向量叉乘 | v3f.cross(u3f);(仅用于三维,其他异常) |
int main()
{
cv::Vec v3b;
cv::Vec2b v2b(1, 2);
cv::Vec2b v2b2(3, 5);
cv::Vec3f v3b2(1, 2, 3);
cv::Vec3f v3b3(2, 5, 3);
int n = v2b[1];
cout << "元素访问:" << (int)v2b[1] << (int)v2b(1) << endl;
cv::Vec3f res = v3b2.cross(v3b3);
cout << "叉乘:" << res[1] << endl;
return EXIT_SUCCESS;
}
cv::Matx<>并不是用于大型数组的,相反,它是设计用于一些特定的小型矩阵操作。
cv::Matx<>一般都以别名cv::Matx{1,2,3,4,6}{1,2,3,4,6}{f,d}的形式应用。
固定矩阵类的维度在编译之前必须已知,正因如此使得固定矩阵类的运算效率高,同时消除了许多动态内存分配操作。内部的数据都是在栈上分配的,所以分配和清楚都很快。
固定矩阵类也是在OpenCV的C++接口中基本类型的核心。
当你要表示一个用来处理矩阵代数的矩阵时,就需要用到固定矩阵类。
cv::Matx支持的操作
操作 | 示例 |
---|---|
默认构造函数 | cv::Matx33f m33f; cv::Matx43d m43d; |
复制构造函数 | cv::Matxm22d(n22d); |
值构造函数 | cv::Matx22d m(x0, x1, x2, x3); |
含相同元素的矩阵 | m33f = cv::Matx33f::all(x); |
全零矩阵 | m23d = cv::Matx23d::zeros(); |
全一矩阵 | m16f = cv::Matx16f::ones(); |
创建一个单位矩阵 | m33f = cv::Matx33f::eye(); |
创建一个可以容纳另一个矩阵对角线的矩阵 | m31f = cv::Matx33f::diag(); |
创建一个均匀分布的矩阵 | m33f = cv::Matx33f::randu(min, max); |
创建一个正态分布的矩阵 | m33f = cv::Matx33f::nrandn(mean, variance); |
成员访问 | m(i, j); m(i)(一个参数只对应一维矩阵) |
矩阵代数运算 | m1 = m0; m1 * m0; m0 + m1; m0 - m1 |
单例(singleton)代数 | m*a; a*m; m / a; |
比较 | m1 == m2; m1 != m2; |
点积(元素相乘的积,单精度) | m1.dot(m2); |
点积(元素相乘的积,双精度) | m1.ddot(m2); |
改变矩阵形状 | m91f = m33f.reshape<9, 1>(); |
变换操作符(类型转换) | m44f = (cv::Matx44f)m44d; |
提取(i,j)处的2*2子矩阵 | m44f.get_minor<2, 2>(i, j); |
提取第 i 行 | m14f = m44f.row(i); |
提取第 j 列 | m41f = m44f.col(j); |
提取矩阵对角线 | m41f = m44f.diag(); |
计算转置 | m44f = m44f.t(); |
逆矩阵 | n44f = m44f.inv(method);(默认方法:cv::DECOMP_LU) |
解线性系统 | m31f = m33f.solve( rhs31f, method ); m32f = m33f.solve<2>( rhs32f, method );(默认方法:DECOMP_LU) |
逐元素相乘 | m1.mul( m2 ); |
解线性系统:当隐含的矩阵方程的右边有多个列时使用模板的形式,在上例中,本质是在同时解决k个不同的系统,k的值必须作为模板参数传递给solve<>();它还决定结果矩阵中的列数。
bool cv::solve(
inputArray src1,
inputArray src2,
outputArray dst,
int flags = DECOMP_LU
);
//解线性方程 A*X=B
//src1 线性系统的左侧(相当于上面的A),src2 线性系统的右侧(相当于上面的B),dst 输出的解决方案(相当于要求解的X),flag为使用的方法
//使用CV_LU方法,如果src1不是奇异矩阵(奇异矩阵行列式为0 ,没有逆矩阵)则返回1,否则返回0
//如果A是奇异矩阵 也就不存在逆矩阵 所以无法计算
Point类由自己的模板派生的,但同时他们也可以从固定向量类转换得到。
Point类和固定向量类之间不同处:
Point类:成员通过名称变量访问的(mypoint.x, mypoint.y)
Vec类:成员通过下标访问(myvec[0], myvec[1])
Point类是通过别名调用作为一个正确模板的实例。这些别名可以是:cv::Point2i, cv::Point2f, cv::Point2d, cv::Point3i, cv::Point3f, cv::Point3d.
下表中有几个非常重要的受支持的操作,但它们是间接的通过隐式转换到固定向量类而受支持。这些操作显著包含所有的向量(vector)和标量(singleton),重载了线性代数的操作符以及比较运算符。
注释:singleton表示:任何类型的向量都是一个数组的实例。
Point类支持的操作
操作 | 示例 |
---|---|
默认构造函数 | cv::Point2i p;cv::Point3i p; |
复制构造函数 | cv::Point3f p2(p1); |
值构造函数 | cv::point2i(x0, x1); cv::Point3d p(x0, x1, x2); |
构造成固定向量类 | (cv::Vec3f) p; |
成员访问 | p.x; p.y;p.z; |
点乘 | float x = p1.dot( p2 ) |
双精度点乘 | double x = p1.ddot( p2 ) |
叉乘(矢量积) | p1.cross( p2 )(只针对3维point) |
判断一个点p是否在矩形r内 | p.inside( r )(只针对2维point) |
cv::Scalar本质上是一个四维Point类,且一般是双精度四元素向量的别名。其所有成员都是双精度浮点数。
cv::Scalar对象的元素是通过证书下标来访问的,与cv::Vec<>相同,因为cv::Scalar直接继承cv::Vec
cv::Scalar类支持的操作
操作 | 示例 |
---|---|
默认构造函数 | cv::Scalar s; |
复制构造函数 | cv::Scalar s2(s1); |
值构造函数 | cv::Scalar s(x0); cv::Scalar s(x0, x1, x2, x3); |
元素相乘 | s1.mul(s2); |
(四元数)共轭 | s.conj();(返回cv::Scalar(s0, -s1, -s2, -s3)) |
(四元数)真值测试 | s.isReal(); (如果s1 == s2 == s3 == 0, 返回true) |
cv::Scalar直接从固定向量类模板实例中继承而来,它继承了所有的向量代数操作、成员访问函数(操作符[])和一些固定向量类的特性。
Size类在实际操作时与Point类相似,而且可以与Point类相互转换。区别在于Point类的数据成员是x和y,而Size的成员是 width 和 height。
Size类有三个别名:cv::Size, cv::Size2i, cv::Size2f. 前两个是等价的。
Size类支持的操作
操作 | 示例 |
---|---|
默认构造函数 | cv::Size sz; cv::Size2i sz; cv::Size2f sz; |
复制构造函数 | cv::Size sz2(sz1); |
值构造函数 | cv::Size2f sz(w, h); |
成员访问 | sz.width, sz.height; |
计算面积 | sz.area(); |
矩形类包含Point类的成员x和y(矩形左上角)和Size类的成员width和height(代表矩形的大小)。然而他们并没有继承关系。
cv::Rect支持的操作
操作 | 示例 |
---|---|
默认构造函数 | cv::Rect r; |
复制构造函数 | cv::Rect r2(r1); |
值构造函数 | cv::Rect(x, y, w, h); |
由起始点和大小构造 | cv::Rect(cv::Point, cv::Size); |
由两个对角构造 | cv::Rect(cv::Point, cv::Point); |
成员访问 | r.x; r.y; r.width; r.height |
计算面积 | r.area() |
提取左上角 | r.tl(); |
提取右下角 | r.br(); |
判断点p是否在矩形r内 | r.contains(p); |
cv::Rect 对象的覆写操作符
操作 | 示例 |
---|---|
矩形r1和矩形r2的交集 | cv::Rect r3 = r1 & r2; r1 &= r2; |
同时包含矩形r1和矩形r2的最小面积矩形 | cv::Rect r3 = r1 | r2; r1 |= r2; |
平移矩形r x个数量 | cv::Rect rx = r + x; r += x; |
扩大矩形r s大小 | cv::Rect rs = r + s; r += s; |
比较矩形r1 和矩形r2是否相等 | bool eq = (r1 == r2); |
比较矩形r1 和矩形r2是否不相等 | bool ne = (r1 != r2); |
cv::RotatedRect类是OpenCV中少数底层没有使用模板的C++接口类之一。它包含一个中心点cv::Point2f,一个大小 cv::Size2f 和一个额外的角度 float 的容器。其中浮点型数据(float)的角度代表图形绕中心点旋转的角度。
cv::RotatedRect 是以中心为原点
cv::Rect 以左上角为原点
cv::RotatedRect 支持的操作
操作 | 示例 |
---|---|
默认构造函数 | cv::RotatedRect rr(); |
复制构造函数 | cv::RotatedRect rr2(rr1); |
从两个点构造 | cv::RotatedRect(cv::Point, cv::Point); |
值构造函数(一个点,一个大小,一个角度) | cv::RotatedRect rr(cv::Point, cv::Size, float angle); |
成员访问 | rr.center, rr.size, rr.angle; |
返回四个角的列表 | rr.points(pts[4]); |
OpenCV的复数类与STL复数类模板complex<> 不一样,但与之兼容,可以互相转换。
区别:STL中,使用成员函数 real() 和 imag() 获取实部和虚部
OpenCV中通过成员变量 re 和 img 获取。
Opencv复数类支持的操作
操作 | 示例 |
---|---|
默认构造函数 | cv::Complexf z1; cv::Complexd z2; |
复制构造函数 | cv::Complexf z2(z1); |
值构造函数 | cv::Complexd z1(re0);cv::Complexd(re0, im1); |
复制构造函数 | cv::Complexf u2f(v2f); |
成员访问 | z1.re; z1.im; |
复共轭 | z2 = z1.conj(); |