opencv学习(十一)之绘图函数

opencv中提供了很多绘图函数,在进行图像处理,对感兴趣区域进行标定时,就需要利用这些绘图函数。现在集中做一个归纳介绍。

1. Point
Point常用来指定一幅二维图像中的点。如

Point pt;
pt.x = 10;
pt.y = 8;
或
Point pt = Point(10,8);

其指向的是在图像中(10, 8)位置的一个像素点。
查找Point引用可以在”core.hpp”文件发现如下语句:

typedef Point_<int> Point2i;
typedef Point2i Point;

即Point_与Point2i和Point是等价的。查看Point_定义出现很多模板如下:

template<typename _Tp> inline Point_<_Tp>::Point_(_Tp _x, _Tp _y) : x(_x), y(_y) {}

其从Point_继承而来,继续查看Point_定义如下:

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)来指定二维图像中的点。

2. Scalar
表示颜色的类,Scalar代表了一个四元素的vector容器,在opencv中常用来传递像素值。在本篇博客中将主要用来表示BGR三个像素的值。如果不使用则最后一个参数不用设置。如

Scalar(a, b, c);

其中a,b,c分别代表像素点Blue,Green,Red的值。
同样查看Scalar类的引用在”core.hpp”头文件发现如下语句:

typedef Scalar_<double> Scalar;

查看Scalar_定义:

template<typename _Tp> class 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;
};

从定义语句Scalar_(_Tp v0, _Tp v1, _Tp v2=0, _Tp v3=0);中可以看出Scalar最后两个参数都有默认值,故在不适用第四个参数时可以直接忽略。

3. Size
表示尺寸的类,依旧查看其引用和定义如下:

typedef Size_<int> Size2i;
typedef Size_<double> Size2d;
typedef Size2i Size;

所以针对int类型的size参数,其可以直接使用Size类,而对于double类型的size参数,只能使用Size2d。查看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
};

里面有很多方法。在本篇博客中将使用Size_(_Tp _width, _Tp _height);直接指定size的宽和高。

4. line
绘制直线类。其定义如下:

CV_EXPORTS_W void line(CV_IN_OUT Mat& img, Point pt1, Point pt2, const Scalar& color,
                     int thickness=1, int lineType=8, int shift=0);

参数解释
.Mat& img: 输入输出图像
.Point pt1和pt2: 二维Point类的点坐标,由Point指定
.Scalar& color: 直线颜色
. int thickness = 1: 直线宽度,有默认值1
. int lineType = 8: 直线类型,默认值为8

5. ellips
绘制椭圆。其定义如下:

CV_EXPORTS_W void ellipse(CV_IN_OUT Mat& img, Point center, Size axes,
                        double angle, double startAngle, double endAngle,
                        const Scalar& color, int thickness=1,
                        int lineType=8, int shift=0);

参数解释
. Mat& img: 输入输出图像
. Point center: 由Point类指定的椭圆中心坐标
. Size axes: 由Size类指定的椭圆所在区域矩形
. double angle: 椭圆长轴偏离角度
. double startAngle: 绘制椭圆起始角度
. double endAngle: 绘制椭圆终点角度。如果设置startAngle为0,设置endAngle为360则表示整个椭圆
. const Scalar& color: 椭圆颜色
. int thickness = 1: 椭圆边的线宽
. int lineType = : 椭圆变线的类型

6. rectangle
绘制矩形,其定义如下:

CV_EXPORTS_W void rectangle(CV_IN_OUT Mat& img, Point pt1, Point pt2,
                          const Scalar& color, int thickness=1,
                          int lineType=8, int shift=0);

//! draws the rectangle outline or a solid rectangle covering rec in the image
CV_EXPORTS void rectangle(CV_IN_OUT Mat& img, Rect rec,
                          const Scalar& color, int thickness=1,
                          int lineType=8, int shift=0);

可以看出其有两种参数传入方式。一类是用Point指定点,另一类是用Rect函数指定边长。
. 针对第一类指定方式,Point类指定的两个点分别为矩形的左上角点坐标和矩形左下角点坐标
. Rect指定边长,查看其定义有如下语句

typedef Rect_<int> Rect;

说明Rect是int类型的数据结构,与Rect_等价。查看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
};

常用 Rect_(Tp _x, _Tp _y, _Tp _width, _Tp _height);来定义一个矩形;也可以使用函数Rect(const Point_<Tp>& pt1, const Point<_Tp>& pt2);指定矩形左上角的点和右下角的点。

7. circle
绘制圆。查看其定义

CV_EXPORTS_W void circle(CV_IN_OUT Mat& img, Point center, int radius,
                       const Scalar& color, int thickness=1,
                       int lineType=8, int shift=0);

参数解释
. Mat& img: 输入输出图像
. Point center: Point指定的一个二维点作为圆心
. int radius: 圆的半径
. const Scalar& color: Scalar指定的绘制圆的颜色
. int thickness = 1: 圆边的线宽
. int lineType = 8: 圆边线的类型

8. filled polygon
填充多边形。其定义有两种形式

CV_EXPORTS void fillPoly(Mat& img, const Point** pts,
                         const int* npts, int ncontours,
                         const Scalar& color, int lineType=8, int shift=0,
                         Point offset=Point() );

