《学习OpenCV3》第3章 了解OpenCV的数据类型

学习OpenCV系列博客
上一章: 《学习OpenCV3》第2章 OpenCV初探
下一章: 《学习OpenCV3》第4章 图像和大型数组类型(持续更新)

1. OpenCV数据类型分类

1.1 基础数据类型分类:

  • 第一类是直接从C++继承的基础数据类型,比如 int,float 等。这些类型包括简单的数组和矩阵,同时也代表一些简单的几何概念,比如 矩形大小 等;
  • 第二类是辅助对象。这些对象代表更抽象的概念,比如 垃圾收集指针类,用于数据切片的范围对象 range objects, 以及 抽象的终止条件类
  • 第三类可以称为大型数组类型。这些对象原本目的是涵盖数组或一些其他的原语、程序集或更常见的基础数据类型。这一类的典型代表是 Mat 类,该类用来表示任意维度的包含任意基础元素的数组。存储图像是 Mat 类的特殊用途,这个类还涵盖其他类型,比如稀疏矩阵 SparseMat ,它更适用于直方图这样的稀疏数据。
  • 除了这些类型,OpenCV还使用了很多标准模板库(STL)。OpenCV相当依赖 vector 类, 许多OpenCV库函数在参数列表中有vector模板类。

1.2 基础类型概述

  • Vec<> 是固定向量类,它是用来处理小型响亮的。
  • Matx<> 是固定矩阵类(注意不是 Mat) ,它并不是用于大型数组的,而是用于一些特定的小型矩阵操作。固定矩阵类的维度在编译之前必须已知,这使得它的运算效率高,同时消除了许多动态内存分配操作。

2. 深入了解基础类型

2.1 Point类

  • Point类的实现基于一个基础模板结构,所以它可以成为任何类型的点,如整型和浮点型。这里有两个模板,一个是二维点,一个是三维点。Point类的巨大优势就是简单并且开销小。它也可以转换成更广义的类型,比如在需要的时候可以转换为固定向量类或者是固定矩阵类。
  • Point 类通过 Point2i , Point3f 这类别名来实例化。 最后一个字母的含义是:b是无符号字符,s是短整型,i是32位整型,f是32位浮点数,d是64位浮点数。
  • 直接受Point类支持的操作
操作示例
默认构造函数Point2i p
复制构造函数Point3f p2(p1)
值构造函数Point2i(x0,x1)
构造成固定向量类(Vec3f) p
成员访问p.x, p.y
点乘float x = p1.dot(p2)
双精度点乘double x = p1.ddot(p2)
叉乘p1.cross(p2) 针对三维点
判断一个点p是否在矩形r内p.inside( r ) 针对二维点

2.2 Scalar类

  • Scalar是四维点类。
操作示例
默认构造函数Scalar s
复制构造函数Scalar s2(s1)
值构造函数Scalar s(x0) ; Scalar s(x0,x1,x2,x3)
构造成固定向量类(Vec3f) p
元素相乘s1.mul(s2)
(四元数)共轭s.conj(); // return Scalar(s0, -s1, -s2, -s3)
(四元数)真值测试s.isReal(); // return true, if s0 == s1== s2 ==s3)

2.3 size类

  • size类在实际操作时与Point类似,而且可以与其相互转换。这两者之间主要的区别在于Point类的数据成员是xy,而size类的成员是widthheight
  • size类的三个别名是 SizeSize2i, Size2f,前面两个是等价的。
  • size类不支持转换为固定向量类,这一点与Point类不同。但是Point类和固定向量类都可以转成size
操作示例
默认构造函数Size sz, Size2i sz, Size2f sz
复制构造函数Size sz2(sz1)
值构造函数Size sz(w,h)
成员访问sz.width, sz.height
计算面积sz.area()

2.4 Rect类

  • Rect类包含Point类的成员xy(矩形左上角)和size类的成员widthheight(代表了矩形的大小)。然而矩形类并不是从Point类或size类继承过来的,所以它并没有从它们那里继承操作。
操作示例
默认构造函数Rect r
复制构造函数Rect r2(r1))
值构造函数Rect(x,y,w,h)
由左上角点和大小Rect(p, sz)
由两个对角构造Rect(p1, p2)
成员访问r.x; r.y; r.width; r.height
计算面积r.area()
提取左上角r.tl()
提取右下角r.br()
判断点是否在矩形内r.contains( p)
  • Rect对象的覆写操作符
操作示例
矩形r1和矩形r2的交集Rect r3 = r1 & r2
同时能包含矩形r1和矩形r2的最小矩形Rect r3 = r1丨r2 ; r1丨= r2
矩形平移Rect r = r + p
矩形扩大Rect r = r + sz
矩形是否相等bool eq = (r1 == r2); bool ne = (r1 != r2)

2.5 RotatedRect类

  • RotatedRect类包含一个中心点Point2f、一个尺寸Size2f和一个额外的角度float。角度代表图形绕中心旋转的角度,需要注意的是RotatedRect是以中心为原点的。
