【opencv4.3.0教程】05之基础结构2之矩形结构Rect_详解

目录

一、前言

二、温故知新

1、基础结构都有啥

2、Point_

3、Size_

三、Rect_

1、定义

1.构造函数

2.基本操作

3.成员变量

4.使用时的数据类型

2、常用方法

1.定义中的方法

2.常用运算

3、代码实战


一、前言

上一篇文章,我们讲了OpenCV中的基础结构,还讲了两个最常用也是最基本的结构,今天这篇博客,我们来讲剩下两个常见的结构。

二、温故知新

1、基础结构都有啥

上一节课,我们讲到了基础结构,那我们都讲到哪些结构呢?跟我一起来回顾一下吧!

1.Complex:这个是复数类,跟我们数学上学到的复数是一样的。

2.Point_:表示的是二维点,包括两个坐标坐标值,也包括最常见的点的相关操作。

3.Point3_:表示三维点,包括三个坐标值:

4.Size_:表示图像或矩形大小。包括两个成员变量:width和height,表示图像或者矩阵的大小。

5.Rect_:这个用于描述二维矩形,主要有两个部分的参数:

(1)图像矩阵的左上角坐标。

(2)图像矩阵的宽度和高度。

6.RotatedRect:带有旋转角度的矩形。主要有三个部分的参数:

(1)矩形的中心坐标。

(2)矩形长宽。

(3)图像旋转角度。

7.Range:表示图像的连续子序列。

8.Scalar_:常用于定义像素值。

9.KeyPoint:用于角点检测。

10.DMatch:用于查询描述符索引、列车描述符索引、列车图像索引和描述符之间的距离。

11.TermCriteria:定义迭代算法终止条件的类。我们可以使用默认构造函数初始化它,然后重写任何参数,或者可以使用构造函数的高级变量完全初始化结构。

2、Point_

然后,我们又详细讲解了Point_类,讲了它的基本定义和常见用法。

Point_类有两个成员变量:

    _Tp x; //!< x coordinate of the point
    _Tp y; //!< y coordinate of the point

有多个构造函数:

    //! default constructor
    Point_();
    Point_(_Tp _x, _Tp _y);
    Point_(const Point_& pt);
    Point_(Point_&& pt) CV_NOEXCEPT;
    Point_(const Size_<_Tp>& sz);
    Point_(const Vec<_Tp, 2>& v);

还有很多常用操作,因为内容比较多,就不再在这里说明啦!大家可以打开上一篇博客去详细查看哦:

Point_类常用方法

3、Size_

然后,我们又详细讲解了Size_类,讲了它的基本定义和常见用法。

Size_类也有两个成员变量:

    _Tp width; //!< the width
    _Tp height; //!< the height

有多个构造函数:

    //! default constructor
    Size_();
    Size_(_Tp _width, _Tp _height);
    Size_(const Size_& sz);
    Size_(Size_&& sz) CV_NOEXCEPT;
    Size_(const Point_<_Tp>& pt);

还有很多常用操作,因为内容比较多,就不再在这里说明啦!大家可以打开上一篇博客去详细查看哦:

Size_类常用方法

接下来让我们进入一个新的结构。

三、Rect_

除了上面两个最基本的就是Rect_了,我们怎么理解Rect_呢?

一个明确位置且横平竖直的矩形。

比如下面这几个:

一般来说,我们构建这个矩形,可以通过如下方法:

1.一个定位点,矩形的长和宽;

2.两个定位点(要求分别为对角线);

这是我们最基本的理解方式,了解了这些,就让我们从定义出发,一步一步来了解它吧!

1、定义

跟上一次一样,我们先从定义入手,对它有个最基本的认识:

template<typename _Tp> class Rect_
{
public:
    typedef _Tp value_type;

    //! default constructor
    Rect_();
    Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height);
    Rect_(const Rect_& r);
    Rect_(Rect_&& r) CV_NOEXCEPT;
    Rect_(const Point_<_Tp>& org, const Size_<_Tp>& sz);
    Rect_(const Point_<_Tp>& pt1, const Point_<_Tp>& pt2);

    Rect_& operator = ( const Rect_& r );
    Rect_& operator = ( Rect_&& r ) CV_NOEXCEPT;
    //! 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;
    //! true if empty
    bool empty() const;

    //! conversion to another data type
    template<typename _Tp2> operator Rect_<_Tp2>() const;

    //! checks whether the rectangle contains the point
    bool contains(const Point_<_Tp>& pt) const;

    _Tp x; //!< x coordinate of the top-left corner
    _Tp y; //!< y coordinate of the top-left corner
    _Tp width; //!< width of the rectangle
    _Tp height; //!< height of the rectangle
};

