【3】OpenCV C++版的基础数据类型

OpenCV中的数据类型
OpenCV有很多数据类型,它们都基于一些重要视觉概念的抽象而设计,来提供相对简单,直观的表示和处理。

从组织结构的角度而言,OpenCV的基础数据类型主要分为三类

第一类,直接从C++原语中继承的基础数据类型(如int和float),这些类型包括简单的数组和矩阵。

第二类,辅助对象,这些对象代表更抽象的概念,比如垃圾收集指针,用于数据切片的范围对象(range objects)

第三类,大型数组类型,典型的代表是cv::Mat类,该类用来代表任意维度的包含任意基础元素的数组。

除了这些,OpenCV还有很多标准模板库(STL)。
基础类型介绍
每一个基础类型实际上都是一个相对复杂的类,支持它自己的接口函数、重载以及类似的操作

1.Point类

这个类是OpenCV的基础类型,Point可能是最简单的,它是一个点模板类。

它们可以成为任何类型的点,如整型和浮点型,还分为二维点模板类Point_和三维点模板类Point3_,源代码中定义为:

  typedef Point_<int> Point2i;
  typedef Point2i Point;
  typedef Point_<float> Point2f;
  typedef Point_<double> Point2d;
  typedef Point3_<int> Point3i;
  typedef Point3_<float> Point3f;
  typedef Point3_<double> Point3d;


所以在大多数程序中,Point类是通过类似于cv::Point2i和cv:Point3f这类别名来实例化的,别名的最后一个字母表示构造该点需要的原语:

b是一个无符号字符
s是一个短整型
i是一个32位整型
f是一个32位浮点数
d是一个64位浮点数
Point类原生支持的函数列表:

操作示例
默认构造函数

Point2i p;

Point3i p;

复制构造函数Point3f p2(p1);
值构造函数

Point2i (x0,x1);

Point3d (x0,x1,x2);

构造成固定向量类Vec3f p;
成员访问p.x,p.y
点乘double x = p1.dot(p2);
双精度点乘p1.cross(p2);
叉乘p.inside(r);
判断一个点p是否在矩形r内p.inside(r);
Point point;//创建一个2D点对象
  point.x = 10;//初始化x坐标值
  point.y = 8;//初始化y坐标值
  或者
  Point point = Point(10, 8);

2.Scalar类

cv::Scalar类是四维点类。在这个模板中,所有的成员都是双精度浮点数。定义如下:

template<typename _Tp> class Scalar_ : public Vec<_Tp, 4>
{
public:
    //! default constructor
    Scalar_();
    Scalar_(_Tp v0, _Tp v1, _Tp v2=0, _Tp v3=0);
    Scalar_(_Tp v0);
 
    Scalar_(const Scalar_& s);
    Scalar_(Scalar_&& s) CV_NOEXCEPT;
 
    Scalar_& operator=(const Scalar_& s);
    Scalar_& operator=(Scalar_&& s) CV_NOEXCEPT;
 
    template<typename _Tp2, int cn>
    Scalar_(const Vec<_Tp2, cn>& v);
 
    //! returns a scalar with all elements set to v0
    static Scalar_<_Tp> all(_Tp v0);
 
    //! conversion to another data type
    template<typename T2> operator Scalar_<T2>() const;
 
    //! per-element product
    Scalar_<_Tp> mul(const Scalar_<_Tp>& a, double scale=1 ) const;
 
    //! returns (v0, -v1, -v2, -v3)
    Scalar_<_Tp> conj() const;
 
    //! returns true iff v1 == v2 == v3 == 0
    bool isReal() const;
};

Scalar类支持的操作:

操作示例
默认构造函数Scalar s;
复制构造函数Scalar  s2(s1);
值构造函数

Scalar s(x0);

Scalar s(x0,x1,x2,x3);

元素相乘s1.mul(s2);
(四元素)共轭s.conj();
(四元素)真值测试s.isReal();

 Scalar类是四维双精度向量的快速表示,它是直接从固定向量类模板实例中继承而来。

3.Size类

Size类在实际操作时与Point类类似,而且可以与Point类互相转换,两者的主要区别在于Point类的数据成员是x和y,而size类中对应的成员是width和height。

Size类的三个别名分别是cv::Size, cv::Size2i, cv::Size2f. 前两个等价,最后一个表示32位浮点数大小。

Size类可以与对应的旧类型的OpenCV类(CvSize和CvSizeD32f)互相转换

Size类直接支持的操作:
 

操作示例
默认构造函数

Size sz;

Size2i sz;

Size2f sz;

复制构造函数Size sz2(sz1);
值构造函数Size2f sz(w,h);
成员访问sz.width; sz.height;
计算面积sz.area();

Size类不支持转换到固定向量类,但是固定向量类和Point类可以被转换成Size类

4.Rect类

矩形类包含Point类的成员x和y(矩形左上角)和Size类的成员width和height(代表矩形的大小)。

矩形类并不是从Point类或者Size()类继承过来的,所以并没有从它们中继承操作

Rect直接支持的操作:

操作示例
默认构造函数Rect r;
复制构造函数Rect r2(r1);
值构造函数Rect r(x,y,w,h);
由起始点和大小构造Rect r(p,sz); 
由两个对角构造rect r(p1,p2);
成员访问r.x,r.y,t.width,r.height;
计算面积r.area();
提取左上角r.tl();
提取右上角r.br();
判断p是否在矩形内r.contains(p);

