对有关opencv的基础知识做一系列的总结,今天是第一节
第一章
1.1介绍
OpenCV(Open Source Computer Vision Library)是一个基于BSD协议的开源库,它包含了数百个计算机视觉的算法实现。这个文档描述了OpenCV 2.x的API函数,这个版本的API是基于C++,而早期的1.x版本的OpenCV是基于C语言的。后者在opencv 1x.pdf中给出了描述。
OpenCV具有模块化结构,这意味着程序包中包含着一些动态和静态的库。以下列出的是可用的模块:
- core(核心)——这个紧凑的模块定义了一些基础的数据结构,包括密集型多维数组Mat和一些其他模块将会用到的基础函数。
- imgproc(图像处理)——在图像处理模块中包括了线性和非线性的图像滤波功能,几何变换(调整大小、仿射、透视、重映射等),色彩空间变换,以及直方图操作等等。
- video(视频)——视频分析模块包括了包括了运动估计、背景提取、对象追踪等功能。
- calib3d(3D标定)——基本的多视角几何算法、相机标定、目标姿势估计、立体对应算法和3D重构等。
- features2d(2D特征)——特征检测、描述和模式匹配。
- objdetect(目标检测)——对预先定义好的的物体和实例进行检测(例如人脸、眼睛、被子、人、汽车等等)。
- highgui——一个简单易用的视频捕捉、图片和视频编码接口,以及简单的UI实现。
- gpu——区别于其他OpenCV模块的GPU加速算法。
- ……一些其他的帮助模块,例如函数链接型神经网络、Google测试封装、Python绑定等等。
接下来的文档描述了各个模块的功能。但是首先要确保弄明白通常情况下库中的API函数是怎样使用的。
第二章
核心——核心函数
2.1 基础结构
数据类型
类:DataType
OpenCV原始数据类型的特征模版。OpenCV的原始数据类型包括unsigned char、bool、signed char、unsigned short、signed short、int、float、double以及由这些基础类型组成的元组,这些元组中的所有值都属于相同的类型。这个原始数据类型列表中的所有类型都可以使用一个标示符进行表示CV_<bit-depth>{U|S|F}C(<number_of_channels>),例如,uchar ~ CV_8UC1,3元素的浮点元组~ CV_32FC3,等等。一个一般的OpenCV结构体能够被存储到一个单独的实例中,例如一个原始数据类型Vec。多个实例可以被存储在std::vector、Mat、Mat_、SparseMat、OparseMat_或其他可以保存Vec实例的容器中。
DataType类主要用来为原始数据类型提供描述,同时它不会给对应的类加入子段和方法(实际上不可能修改C/C++的原始数据类型)。这个技术依赖于C++的类特性。DataType本身并不会被使用,但是他的特殊版本会被使用,例如:
template<> class DataType<uchar>
{
typedef uchar value_type;
typedef int work_type;
typedef uchar channel_type;
enum { channel_type = CV_8U, channels = 1, fmt=’u’, type = CV_8U };
};
...
template<typename _Tp> DataType<std::complex<_Tp> >
{
typedef std::complex<_Tp> value_type;
typedef std::complex<_Tp> work_type;
typedef _Tp channel_type;
// DataDepth is another helper trait class
enum { depth = DataDepth<_Tp>::value, channels=2,
fmt=(channels-1)*256+DataDepth<_Tp>::fmt,
type=CV_MAKETYPE(depth, channels) };
};
...
这个类的主要的目的是为为OpenCV的兼容数据类型标示符转换编译类型信息,例如:
// 申请一个 30x40 浮点矩阵
Mat A(30, 40, DataType<float>::type);
Mat B = Mat_<std::complex<double> >(3, 3);
// 下边将会打印出6,2,意思是depth == CV_64F,channels == 2
cout << B.depth() << ", " << B.channels() << endl;
所以这个特性用来告诉OpenCV你当前在使用什么数据类型,即使这个类型并非源自于OpenCV。例如,矩阵B将会被编译,因为OpenCV定义了专门的模版类DataType<complex<_Tp> >。这个机制也用于泛型机制。
Point_
类:Point_
2D点的模板类,用来描述它的x和y坐标。这个类的实例可以与C结构体CvPoint和CvPoint2D32f之间进行互相转换。其中有类型转换运算符将点的坐标转换成指定的类型。将浮点型坐标转换成整形坐标要通过舍入来完成。通常,转换工作会对每一个坐标执行这个操作。除了上边提到的类成员,以下列出的其它对点的使用操作:
pt1 = pt2 + pt3;
pt1 = pt2 - pt3;
pt1 = pt2 * a;
pt1 = a * pt2;
pt1 += pt2;
pt1 -= pt2;
pt1 *= a;
double value = norm(pt); // L2 norm
pt1 == pt2;
pt1 != pt2;
为了使用方便,还定义了下边的类别名:
typedef Point_<int> Point2i;
typedef Point2i Point;
typedef Point_<float> Point2f;
typedef Point_<double> Point2d;
例如:
Point2f a(0.3f, 0.f), b(0.f, 0.4f);
Point pt = (a + b)*10.f;
cout << pt.x << ", " << pt.y << endl;
Point3_
类:Point3_
3D点的模板类,用来描述它的x、y和z坐标。这个类的实例可以与C结构体CvPoint2D32f之间进行互相转换。与Point_相似,3D坐标可以被转换成其他类型。同时这个类也支持vector和比较操作。
Point3_<>有以下可用的别名:
typedef Point3_<int> Point3i;
typedef Point3_<float> Point3f;
typedef Point3_<double> Point3d;
Size_
类:Size_
用于指定图像和矩形尺寸的类模板。这个类包含两个成员变量width和height。这个结构体可以与老版OpenCV中的CvSize和CvSizeD32f之间进行转换。能够应用于Point_类的算法和比较操作对Size_也是有效的。
OpenCV定义了以下Size_<>的别名:
typedef Size_<int> Size2i;
typedef Size2i Size;
typedef Size_<float> Size2f;
Rect_
类:Rect_
2D矩形的模板类,用以下参数进行描述:
- 左上角的坐标。这是一个OpenCV中的内定的值Rect_::x和Rect_::y。但是在你的算法中可能会从左下角计算x和y。
- 矩形的宽和高。
OpenCV假设矩形的上边沿和左边沿是包含的,而右边沿和下边沿是不包含的。例如,如果符合以下情况,则方法Rect_::contains将返回true:
x <pt:x < x + width; y<pt:y < y + height
实际上在OpenCV中循环浏览一个图像的ROI(ROI被通过Rect_<int>指定)是这样实现的:
for(int y = roi.y; y < roi.y + rect.height; y++)
for(int x = roi.x; x < roi.x + rect.width; x++)
{
// ...
}
除了成员变量,以下对于矩形的操作也得到了实现:
- rect = rect +/- point (通过某一偏移值移动矩形)
- rect = rect +/-size (通过某一数量扩大或缩小矩形)
- rect += point, rect -= point, rect += size, rect -= size (扩张操作)
- rect = rect1 & rect2 (矩形相交)
- rect = rect1 | rect2 (包含rect2和rect3的最小区域 )
- rect &= rect1, rect |= rect1 (and the corresponding augmenting operations)
- rect == rect1, rect != rect1 (矩形比较)
下边是一个如何确定矩形包含关系的例子(rect1属于rect2):
template<typename _Tp> inline bool
operator <= (const Rect_<_Tp>& r1, const Rect_<_Tp>& r2)
{
return (r1 & r2) == r1;
}
为了便利,Rect_<>有以下别名:
typedef Rect_<int> Rect;