typedef Rect_<int> Rect2i;
typedef Rect_<float> Rect2f;
typedef Rect_<double> Rect2d;
typedef Rect2i Rect;

template<typename _Tp> class DataType< Rect_<_Tp> >
{
public:
    typedef Rect_<_Tp>                               value_type;
    typedef Rect_<typename DataType<_Tp>::work_type> work_type;
    typedef _Tp                                      channel_type;

    enum { generic_type = 0,
           channels     = 4,
           fmt          = traits::SafeFmt<channel_type>::fmt + ((channels - 1) << 8)
#ifdef OPENCV_TRAITS_ENABLE_DEPRECATED
           ,depth        = DataType<channel_type>::depth
           ,type         = CV_MAKETYPE(depth, channels)
#endif
         };

    typedef Vec<channel_type, channels> vec_type;
};

namespace traits {
template<typename _Tp>
struct Depth< Rect_<_Tp> > { enum { value = Depth<_Tp>::value }; };
template<typename _Tp>
struct Type< Rect_<_Tp> > { enum { value = CV_MAKETYPE(Depth<_Tp>::value, 4) }; };
} // namespace

这里面最基本的定义主要包括如下三部分:

1.构造函数

几个构造函数,用于生成Rect对象:

    //! default constructor
    Rect_();
    Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height);
    Rect_(const Rect_& r);
    Rect_(Rect_&& r) CV_NOEXCEPT;
    Rect_(const Point_<_Tp>& org, const Size_<_Tp>& sz);
    Rect_(const Point_<_Tp>& pt1, const Point_<_Tp>& pt2);

 对于第一个构造函数,可以创建一个空的矩形,左上角顶点坐标为(0,0),矩形的长宽均为0。一般这种无参构造函数都是创建空的对象,值的初始化要么为空,要么为0。

我们上面说到,想要构造一个矩形,可以有两种方式:

第一种方式是使用一个点的坐标和长宽。

(1)对于这种方式,我们既可以给四个参数:横坐标、纵坐标、长、宽:

    Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height);

(2)也可以使用我们昨天提到的两个类型:Point_和Size_。

    Rect_(const Point_<_Tp>& org, const Size_<_Tp>& sz);

第二种方式是使用两个对角线顶点:

    Rect_(const Point_<_Tp>& pt1, const Point_<_Tp>& pt2);

除了上面的两种方法,我们还有一种方法就是使用另外的矩形为该矩形赋值:

    Rect_(const Rect_& r);
    Rect_(Rect_&& r) CV_NOEXCEPT;

 

2.基本操作

在定义中,还有如下基本操作:

    Rect_& operator = ( const Rect_& r );
    Rect_& operator = ( Rect_&& r ) CV_NOEXCEPT;
    //! 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;
    //! true if empty
    bool empty() const;

    //! conversion to another data type
    template<typename _Tp2> operator Rect_<_Tp2>() const;

    //! checks whether the rectangle contains the point
    bool contains(const Point_<_Tp>& pt) const;

我们分类说明一下,方便大家理解:

第一类,基本赋值操作

    Rect_& operator = ( const Rect_& r );
    Rect_& operator = ( Rect_&& r ) CV_NOEXCEPT;

这个跟上面讲到的使用别的矩形为矩形赋值的功能是一致的;

第二类,求顶点,获取矩形的左上角顶点和右下角顶点的坐标

    //! 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;
    //! true if empty
    bool empty() const;

第四类,转化为其他类型

    //! conversion to another data type
    template<typename _Tp2> operator Rect_<_Tp2>() const;

第五类,判断矩形是否包含某点,跟在点中的函数是一个含义

    //! checks whether the rectangle contains the point
    bool contains(const Point_<_Tp>& pt) const;

3.成员变量

四个类体成员变量,包括横纵坐标,还有矩形的长和宽:

    _Tp x; //!< x coordinate of the top-left corner
    _Tp y; //!< y coordinate of the top-left corner
    _Tp width; //!< width of the rectangle
    _Tp height; //!< height of the rectangle

4.使用时的数据类型

当我们定义了Rect_类之后,跟上面一样,我们要定义具体的使用过程中的类型:

typedef Point_<int> Point2i;
typedef Point_<int64> Point2l;
typedef Point_<float> Point2f;
typedef Point_<double> Point2d;
typedef Point2i Point;

 

2、常用方法

接下来我们要说的就是方法,这里有很多实现了上面的类定义时的方法,我们在上面也具体讲解了,在这里我们讲一下具体的实战。

1.定义中的方法

定义中的方法包括构造函数和几个常用方法,构造函数如下:

template<typename _Tp> inline
Rect_<_Tp>::Rect_()
    : x(0), y(0), width(0), height(0) {}

template<typename _Tp> inline
Rect_<_Tp>::Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height)
    : x(_x), y(_y), width(_width), height(_height) {}

