绘图

来源:互联网 发布:软件企业评估 编辑:程序博客网 时间:2024/04/29 08:05

我们经常需要绘制图像或者在已有的图像上方绘制一些图形。为此,OpenCV提供了一系列的函数帮助我们绘制直线、方形和圆形等。

直线

cvLine()是绘图函数中最简单的,只需用Bresenham算法[Bresenham65]画一条线:


void  cvLine(  
  CvArr*    array,  
  CvPoint   pt1,  
  CvPoint   pt2,  
  CvScalar  color,  
  int       thickness    = 1,  
  int       connectivity = 8 
); 
cvLine()函数中的第一个属性是CvArr*。在这里,它一般为一个图像类型的指针IplImage*。随后两个CvPoint是一种简单的数据结构,它只包括整型变量x和y。我们可以用CvPoint(int x, int y)函数快速地构造一个CvPoint类型的变量,这样可以方便地把两个整型变量值赋给CvPoint数据结构。


下一个属性是CvScalar类型的颜色变量。CvScalar也是一种数据结构,定义如下所示:


typdef struct {  
  double val[4];  
} CvScalar; 
可以看出,这种结构只是四个双精度浮点型变量的集合。在这里,前三个分别代表红,绿,蓝通道;没有用到第四个(它只在适当的时候用于alpha通道)。一个常用的便捷宏指令是CV_RGB(r, g, b),该指令采用三个数字作为参数并将其封装到CvScalar。


接下来的两个属性是可选的。thickness是线的粗细(像素),connectivity被设为反走样模式,默认值为"8连通",这种是较为平滑不会走样的线型。也可以设置为"4连通",这样的话,斜线会产生重叠以致看上去过于粗重,不过画起来速度要快得多。


cvRectangle()和cvLine()几乎同样便捷。cvRectangle()用于画矩形。除了没有connectivity参数,它和cvLine()的其他参数都是一样的。因为由此产生的矩形总是平行与X和Y轴。利用cvRectangle(),我们只需给出两个对顶点,OpenCV便于画出一个矩形。

矩形
void  cvRectangle(  
  CvArr*    array,  
  CvPoint   pt1,  
  CvPoint   pt2,  
  CvScalar  color,  
  int       thickness = 1 
); 

圆形和椭圆

画圆同样简单,其参数与前相同。

  1. void  cvCircle (  
  2.   CvArr*    array,  
  3.   CvPoint   center,  
  4.   int       radius,  
  5.   CvScalar  color,  
  6.   int       thickness    = 1,  
  7.  
  8.  
  9.   int       connectivity = 8 
  10. ); 

对圆形和矩阵等很多封闭图形来说,thickness参数也可以设置为CV_FILL,其值是-1;其结果是使用与边一样的颜色填充圆内部。

椭圆函数比cvCircle()略微复杂一些:

  1. void cvEllipse(  
  2.   CvArr*    img,  
  3.   CvPoint   center,  
  4.   CvSize    axes,  
  5.   double    angle,  
  6.   double    start_angle,  
  7.   double    end_angle,  
  8.   CvScalar  color,  
  9.   int       thickness = 1,  
  10.   int       line_type = 8 
  11. ); 

【79】

这里,主要的新成员是axes属性,其类型为CvSize。CvSize函数与CvPoint和CvScalar非常相似;这是一个仅包含宽度和高度的简单结构。同CvPoint和CvScalar一样,CvSize也有一个简单的构造函数cvSize(int height, int width),在需要的时候返回一个CvSize数据。在这种情况下,height和width参数分别代表椭圆的长短半轴长。

angle是指偏离主轴的角度,从X轴算起,逆时针方向为正。同样,start_angle和end_angle表示弧线开始和结束位置的角度。因此,一个完整的椭圆必须分别将这两个值分别设为0°和360°。

外接矩形

使用外接矩形是描述椭圆绘制的另一种方法:

  1. void cvEllipseBox(  
  2.   CvArr*    img,  
  3.   CvBox2D   box,  
  4.   CvScalar  color,  
  5.   int       thickness = 1,  
  6.   int       line_type = 8,  
  7.   int       shift     = 0 
  8. ); 

这里用到OpenCV的另一个结构CvBox2D:

  1. typdef struct {  
  2.   CvPoint2D32f  center;  
  3.   CvSize2D32f   size;  
  4.   float         angle;  
  5. } CvBox2D; 

CvPoint2D32f是CvPoint的浮点形式,同时CvSizet2D32f也是CvSize的浮点形式。这些,连同倾斜角度,可以有效地描述椭圆的外接矩形


多边形

最后,我们有一系列绘制多边形的函数。

  1. void cvFillPoly(  
  2.   CvArr*        img,  
  3.   CvPoint**     pts,  
  4.   int*          npts,  
  5.   int           contours,  
  6.   CvScalar      color,  
  7.   int           line_type = 8 
  8. );  
  9.  
  10. void cvFillConvexPoly(  
  11.   CvArr*    img,  
  12.   CvPoint*  pts,  
  13.   int       npts,  
  14.   CvScalar  color,  
  15.   int       line_type = 8 
  16. );  
  17.  
  18. void cvPolyLine(  
  19.   CvArr*        img,  
  20.   CvPoint**     pts,  
  21.   int*          npts,  
  22.   int           contours,  
  23.   int           is_closed,  
  24.   CvScalar      color,  
  25.   int           thickness = 1,  
  26.  
  27.  
  28.   int           line_type = 8 
  29. ); 

【79~80】

上述三种方法依据同一思路又略有不同,其主要区别是如何描述点。

在cvFillPoly()中,点是由CvPoint数组提供的。它允许cvFillPoly()在一次调用中绘制多个多边形。同样地,npts是由记数点构成的数组,与多边形对应。如果把变量is_closed设为true,那么下一个多边形的第一个线段就会从上一多边形最后一点开始。cvFillPoly()很稳定,可以处理自相交多边形,有孔的多边形等复杂问题。然而不幸的是,函数运行起来相对缓慢。

cvFillConvexPoly()和cvFillPoly()类似。不同的是,它一次只能画一个多边形,而且只能画凸多边形 。好处是,cvFillConvexPoly()运行得更快。

第三个cvPolyLine(),其参数与cvFillPoly()相同,但因为只需画出多边形的边,不需处理相交情况。因此,这种函数运行速度远远超过cvFillPoly()。



原创粉丝点击