CV_EXPORTS_W void fillPoly(InputOutputArray img, InputArrayOfArrays pts,
                           const Scalar& color, int lineType=8, int shift=0,
                           Point offset=Point() );

. 第一种形式定义,有Point** pts,是一个二阶指针,用来指定多边形顶点。多边形顶点不是某个特定点,而是多个点,所以用Point类定义的数组来表示顶点坐标,如下

Point points[1][10];        //定义一个Point类数组,大小为一行十列
points[0][0] = Point(w / 4.0, 7 * w / 8.0);
points[0][1] = Point(w / 4.0,  w / 8.0);
...
const Point* ppt[1] = { points[0] };    //points[0]为第一行元素指针
/*此时定义一个Point* 类型的指针用来存放point[0]的指针,而ppt就是二阶指针*/

const int* npts是说明多边形顶点个数,与上述顶点个数保持一致。如

int npt[] = { 10 };

之后调用函数进行图形绘制

.第二种形式定义同样给出输入点数组。

综合示例:
结合上面的函数介绍,给出一个综合的示例程序

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>

using namespace std;
using namespace cv;

void MyEllipse(Mat img, double angle);
void MyFilledCircle(Mat img, Point center);
void MyLine(Mat img, Point start, Point end);
void MyPolygon(Mat img);

const int w = 400;

int main()
{
    char atom_window[] = "Drawing 1: Atom";
    char rook_window[] = "Drawing 2: Rook";

    //创建两个空的图像
    Mat atom_image = Mat::zeros(w, w, CV_8UC3);
    Mat rook_image = Mat::zeros(w, w, CV_8UC3);

    //使用ellipse和circle函数绘制一个简单的原子结构
    MyEllipse(atom_image,90);
    MyEllipse(atom_image,0);
    MyEllipse(atom_image,45);
    MyEllipse(atom_image,-45);

    MyFilledCircle(atom_image,Point(w/2.0, w/2.0));

    namedWindow(atom_window,WINDOW_AUTOSIZE);
    imshow(atom_window,atom_image);

    //使用line,rectangle,polygon(多边形)绘制一个rook
    MyPolygon(rook_image);

    //创建一个矩形
    rectangle(rook_image,Point(0, 7*w/8.0),Point(w,w),Scalar(0,255,255),-1, 8);

    //创建直线
    MyLine(rook_image,Point(0,15*w/16),Point(w, 15*w/16));
    MyLine(rook_image,Point(w/4, 7*w/8),Point(w/4,w));
    MyLine(rook_image,Point(w/2, 7*w/8),Point(w/2,w));
    MyLine(rook_image,Point(3*w/4, 7*w/8), Point(3*w/4,w));

    //显示绘制的图像
    namedWindow(rook_window,WINDOW_AUTOSIZE);
    imshow(rook_window,rook_image);

    waitKey(0);

    return 0;
}

void MyEllipse(Mat img, double angle)
{
    int thickness = 2;      //线宽
    int lineType = 8;       //线的类型
    ellipse(img,Point(w/2.0, w/2.0),Size(w/4.0, w/16.0),angle,0,360,Scalar(255,0,0),thickness,lineType);
}

void MyFilledCircle(Mat img, Point center)
{
    int thickness = -1;
    int lineType = 8;

    circle(img,center,w/32.0,Scalar(0,0,255),thickness,lineType);
}

void MyLine(Mat img, Point start, Point end)
{
    int thickness = 2;
    int lineType = 8;
    line(img, start, end, Scalar(0,0,0),thickness,lineType);
}

void MyPolygon(Mat img)
{
    int lineType = 8;

    //生成一些点
    Point rook_points[1][20];
    rook_points[0][0] = Point(w/4.0, 7*w/8.0);
    rook_points[0][1] = Point(3*w/4.0, 7*w/8.0);
    rook_points[0][2] = Point(3*w/4.0, 13*w/16.0);
    rook_points[0][3] = Point(11*w/16.0, 13*w/16.0);
    rook_points[0][4] = Point(19*w/32.0, 3*w/8.0);
    rook_points[0][5] = Point(3*w/4.0, 3*w/8.0);
    rook_points[0][6] = Point(3*w/4.0, w/8.0);
    rook_points[0][7] = Point(26*w/40.0, w/8.0);
    rook_points[0][8] = Point(26*w/40.0, w/4.0);
    rook_points[0][9] = Point(22*w/40.0, w/4.0);
    rook_points[0][10] = Point(22*w/40.0, w/8.0);
    rook_points[0][11] = Point(18*w/40.0, w/8.0);
    rook_points[0][12] = Point(18*w/40.0, w/4.0);
    rook_points[0][13] = Point(14*w/40.0, w/4.0);
    rook_points[0][14] = Point(14*w/40.0, w/8.0);
    rook_points[0][15] = Point(w/4.0, w/8.0);
    rook_points[0][16] = Point(w/4.0, 3*w/8.0);
    rook_points[0][17] = Point(13*w/32.0, 3*w/8.0);
    rook_points[0][18] = Point(5*w/16.0, 13*w/16.0);
    rook_points[0][19] = Point(w/4.0, 13*w/16.0);

    const Point* ppt[1] = {rook_points[0]};
    int npt[] = {20};

    fillPoly(img,ppt,npt,1,Scalar(255,255,255),lineType);
}

运行结果如图所示:
这里写图片描述

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值