template<typename _Tp> inline
Rect_<_Tp>::Rect_(const Rect_<_Tp>& r)
    : x(r.x), y(r.y), width(r.width), height(r.height) {}

template<typename _Tp> inline
Rect_<_Tp>::Rect_(Rect_<_Tp>&& r) CV_NOEXCEPT
    : x(std::move(r.x)), y(std::move(r.y)), width(std::move(r.width)), height(std::move(r.height)) {}

template<typename _Tp> inline
Rect_<_Tp>::Rect_(const Point_<_Tp>& org, const Size_<_Tp>& sz)
    : x(org.x), y(org.y), width(sz.width), height(sz.height) {}

template<typename _Tp> inline
Rect_<_Tp>::Rect_(const Point_<_Tp>& pt1, const Point_<_Tp>& pt2)
{
    x = std::min(pt1.x, pt2.x);
    y = std::min(pt1.y, pt2.y);
    width = std::max(pt1.x, pt2.x) - x;
    height = std::max(pt1.y, pt2.y) - y;
}

常用方法如下:

template<typename _Tp> inline
Point_<_Tp> Rect_<_Tp>::tl() const
{
    return Point_<_Tp>(x,y);
}

template<typename _Tp> inline
Point_<_Tp> Rect_<_Tp>::br() const
{
    return Point_<_Tp>(x + width, y + height);
}

template<typename _Tp> inline
Size_<_Tp> Rect_<_Tp>::size() const
{
    return Size_<_Tp>(width, height);
}

template<typename _Tp> inline
_Tp Rect_<_Tp>::area() const
{
    const _Tp result = width * height;
    CV_DbgAssert(!std::numeric_limits<_Tp>::is_integer
        || width == 0 || result / width == height); // make sure the result fits in the return value
    return result;
}

template<typename _Tp> inline
bool Rect_<_Tp>::empty() const
{
    return width <= 0 || height <= 0;
}

template<typename _Tp> template<typename _Tp2> inline
Rect_<_Tp>::operator Rect_<_Tp2>() const
{
    return Rect_<_Tp2>(saturate_cast<_Tp2>(x), saturate_cast<_Tp2>(y), saturate_cast<_Tp2>(width), saturate_cast<_Tp2>(height));
}

template<typename _Tp> inline
bool Rect_<_Tp>::contains(const Point_<_Tp>& pt) const
{
    return x <= pt.x && pt.x < x + width && y <= pt.y && pt.y < y + height;
}

我们使用构造函数创建几个矩形:

	Rect r1 = Rect();
	Rect r2 = Rect(1, 2, 3, 4);
	Rect r3 = Rect(Point(5, 5), Size(10, 10));
	Rect r4 = Rect(Point(5, 6), Point(10, 10));
	Rect r5 = Rect(r4);

然后我们调用常用方法,查看一下效果:

	cout << "r1 = " << r1 << endl;
	cout << "r2 = " << r2 << endl;
	cout << "r3 = " << r3 << endl;
	cout << "r4 = " << r4 << endl;
	cout << "r5 = " << r5 << endl;
	cout << "【r5 info】" << endl;
	cout << "r5.x = " << r5.x << endl;
	cout << "r5.y = " << r5.y << endl;
	cout << "r5.width = " << r5.width << endl;
	cout << "r5.height = " << r5.height << endl;
	cout << "r5.size = " << r5.size() << endl;
	cout << "r5.area = " << r5.area() << endl;
	cout << "r5.br = " << r5.br() << endl;
	cout << "r5.tl = " << r5.tl() << endl;

	if (r4 == r5) cout << "r4 = r5" << endl;
	else cout << "r4 != r5" << endl;
	if (r5.contains(Point())) cout << "Point" << Point() << " 在 Rect" << r5 << "中!" << endl;
	else cout << "Point" << Point() << " 不在 Rect" << r5 << "中!" << endl;

执行结果如下:

2.常用运算

常用运算包括赋值运算,四则运算等,具体如下:

1.让左上角定位点移位的加赋值与减赋值,及其相关运算:

template<typename _Tp> static inline
Rect_<_Tp>& operator += ( Rect_<_Tp>& a, const Point_<_Tp>& b )
{
    a.x += b.x;
    a.y += b.y;
    return a;
}

template<typename _Tp> static inline
Rect_<_Tp>& operator -= ( Rect_<_Tp>& a, const Point_<_Tp>& b )
{
    a.x -= b.x;
    a.y -= b.y;
    return a;
}

template<typename _Tp> static inline
Rect_<_Tp> operator + (const Rect_<_Tp>& a, const Point_<_Tp>& b)
{
    return Rect_<_Tp>( a.x + b.x, a.y + b.y, a.width, a.height );
}

