一,opencv模块core内容第一部分——Basic Structures(基本数据结构)
该模块中包含了opencv所利用到的最基本的数据结构,是opencv最基础最核心,也是最需要掌握的内容,本章节主要介绍opencv2.x基于c++的类,只是顺带提一下opencv1.x中的基于c语言类型的数据结构。
opencv2.x中最基础的数据类型有如下几个:
DataType——数据类型
Point_,Point3_——点(x,y,z)
Size_——尺寸(width*heigth)
Rect_,RotatedRect——矩形(x,y,width,height)
TermCriteria——终止条件
Matx——小矩阵
Vec——向量
Scalar_——标量
Range——范围Ptr
——指针(重点,难点,需花时间
)Mat
,Mat_——矩阵(最重要,最核心,需要很多时间)
InputArray,OutputArray——输入输出数组
NartMatIterator——矩阵迭代
SparseMat,SparseMat_——稀疏矩阵
Algorithm——算法
">
二,DataType
数据类型简介:
该类是opencv的最原始的数据类型,opencv的基本的数据类型有unsigned char, bool, signed char, unsigned short, signed short, int , float, double 或者是这些类型的多个元素的组合(rgb,三通道数据类型)
。以上列表中任何原始数据类型都可以被CV_ <bit-depth>{U|S|F}C(<number_of_channels>)
来定义。例如,uchar——CV_8UC1,3个元素的浮点元组——CV_32FC3
等等。一个通用的能够存储这样一个原始数据类型的opencv结构就是Vec。这样的数据类型的实例可以被存储在std::vector, Mat, Mat_, SparseMat, SparseMat_, 或者是任何其他能偶存储Vec实例的容器类。结论:DataType就是opencv最基本的数据类型,
CV_8UC1之类的东西。
类定义
1 | template<> class DataType<uchar> |
这个类的作用就是讲可确定编译时间类型的数据转化为opencv特定的可编译数据类型。例如:1
2
3
4
5
6// allocates a 30x40 floating-point matrix
Mat A(30, 40, DataType<float>::type);
Mat B = Mat_<std::complex<double> >(3, 3);
// the statement below will print 6, 2 /*, that is depth == CV_64F, channels == 2 */
cout << B.depth() << ", " << B.channels() << endl;
在平常的使用中,一般不会直接使用这个类的对象,而是直接使用CV_8UC3
等预定义常量
三,Point_,Point3_
数据类型简介
这两个类就是为了描述计算机图像中的点,Point_描述的是2维的点(x, y)(在opencv1.x中对应的是CvPoint和CvPoint2D32f),Point3_描述的是3维的点(x, y, z) 。
类定义
1 | template<typename _Tp> class CV_EXPORTS Point_ |
其中以Point_模板类为原型预定义了许多表示2维坐标点的类供我们使用:如1
2
3
4typedef Point_<int> Point2i;
typedef Point2i Point;
typedef Point_<float> Point2f;
typedef Point_<double> Point2d;
使用范例:1
2
3Point2f a(0.3f, 0.f), b(0.f, 0.4f);
Point pt = (a + b)*10.f;
cout << pt.x << ", " << pt.y << endl;
Point_类实例能够进行多种运算:
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;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30template<typename _Tp> class CV_EXPORTS Point3_
{
public:
typedef _Tp value_type;
// various constructors
Point3_();
Point3_(_Tp _x, _Tp _y, _Tp _z);
Point3_(const Point3_& pt);
explicit Point3_(const Point_<_Tp>& pt);
Point3_(const CvPoint3D32f& pt);
Point3_(const Vec<_Tp, 3>& v);
Point3_& operator = (const Point3_& pt);
//! conversion to another data type
template<typename _Tp2> operator Point3_<_Tp2>() const;
//! conversion to the old-style CvPoint...
operator CvPoint3D32f() const;
//! conversion to cv::Vec<>
operator Vec<_Tp, 3>() const;
//! dot product
_Tp dot(const Point3_& pt) const;
//! dot product computed in double-precision arithmetics
double ddot(const Point3_& pt) const;
//! cross product of the 2 3D points
Point3_ cross(const Point3_& pt) const;
_Tp x, y, z; //< the point coordinates
};
同样的,Point3_也预定义了一些类让我们直接使用:如1
2
3typedef Point3_<int> Point3i;
typedef Point3_<float> Point3f;
typedef Point3_<double> Point3d;
点 类型的数据结构是opencv中很重要的类型之一。
四,Size_
数据类型简介
该数据类型主要用来表示一定大小的矩形框,它的最主要的数据成员就是width和height了。在opencv1.x中和Size_有相同作用的数据结构就是CvSize和CvSize2D32f了。
类定义
1 | template<typename _Tp> class CV_EXPORTS Size_ |
当然同Point_一样,Size_也预定义了一些数据类型供我们使用1
2
3typedef Size_<int> Size2i;
typedef Size2i Size;
typedef Size_<float> Size2f;
该数据类型时opencv中我们最常用的数据类型之一。
五,Rect_,RotatedRect
数据类型简介
该类则是点Point和尺寸Size的合体了,代表着一副图像中在某个特定位置的矩形框。它最主要的数据成员就是(x, y, width, height),(x, y)表示矩形框左上顶点的位置,而RotatedRect则代表着一个旋转以后的矩形框,除了和矩形框拥有相同的(x, y, width, height)以外,还多了一个angel(旋转角度)的数据成员:
类定义
1 | template<typename _Tp> class CV_EXPORTS Rect_ |
该模版类预定义了一些类,来供我们使用1
typedef Rect_<int> Rect;
该类实例能够进行多种数学运算如下:1
2
3
4
5
6
7rect = rect + point (矩形位置平移)
rect = rect + size (扩大或缩小矩形)
rect += point, rect -= point, rect += size, rect -= size
rect = rect1 & rect2
rect = rect1 | rect2
rect &= rect1, rect |= rect1
rect == rect1, rect != rect1
该类型是opencv中最常用的数据类型之一。
1 | class CV_EXPORTS RotatedRect |
旋转矩形使用范例如下:1
2
3
4
5
6
7
8
9
10
11
12
13Mat image(200, 200, CV_8UC3, Scalar(0));
RotatedRect rRect = RotatedRect(Point2f(100,100), Size2f(100,50), 30);
Point2f vertices[4];
rRect.points(vertices);
for (int i = 0; i < 4; i++)
line(image, vertices[i], vertices[(i+1)%4], Scalar(0,255,0));
Rect brect = rRect.boundingRect();
rectangle(image, brect, Scalar(255,0,0));
imshow("rectangles", image);
waitKey(0);
六,Mat
, Matx, Mat_, SparseMat, SparseMat_
数据类型简介
矩阵是计算机视觉,计算机图像处理中最终要的概念。由于图像在计算机中都采用像素点来表示,一副图像是由width*height个像素点来组成,这所有的点组合起来就像是数学中的Mat(矩阵)。将矩阵的使用学好了,对于计算机图像处理,计算机视觉的认知就算是真正的开始了。毫无疑问,矩阵(Mat)这种数据类型是opencv最核心的数据类型,没有之一。然而为了应对各种图像的情况,opencv定义了多种类型的矩阵供我们使用。以下便让我一一介绍:
类定义
- Mat(矩阵)
该矩阵代表着n维数字类型的单通道或者是多通道的数组类型的数据。它可以存储实数或者是复数向量和矩阵,灰度图或者彩色图,立体像素卷,向量域,点云,直方图(高维的直方图最好用稀疏矩阵SparseMat来存储)等等。数组M的数据位置被数组M.step[]定义,所以访问矩阵中的M(i0,i1,···,in-1),就可以通过如下公式访问:= M.data + M.step[0]*i_0 + M.step[1]*i_1 + ... + M.step[M.dims-1]*i_{M.dims-1} ``` 1
对于二维矩阵来说,访问其中的元素就是 ```addr(M_{i,j}) = M.data + M.step[0]*i + M.step[1]*j
在opencv1.x中与矩阵Mat相对应的数据类型就是CvMat, IplImage, 和CvMatND等,其类定义如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27class CV_EXPORTS Mat
{
public:
// ... a lot of methods ...
...
/*! includes several bit-fields:
- the magic signature
- continuity flag
- depth
- number of channels
*/
int flags;
//! the array dimensionality, >= 2
int dims;
//! the number of rows and columns or (-1, -1) when the array has more than 2 dimensions
int rows, cols;
//! pointer to the data
uchar* data;
//! pointer to the reference counter;
// when array points to user-allocated data, the pointer is NULL
int* refcount;
// other members
...
};
一般情况下表示一副图像只需要二维矩阵就够了,要么一个像素点事灰度值,要么一个像素点是一个向量,存储rgb三色。
基本的构造一个Mat对象的方法如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34// make a 7x7 complex matrix filled with 1+3j.
Mat M(7,7,CV_32FC2,Scalar(1,3));
// and now turn M to a 100x60 15-channel 8-bit matrix.
// The old content will be deallocated
M.create(100,60,CV_8UC(15));
// create a 100x100x100 8-bit array
int sz[] = {100, 100, 100};
Mat bigCube(3, sz, CV_8U, Scalar::all(0));
// add the 5-th row, multiplied by 3 to the 3rd row
M.row(3) = M.row(3) + M.row(5)*3;
// now copy the 7-th column to the 1-st column
// M.col(1) = M.col(7); // this will not work
Mat M1 = M.col(1);
M.col(7).copyTo(M1);
// create a new 320x240 image
Mat img(Size(320,240),CV_8UC3);
// select a ROI
Mat roi(img, Rect(10,10,100,100));
// fill the ROI with (0,255,0) (which is green in RGB space);
// the original 320x240 image will be modified
roi = Scalar(0,255,0);
Mat A = Mat::eye(10, 10, CV_32S);
// extracts A columns, 1 (inclusive) to 3 (exclusive).
Mat B = A(Range::all(), Range(1, 3));
// extracts B rows, 5 (inclusive) to 9 (exclusive).
// that is, C ~ A(Range(5, 9), Range(1, 3))
Mat C = B(Range(5, 9), Range::all());
Size size; Point ofs;
C.locateROI(size, ofs);
// size will be (width=10,height=10) and the ofs will be (x=1, y=5)
Mat的构造函数如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38C++: Mat::Mat()
C++: Mat::Mat(int rows, int cols, int type)
C++: Mat::Mat(Size size, int type)
C++: Mat::Mat(int rows, int cols, int type, const Scalar& s)
C++: Mat::Mat(Size size, int type, const Scalar& s)
C++: Mat::Mat(const Mat& m)
C++: Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP)
C++: Mat::Mat(Size size, int type, void* data, size_t step=AUTO_STEP)
C++: Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange=Range::all() )
C++: Mat::Mat(const Mat& m, const Rect& roi)
C++: Mat::Mat(const CvMat* m, bool copyData=false)
C++: Mat::Mat(const IplImage* img, bool copyData=false)
C++: template<typename T, int n> explicit Mat::Mat(const Vec<T, n>& vec, bool copyData=true)
C++: template<typename T, int m, int n> explicit Mat::Mat(const Matx<T, m, n>& vec, bool copyData=true)
C++: template<typename T> explicit Mat::Mat(const vector<T>& vec, bool copyData=false)
C++: Mat::Mat(int ndims, const int* sizes, int type)
C++: Mat::Mat(int ndims, const int* sizes, int type, const Scalar& s)
C++: Mat::Mat(int ndims, const int* sizes, int type, void* data, const size_t* steps=0)
C++: Mat::Mat(const Mat& m, const Range* ranges)
Parameters:
ndims – Array dimensionality.
rows – Number of rows in a 2D array.
cols – Number of columns in a 2D array.
roi – Region of interest.
size – 2D array size: Size(cols, rows) . In the Size() constructor, the number of rows and the number of columns go in the reverse order.
sizes – Array of integers specifying an n-dimensional array shape.
type – Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices.
s – An optional value to initialize each matrix element with. To set all the matrix elements to the particular value after the construction, use the assignment operator Mat::operator=(const Scalar& value) .
data – Pointer to the user data. Matrix constructors that take data and step parameters do not allocate matrix data. Instead, they just initialize the matrix header that points to the specified data, which means that no data is copied. This operation is very efficient and can be used to process external data using OpenCV functions. The external data is not automatically deallocated, so you should take care of it.
step – Number of bytes each matrix row occupies. The value should include the padding bytes at the end of each row, if any. If the parameter is missing (set to AUTO_STEP ), no padding is assumed and the actual step is calculated as cols*elemSize() . See Mat::elemSize() .
steps – Array of ndims-1 steps in case of a multi-dimensional array (the last step is always set to the element size). If not specified, the matrix is assumed to be continuous.
m – Array that (as a whole or partly) is assigned to the constructed matrix. No data is copied by these constructors. Instead, the header pointing to m data or its sub-array is constructed and associated with it. The reference counter, if any, is incremented. So, when you modify the matrix formed using such a constructor, you also modify the corresponding elements of m . If you want to have an independent copy of the sub-array, use Mat::clone() .
img – Pointer to the old-style IplImage image structure. By default, the data is shared between the original image and the new matrix. But when copyData is set, the full copy of the image data is created.
vec – STL vector whose elements form the matrix. The matrix has a single column and the number of rows equal to the number of vector elements. Type of the matrix matches the type of vector elements. The constructor can handle arbitrary types, for which there is a properly declared DataType . This means that the vector elements must be primitive numbers or uni-type numerical tuples of numbers. Mixed-type structures are not supported. The corresponding constructor is explicit. Since STL vectors are not automatically converted to Mat instances, you should write Mat(vec) explicitly. Unless you copy the data into the matrix ( copyData=true ), no new elements will be added to the vector because it can potentially yield vector data reallocation, and, thus, the matrix data pointer will be invalid.
copyData – Flag to specify whether the underlying data of the STL vector or the old-style CvMat or IplImage should be copied to (true) or shared with (false) the newly constructed matrix. When the data is copied, the allocated buffer is managed using Mat reference counting mechanism. While the data is shared, the reference counter is NULL, and you should not deallocate the data until the matrix is not destructed.
rowRange – Range of the m rows to take. As usual, the range start is inclusive and the range end is exclusive. Use Range::all() to take all the rows.
colRange – Range of the m columns to take. Use Range::all() to take all the columns.
ranges – Array of selected ranges of m along each dimensionality.
Mat的其他各种成员方法见Mat详解
- Matx(小矩阵)
该类型的矩阵为能够确定类型,确定尺寸和确定编译时间的小矩阵。
其基本定义如下;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19template<typename _Tp, int m, int n> class Matx {...};
typedef Matx<float, 1, 2> Matx12f;
typedef Matx<double, 1, 2> Matx12d;
...
typedef Matx<float, 1, 6> Matx16f;
typedef Matx<double, 1, 6> Matx16d;
typedef Matx<float, 2, 1> Matx21f;
typedef Matx<double, 2, 1> Matx21d;
...
typedef Matx<float, 6, 1> Matx61f;
typedef Matx<double, 6, 1> Matx61d;
typedef Matx<float, 2, 2> Matx22f;
typedef Matx<double, 2, 2> Matx22d;
...
typedef Matx<float, 6, 6> Matx66f;
typedef Matx<double, 6, 6> Matx66d;
使用范例如下:1
2
3
4Matx33f m(1, 2, 3,
4, 5, 6,
7, 8, 9);
cout << sum(Mat(m*m.t())) << endl;
Mat_
SparseMat(稀疏矩阵)
SparseMat_
七,Vec和Scalar_
数据类型简介
Vec是一个储存短数字类型的向量,相当于Matx的特例。
Scalar_是从Vec继承来的4元向量。
类定义
Vec有许多预定义的类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23template<typename _Tp, int n> class Vec : public Matx<_Tp, n, 1> {...};
typedef Vec<uchar, 2> Vec2b;
typedef Vec<uchar, 3> Vec3b;
typedef Vec<uchar, 4> Vec4b;
typedef Vec<short, 2> Vec2s;
typedef Vec<short, 3> Vec3s;
typedef Vec<short, 4> Vec4s;
typedef Vec<int, 2> Vec2i;
typedef Vec<int, 3> Vec3i;
typedef Vec<int, 4> Vec4i;
typedef Vec<float, 2> Vec2f;
typedef Vec<float, 3> Vec3f;
typedef Vec<float, 4> Vec4f;
typedef Vec<float, 6> Vec6f;
typedef Vec<double, 2> Vec2d;
typedef Vec<double, 3> Vec3d;
typedef Vec<double, 4> Vec4d;
typedef Vec<double, 6> Vec6d;
因为Vec的特殊性质,Vec
以下是Vec的一些基本运算:1
2
3
4
5
6
7
8v1 = v2 + v3
v1 = v2 - v3
v1 = v2 * scale
v1 = scale * v2
v1 = -v2
v1 += v2 and other augmenting operations
v1 == v2, v1 != v2
norm(v1) (euclidean norm)
因为Scalar_是从Vec
Scalar_的定义如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28template<typename _Tp> class CV_EXPORTS Scalar_ : public Vec<_Tp, 4>
{
public:
//! various constructors
Scalar_();
Scalar_(_Tp v0, _Tp v1, _Tp v2=0, _Tp v3=0);
Scalar_(const CvScalar& s);
Scalar_(_Tp v0);
//! returns a scalar with all elements set to v0
static Scalar_<_Tp> all(_Tp v0);
//! conversion to the old-style CvScalar
operator CvScalar() const;
//! conversion to another data type
template<typename T2> operator Scalar_<T2>() const;
//! per-element product
Scalar_<_Tp> mul(const Scalar_<_Tp>& t, double scale=1 ) const;
// returns (v0, -v1, -v2, -v3)
Scalar_<_Tp> conj() const;
// returns true iff v1 == v2 == v3 == 0
bool isReal() const;
};
typedef Scalar_<double> Scalar;
八,Range
数据类型简介
该数据类型顾名思义表示的是一个范围,它的主要数据成员就是start和end,它和opencv1.x中的CvSlice相对应
,这个类的主要作用就相当于matlab矩阵中的:运算符,可以访问矩阵中的行或者列的范围。
类定义
1 | class CV_EXPORTS Range |
九,Ptr
数据类型简介
在opencv2.x介绍中,已经说明opencv具有自动内存管理的功能。其实现自动内存管理功能的最主要的方式就是通过Ptr这个指针类来实现的,它相当于c++中的shared_ptr,具有引用计数的功能,当没有任何变量引用一块内存区域时,Ptr就会自动释放这块内存区域。
类定义
1 | template<typename _Tp> class Ptr |
通过使用Ptr < T > obj = new T()来声明一个变量,就会由Ptr来自动管理内存分配和释放。
十,InputArray和OutputArray
数据类型简介
InputArray是用来在opencv函数中用来传递只读参数的代理类。typedef const _InputArray& InputArray;
,_InputArray是一个可以通过Mat,Mat__< T >,Matx
例:
函数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24void myAffineTransform(InputArray _src, OutputArray _dst, InputArray _m)
{
// get Mat headers for input arrays. This is O(1) operation,
// unless _src and/or _m are matrix expressions.
Mat src = _src.getMat(), m = _m.getMat();
CV_Assert( src.type() == CV_32FC2 && m.type() == CV_32F && m.size() == Size(3, 2) );
// [re]create the output array so that it has the proper size and type.
// In case of Mat it calls Mat::create, in case of STL vector it calls vector::resize.
_dst.create(src.size(), src.type());
Mat dst = _dst.getMat();
for( int i = 0; i < src.rows; i++ )
for( int j = 0; j < src.cols; j++ )
{
Point2f pt = src.at<Point2f>(i, j);
dst.at<Point2f>(i, j) = Point2f(m.at<float>(0, 0)*pt.x +
m.at<float>(0, 1)*pt.y +
m.at<float>(0, 2),
m.at<float>(1, 0)*pt.x +
m.at<float>(1, 1)*pt.y +
m.at<float>(1, 2));
}
}
当你使用这个函数时,可以将Mat,Mat__< T >,Matx
而OutputArray是从InputArray继承而来的。它的功能与InputArray类似。
这两个数据类型都有一个共同的限制就是:不要为这两个类显示的构造实例对象。简单来说,他们应该只出现在函数的形参声明中。