上面两篇文章中,简单的介绍了OpenCV的一些使用方法。以使我们更快的了解OpenCV。而下面我们将更多的去探讨OpenCV内部的细节。为了方便我们使用,OpenCV为我们定义了许多数据类模板。了解这些基本的数据结构,将是我们更好使用OpenCV的基础。其中常见的如下所示:
Point_
OpenCV分别为我们定义了2维点坐标和3维点坐标的类模板Point_和Point3_。类定义如下:
template<typename _Tp> class Point_
{
public:
typedef _Tp value_type;
// various constructors
Point_();
Point_(_Tp _x, _Tp _y);
Point_(const Point_& pt);
Point_(const CvPoint& pt);
Point_(const CvPoint2D32f& pt);
Point_(const Size_<_Tp>& sz);
Point_(const Vec<_Tp, 2>& v);
Point_& operator = (const Point_& pt);
//! conversion to another data type
template<typename _Tp2> operator Point_<_Tp2>() const;
//! conversion to the old-style C structures
operator CvPoint() const;
operator CvPoint2D32f() const;
operator Vec<_Tp, 2>() const;
//! dot product
_Tp dot(const Point_& pt) const;
//! dot product computed in double-precision arithmetics
double ddot(const Point_& pt) const;
//! cross-product
double cross(const Point_& pt) const;
//! checks whether the point is inside the specified rectangle
bool inside(const Rect_<_Tp>& r) const;
_Tp x, y; //< the point coordinates
};
从上面的代码我们不难看出Point_类封装了对应数据类型的x,和y坐标值。并且提供了大量的构造函数,以及和C语言结构中的CvPoint等的结构转换。并提供了两个点的点积和向量积运算,以及一个判断点是否在一个矩形内的方法。
除了上面所提供的类成员方法,下列关于点的操作也是可以使用的。
pt1 = pt2 + pt3;
pt1 = pt2 - pt3;
pt1 = pt2 * a;
pt1 = a * pt2;
pt1 += pt2;
pt1 -= pt2;
pt1 *= a;
double value = norm(pt);
pt1 == pt2;
pt1 != pt2
同时,为了方便我们的使用,OpenCV为我们定义了许多别名。如下所示:
typedef Point_<int> Point2i;
typedef Point2i Point;
typedef Point_<float> Point2f;
typedef Point_<double> Point2d;
Point3_和Point2_类似,只是封装了x,y,z坐标。在此不再赘述。
Size_
还有一个简单的类模板Size_,这个类模板为我们指定了矩阵或者图像的大小。类定义如下:
template<typename _Tp> class Size_
{
public:
typedef _Tp value_type;
//! various constructors
Size_();
Size_(_Tp _width, _Tp _height);
Size_(const Size_& sz);
Size_(const CvSize& sz);
Size_(const CvSize2D32f& sz);
Size_(const Point_<_Tp>& pt);
Size_& operator = (const Size_& sz);
//! the area (width*height)
_Tp area() const;
//! conversion of another data type.
template<typename _Tp2> operator Size_<_Tp2>() const;
//! conversion to the old-style OpenCV types
operator CvSize() const;
operator CvSize2D32f() const;
_Tp width, height; // the width and the height
};
可以看到这个类封装了一个叫做宽度和高度的变量。同时提供了计算面积的成员方法。其他的和Point_类类似。没什么特别的。
Rect_
接下来我们看一下OpenCV提供的一个矩形类模板Rect_,类模板定义如下:
template<typename _Tp> class Rect_
{
public:
typedef _Tp value_type;
//! various constructors
Rect_();
Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height);
Rect_(const Rect_& r);
Rect_(const CvRect& r);
Rect_(const Point_<_Tp>& org, const Size_<_Tp>& sz);
Rect_(const Point_<_Tp>& pt1, const Point_<_Tp>& pt2);
Rect_& operator = ( const Rect_& r );
//! the top-left corner
Point_<_Tp> tl() const;
//! the bottom-right corner
Point_<_Tp> br() const;
//! size (width, height) of the rectangle
Size_<_Tp> size() const;
//! area (width*height) of the rectangle
_Tp area() const;
//! conversion to another data type
template<typename _Tp2> operator Rect_<_Tp2>() const;
//! conversion to the old-style CvRect
operator CvRect() const;
//! checks whether the rectangle contains the point
bool contains(const Point_<_Tp>& pt) const;
_Tp x, y, width, height; //< the top-left corner, as well as width and height of the rectangle
};
很简单,这个类指示封装了矩阵的左上角坐标,以及矩形的宽度和高度。其中宽度和高度即为矩阵的大小(Size_),同时也可用于计算面积(area())。另外我们在通过contains函数来计算一个点是否包含在矩阵中时,需要注意的是矩阵的顶部和左边的边界被包含,而不包含右边和底部的边界。
综合实例
下面看一个简单的例子:
#include <cv.h>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
Point2f p1(1.0, 2.0);
Point_<float> p2(3.0, 4.0);
float dotproduct;
double crossproduct;
dotproduct = p2.dot(p1);
crossproduct = p1.cross(p2);
cout << "dot product of p1 and p2 = " << dotproduct << endl;
cout << "cross product of p1 and p2 = " << crossproduct << endl;
p2 += p1;
cout << "Now p2 = " << p2 << endl;
Rect_<float> rect(1.0, 2.0, 3.0, 4.0);
Size_<float> size;
float area;
size = rect.size();
area = rect.area();
cout << "rectangle's size is " << size << endl;
cout << "rectangle's area is " << area << endl;
cout << "rect contains p1 is " << rect.contains(p1) << endl;
cout << "rect contains p2 is " << rect.contains(p2) << endl;
return 0;
}
运行结果
i
注:对于这些类型,我们都可以用<<操作符进行输出。其默认输出格式不再赘述。