操作示例
默认构造函数RotatedRect rr
复制构造函数RotatedRect rr2(rr1))
三个点构造(按顺序,如果无法构成矩形会报错)RotatedRect(p1, p2, p3))
值构造函数,需要一个点、一个尺寸、一个角度RotatedRect rr(p, sz, theta)
成员访问rr.center, rr.size, rr.angle
返回四个角的列表rr.points(pts[4])

2.6 固定矩阵类

  • 固定矩阵类在编译时就已知维度,它内部的所有数据都是在堆栈上分配的,分配和清除都很快。
操作示例
默认构造函数Matx33f m33f; Matx43d m43d
复制构造函数Matx22d m2dd(n22d)
值构造函数Matx21f m(x0, x1); Matx4d m(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 )
含相同元素的矩阵m33f = Matx33f::all(x) ;所有元素都是x
全0矩阵m23d = Matx23d::zeros()
全1矩阵m16f = Matx16f ::ones()
单位矩阵m33f = Matx33f.:eye()
创建一个可以容纳另一个矩阵对角线的矩阵m31f = Matx33f::diag()
创建一个均匀分布的矩阵m33f = Matx33f::randu(min, max)
创建一个正态分布的矩阵m33f = Matx33f::nrandn(mean, variance)
成员访问m(i, j), m(i)
矩阵代数运算m1 = m0; mo*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=m44f.col(j)
提取矩阵对角线m41f=m44f.diag()
转置矩阵n44f = m44f.t()
逆矩阵n44f = m44f.inv(method)
解线性系统m31f = m33f.solve( rhs31f, method)
m31f = m33f.solve<2>( rhs32f, method)
每个元素的乘法m1.mul(m2)

2.7 固定向量类

  • 固定向量类是从固定矩阵类派生出来的,只是为了更方便的使用Matx<>,可以说 Vec是列为1的Matx<>
操作示例
默认构造函数Vec2s v2s; Vec6f v6f
复制构造函数Vec3f u3f(v3f)
值构造函数Vec2f v2f(x0,x1)
成员访问v4f[i]; v3w(j)
向量叉乘v3f.cross(u3f)

2.8 复数类

  • OpenCV的复数类与STL复数类模板complex<>不一样,但是与之兼容,可以相互转换。它们最大的区别在于成员获取,在STL类中,虚部和实部是通过成员函数real()imag()获取的,而OpenCV中,直接通过成员变量reim获取。
操作示例
默认构造函数Complexf z1; Complexd z2
复制构造函数Complexf z2(z1)
Complexf u2f(v2f)
值构造函数Complexd z1(re0); Complexd (re0, im1)
成员访问z1.re; z1.im
共轭复数z2 = z1.conj()

3. 辅助对象

3.1 TermCriteria类

  • 很多算法需要一个终止条件以确定何时退出。通常,终止条件的形式要么是达到允许的有限迭代次数(称为COUNTMAX_ITER),要么是某种形式的误差参数(如果接近于如此程度,就可以退出,称为 EPS,即 epsilon 的简称)。

  • 它有三个公有成员变量(type, maxCount, epsilon)。

  • 构造函数TermCriteria(int type, int maxCount, double epsilon).

  • type设置为 TermCriteria::COUNTTermCriteria::EPS ,也可以把这两个条件并在一起:TermCriteria::COUNT | TermCriteria::EPS.

  • COUNTMAX_ITER是等价的,使用哪个看你心情。

  • 需要注意的是 type 参数必须进行相应的设置才可以继续使用 maxCountEPS 的。

    	TermCriteria criteria(TermCriteria::MAX_ITER | TermCriteria::EPS, 10, 0.01);
    	meanShift(backprojection, rect, criteria);
    

3.2 Range类

  • Range 类用于确定一个连续的整数序列。它有两个元素 startend .
  • 在构造函数中设定: Range( int start, int end ).
  • Range范围包含初始值,但不包含终止值。例如:Range rng(0, 4) 包含 0, 1, 2, 3.
  • 使用 size() 可以得到 Range 类的元素数量。
  • 使用 empty() 测试 range 是否为空。
  • 使用 all() 获得 range 的可用范围。
	Range rng = Range(0, 4);
	cout << rng.size() << endl;
	cout << rng.empty() << endl;
	cout << rng.all() << endl; 

在这里插入图片描述

3.3 Ptr模板和垃圾收集