template<typename _Tp> static inline
Rect_<_Tp> operator - (const Rect_<_Tp>& a, const Point_<_Tp>& b)
{
    return Rect_<_Tp>( a.x - b.x, a.y - b.y, a.width, a.height );
}

2.改变矩形尺寸的加赋值与减赋值,及其相关运算

template<typename _Tp> static inline
Rect_<_Tp>& operator += ( Rect_<_Tp>& a, const Size_<_Tp>& b )
{
    a.width += b.width;
    a.height += b.height;
    return a;
}

template<typename _Tp> static inline
Rect_<_Tp>& operator -= ( Rect_<_Tp>& a, const Size_<_Tp>& b )
{
    const _Tp width = a.width - b.width;
    const _Tp height = a.height - b.height;
    CV_DbgAssert(width >= 0 && height >= 0);
    a.width = width;
    a.height = height;
    return a;
}

template<typename _Tp> static inline
Rect_<_Tp> operator + (const Rect_<_Tp>& a, const Size_<_Tp>& b)
{
    return Rect_<_Tp>( a.x, a.y, a.width + b.width, a.height + b.height );
}

template<typename _Tp> static inline
Rect_<_Tp> operator - (const Rect_<_Tp>& a, const Size_<_Tp>& b)
{
    const _Tp width = a.width - b.width;
    const _Tp height = a.height - b.height;
    CV_DbgAssert(width >= 0 && height >= 0);
    return Rect_<_Tp>( a.x, a.y, width, height );
}

3.两个矩形的公共矩形,如果没有,就是空:

template<typename _Tp> static inline
Rect_<_Tp>& operator &= ( Rect_<_Tp>& a, const Rect_<_Tp>& b )
{
    _Tp x1 = std::max(a.x, b.x);
    _Tp y1 = std::max(a.y, b.y);
    a.width = std::min(a.x + a.width, b.x + b.width) - x1;
    a.height = std::min(a.y + a.height, b.y + b.height) - y1;
    a.x = x1;
    a.y = y1;
    if( a.width <= 0 || a.height <= 0 )
        a = Rect();
    return a;
}

template<typename _Tp> static inline
Rect_<_Tp> operator & (const Rect_<_Tp>& a, const Rect_<_Tp>& b)
{
    Rect_<_Tp> c = a;
    return c &= b;
}

4.两个矩形的最小包围矩形

template<typename _Tp> static inline
Rect_<_Tp>& operator |= ( Rect_<_Tp>& a, const Rect_<_Tp>& b )
{
    if (a.empty()) {
        a = b;
    }
    else if (!b.empty()) {
        _Tp x1 = std::min(a.x, b.x);
        _Tp y1 = std::min(a.y, b.y);
        a.width = std::max(a.x + a.width, b.x + b.width) - x1;
        a.height = std::max(a.y + a.height, b.y + b.height) - y1;
        a.x = x1;
        a.y = y1;
    }
    return a;
}

template<typename _Tp> static inline
Rect_<_Tp> operator | (const Rect_<_Tp>& a, const Rect_<_Tp>& b)
{
    Rect_<_Tp> c = a;
    return c |= b;
}

5.判断两个矩形是否相等

template<typename _Tp> static inline
bool operator == (const Rect_<_Tp>& a, const Rect_<_Tp>& b)
{
    return a.x == b.x && a.y == b.y && a.width == b.width && a.height == b.height;
}

template<typename _Tp> static inline
bool operator != (const Rect_<_Tp>& a, const Rect_<_Tp>& b)
{
    return a.x != b.x || a.y != b.y || a.width != b.width || a.height != b.height;
}

比较简单,我们就通过代码实战来巩固一下吧!

3、代码实战

接下来我们走进实战,为我们以后的使用打好基础吧。

	Rect rect1 = Rect(Point(5, 5), Point(15, 15));
	Rect rect2 = Rect(Point(7, 7), Point(20, 20));
	Point point1 = Point(3, 3);
	Size size1 = Size(4, 4);

	rect1 += point1;
	cout << "rect1 += point1 =  " << rect1 << endl;
	rect1 = rect1 - point1;
	cout << "rect1 - point1  =  " << rect1 << endl;

	rect2 += size1;
	cout << "rect2 += size1  =  " << rect2 << endl;
	rect2 = rect2 - size1;
	cout << "rect2 - size1   =  " << rect2 << endl;
	 
	cout << "rect1 & rect2   =  " << (rect1 & rect2) << endl;
	cout << "rect1 | rect2   =  " << (rect1 | rect2) << endl;

今天的内容就到这里啦,大家一定要多做练习呀!

原创文章 287 获赞 708 访问量 83万+

猜你喜欢

转载自blog.csdn.net/shuiyixin/article/details/106085233
今日推荐