转换操作符和复制构造函数的目的是让cv::Rect能从旧的类型cv::CvRect转换。cv::Rect实际上是用整数实例化的一个矩形模板的别名。

Rect也支持一些列的操作符(覆写),如下表:

操作示例
判断矩形r1和r2的交集Rect r3 = r1&r2; r1&=r2;
同时包含r1和r2的最小面积矩形Rect r3 = r1|r2; r1|=r2;
平移矩形r x个单位Rect rx = r+x; r+=x;
扩大矩形r s个大小Rect rs = r+s; r+=s;
比较矩形r1和矩形r2是否相同bool eq = (r1==r2);
比较矩形r1和矩形r2是否不相同bool eq = (r1!=r2);

5.RotatedRect类

cv::RotatedRect类是OpenCV中少数底层没有使用模板的C++接口类之一,它是包含一个中心点cv::Point2f,一个大小cv::Size2f和一个额外的角度float的容器。

其中浮点型的角度代表图像饶中心点旋转的角度。

RotatedRect和Rect有一个非常重要的不同点事前者是以中心点为原点的。,而Rect则位于左上角为原点。

RotatedRect支持的操作如下:
 

操作

示例

默认构造函数RotatedRect rr();
复制构造函数RotatedRect rr2(rr1);
从两个点构造RotatedRect rr(p1,p2);
值构造函数;需要一个点,一个大小,和一个角度RotatedRect rr(p,sz,theta);
成员访问rr.center,rr,size,rr.angle
返回四个角的列表rr.point(pts[4]);

6.固定矩阵类

固定矩阵类是为编译时就已知维度的矩阵打造的,因为它们内内部的所有数据都是在堆栈上分配的,所以分配和清除都很快。

固定矩阵类同时也是在OpenCV的C++接口中基本类型的核心。

固定向量类继承自固定矩阵类,而其他类的重要操作,要么是继承自固定向量类,要么是依赖于转换成固定向量类。

通常固定矩阵类是一个模板,这个模板是cv::Matx<>,但是独立的矩阵则通常通过别名分配,别名的基础形式是cv::Matx{1,2,...}{1,2...}{f,d},其中的数字可以是1到6之间的任何数。

要表示一个用来处理矩阵代数的矩阵的时候,就会用到矩阵类,如果是图像或者大型点列表这样的大数组,使用固定矩阵类就不是好选择了,应该使用cv::Mat。

固定矩阵类是在编译时就知道矩阵大小的时候用到的,比如相机矩阵

Matx支持的操作如下:

操作示例
默认构造函数

cv::Matx33f m33f;

cv::Matx43d m43d;

复制构造函数cv::Matx22d m22d(n22d);
值构造函数

cv::Matx21f m(x0, x1); 

cv::Matx44d m(x0, x1, x2, x3, ..., x15);

含相同元素的矩阵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; m0 * m1; m0 + m1; m0 -m1;
单例代数m * a, a * m, m / a;
比较m1 == m2; m1 != m2;
点积m1.dot(m2);m1.ddot(m2);
改变矩阵形状m91f = m33f.reshape<9,1>();
变换操作符m44f = (Matx44f) m44d;
提取(i,j)处的2*2子矩阵m44f.get_minor<2, 2>(i, j);
提取第i行m14f = m44f.row(i);
提取第j列m41f = m44.col(j);
提取矩阵对角线m41f = m44f.diag();
计算转置n44f = m44f.t();
逆矩阵n44f = m44f.inv(method);
解线性系统

m31f = m33f.solve(rhs31f, method);

m32f = m33f.solve(rhs32f, method);

每个元素的乘法m1.mul(m2);

7.固定向量类

固定向量类就是从固定矩阵类派生而来的,它们只是为了更方便的使用cv::Matx<>。

在C++继承的意义上,固定向量模板cv::Vec是为列为1的cv::Matx<>。

Vec支持的操作为:

操作示例
默认构造函数Vec2s v2s; Vec6f v6f;
复制构造函数Vec3f u3f(v3f);
值构造函数vec2f v2f(x0,x1);
成员访问v4f[i]; v3w(j);(注意括号和中括号的区别)
向量叉乘v3f.cross(u3f);

固定向量类的最主要的便利是它可以通过单个数索引各项,以及几个特定的额外的函数使常规矩阵运算有意义。

8.复数类

在OpenCV中还有一个应该包含在基础类型中的类,它就是复数类。OpenCV的复数类与STL中的复数类模板Complex<>不一样,但是与之兼容可以互换。最大的区别在于成员获取。

在STL类中,虚部和实部通过成员函数real()和imag()和获取的,而在OpenCV中直接通过成员变量re和im获取。

OpenCV复数类支持的操作:
 

操作示例
默认构造函数Complexf z1; Complex z2;

复制构造函数

Complexf z2(z1);
值构造函数

Complexd z1(re0);

Complexd (re0,im1);

复制构造函数

Complexf u2f(v2f);
成员访问z1.re;z1.mi;
复共轭z2 = z1.conj();

与很多基本类型一样,复数类为重要的模板起了别名,cv::Complexf和cv::Complexd分别是单精度和双精度复数的别名.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值