3.3.1 智能指针如何工作

  • 智能指针(Smart Pointer)是C++中一个非常有用的类型。这个指针允许我们创建一个对象的引用,然后把它传递到各处。你可以创建更多的对该对象的引用,然后所有这些引用都会被计数。当引用超出范围,智能指针的引用计数就会减少。一旦所有的引用(指针的实例)小时,这个对象将自动清理(释放)。

  • 首先为要封装的对象定义一个指针模板的实例:可以调用cv::Ptr< Matx33f> p(new Matx33f) 或者 cv::Ptr< Matx33f> p = makePtr< Matx33f>() 来实现

  • 这个模板的构造函数就拥有指向对应对象的指针。进行这样的操作之后,就得到了一个只能指针 p ,这是一个类似指针的对象,你可以随意传递,并且像使用标准指针一样使用它(支持**operator*()operator->()**等操作)。

  • 一旦得到p就可以创建其他相同类型的对象,而不需要把一个指向新的对象的指针传递给他们。例如可以创建 Ptr< Matx33f> q,当你把p的值传递给q时,起始仍然只有一个实际上的Matx33f实例,而pq同时指向它。

  • pq都知道它们只是两个指针中的一个。当p被释放,q就知道自己是原始矩阵仅存的引用。如果q也要被释放,这时它的析构函数将被调用(隐式),由于q发现自己是最后一个引用,所以它会释放原始矩阵。

  • 可以把这个过程想象成办公室最后一个离开的人有责任关灯。

3.3.2 引用计数功能相关附加函数

  • **Ptr()<>**模板类支持多个接口中的与智能指针的引用计数功能相关的附加函数;
  • **addref()release()**增加或减少指针内部的引用计数,这些都是相对危险的函数,但需要自己管理引用计数的时候还是可以使用的。

3.3.3 empty()函数的两个应用

  • 应用1:empty() 函数可以确定一个智能指针是否指向一个已经被释放掉的对象。举个例子:当你对一个对象调用release() 的时候,你仍然有一个智能指针,但它指向的对象已被销毁。
  • 应用2:确定智能指针对象内部对象指针是否出于其他原因而为NULL。举个例子:你给智能指针赋值时是用了一个刚好首先返回NULL的函数(cvLoadImage(), fopen() 等)。

3.3.4 delete_obj()

  • 这是一个引用计数为零时自动调用的函数。

3.4 cv::Exception类和异常处理

  • Exception类型有成员code,err,func,file,line.分别由一个数字的错误代码表示,对应表示产生异常的错误的字符串错误发生的函数名错误发生的文件错误出现在文件中的行数
  • CV_Error(errorcode, description) 会生成并抛出一个有固定文字描述的异常;
  • CV_Error_(errorcode, printf_fmt_str, [printf-args]) 以同样的方式工作,但允许你使用类似printf格式字符串和参数代替固定的描述;
  • CV_Assert(Condition)CV_DbgAssert(Condition) 都会测试程序中所设定的条件(condition),如果条件不符合,则抛出异常。
  • 在较新的OpenCV版本中,这些功能只能在调试(debug)版本使用。
  • 这些宏是抛出异常的首选方法,因为他们会自动为你处理函数、文件和行。

3.5 DataType<>模板

4. 工具函数

4.1 函数列表

  • 工具函数和系统函数
函数名称描述
alignPtr()对齐指针给定字节数
alignSize()将缓冲区大小与给定的字节数对齐
allocate()分配一个C风格的数组对象
Ceil()近似一个浮点数x到不小于x的最近的整数(向上取整)
cubeRoot计算一个数的立方根
CV_Assert()如果给定的条件不为真,则抛出异常
CV_Error()构造cv::Exception (从固定的字符串) 并抛出异常的一个宏
CV_Error_()构造cv::Exception (从格式化的字符串) 并抛出异常的一个宏
deallocate()释放一个C风格的数组对象
error()指示错误并抛出异常
fastAtan2()向量的二维角度的计算
fastFree()释放一个内存缓冲区
fastMalloc()分配一个对齐的内存缓冲区
cvFloor()近似一个浮点数x到不大于x的最近的整数(向下取整)
format()以sprintf类似格式创建一个STL字符串
getCPUTickCount()从内部CPU计时器获得tick技术
getNumThreads()获得当前OpenCV使用的线程
getOptimalDFTSize()计算要传递给DFT的数组的最适宜大小
getThreadNum()获得当前线程的索引
getTickCount()获得系统的tick计数
getTickFrequency获得每秒的tick计数
cvIsInf()判断一个浮点数x是否无穷
cvIsNan()判断一个浮点数x是否不是一个数
cvRound()近似一个浮点数x到最近的整数
setNumThreads()设定OpenCV使用的线程
setUseOptimized()开启或关闭优化代码
useOptimized指示代码优化的启用

5. 模板结构

  • OpenCV 2.1以及后续的版本都建立在类似于STL、boost及其他类似库的模板元编程风格之上。这些库的设计非常强劲,不管是在质量上还是在速度上都非常领先,并且对开发者保持了最大限度的自由。从惯例上来说,OpenCV中所使用的模板结构允许算法以一种抽象的形式表达并且不需要依赖于C++的基本结构,甚至不依赖于OpenCV的基本结构。
  • 通用的固定长度模板
函数名称描述
cv::Point_< Type T>包含两个类型T对象的点
cv::Rect_< Type T>位置、宽度和高度, 均为类型T
Vec< Type T, int H>一个类型T的集合
Matx< Type T, int H, int W>一个H* W的类型T
Scalar_< Type T>一个包含四个类型T对象的集合(和cv::Vec< T, 4>)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MechMaster

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值