Basic Drawing

此为OpenCV官方教程的个人翻译

目标

在本篇文章中,您将学习如何:

  • 使用Point定义图像中的 2D 点。
  • 使用Scalar及其作用
  • 使用 OpenCV 函数line绘制一条线
  • 使用 OpenCV 函数ellipse绘制椭圆
  • 使用 OpenCV 函数rectangle绘制矩形
  • 使用 OpenCV 函数circle绘制
  • 使用 OpenCV 函数 fillPoly 绘制一个被填充的多边形

OpenCV 相关理论

在这个教程中,我们将经常使用两个结构:Point and Scalar:

Point

Point代表一个2D点,由图像中的x和y左边定义,我们可以这样定义它:

Point pt;
pt.x = 10;
pt.y = 8;

或者

Point pt = Point(10, 8);

Scalar

  • Scalar表示 4 元素向量。Scalar类型在 OpenCV 中广泛用于传递像素值。

  • 在本教程中,我们将广泛使用它来表示BGR颜色值(3个参数)。如果最后一个参数不打算使用,则无需定义该参数。

  • 让我们看一个例子,如果我们被要求一个颜色参数,我们给出:

    Scalar( a, b, c )
    

    我们就定义了一个BGR颜色,例如:蓝色= a绿色= b红色= c

代码

  • 下面的代码位于 OpenCV 示例文件夹中。或者,您可以从这里获取它

解释

  1. 计划绘制两个示例(一个原子和一个车),因此我们必须创建02个图像和两个窗口来显示它们。

    /// Windows names
    char atom_window[] = "Drawing 1: Atom";
    char rook_window[] = "Drawing 2: Rook";
    
    /// Create black empty images
    Mat atom_image = Mat::zeros( w, w, CV_8UC3 );		// w为宽度
    Mat rook_image = Mat::zeros( w, w, CV_8UC3 );
    
  2. 我们创建了绘制不同几何形状的函数。例如,为了绘制原子,我们使用MyEllipseMyFilledCircle

    /// 1. Draw a simple atom:
    
    /// 1.a. Creating ellipses
    MyEllipse( atom_image, 90 );
    MyEllipse( atom_image, 0 );
    MyEllipse( atom_image, 45 );
    MyEllipse( atom_image, -45 );
    
    /// 1.b. Creating circles
    MyFilledCircle( atom_image, Point( w/2.0, w/2.0) );
    
  3. 为了绘制车,我们使用了MyLinerectangleMyPolygon

    /// 2. Draw a rook
    
    /// 2.a. Create a convex polygon
    MyPolygon( rook_image );
    
    /// 2.b. Creating rectangles
    rectangle( rook_image,
               Point( 0, 7*w/8.0 ),
               Point( w, w),
               Scalar( 0, 255, 255 ),
               -1,
               8 );
    
    /// 2.c. Create a few lines
    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 ) );
    
  4. 让我们看看这些函数的具体内容:

    • MyLine

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

      正如我们所看到的,MyLine只调用函数line,它执行以下操作:

      • 绘制一条从点start到点end线
      • 该行显示在图像img
      • 线条颜色由Scalar(0, 0, 0)定义,该Scalar是对应于黑色的 BGR 值
      • 线条粗细设置为thickness(在本例中为 2)
      • 该line是由8个点连接成的line(lineType = 8)
    • MyEllipse

      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 );
      }
      

      从上面的代码中,我们可以观察到函数ellipse绘制了一个椭圆,使得:

      • 椭圆显示在图像 img
      • 椭圆中心位于点 (w/2.0, w/2.0) 中,并限制在大小为 (w/4.0, w/16.0) 的框中
      • 椭圆被旋转了angle
      • 椭圆在 0 到 360 度之间延伸一条弧
      • 图形的颜色将是Scalar(255,0,0),这意味着BGR值中的蓝色。
      • 椭圆的thickness为 2。
    • MyFilledCircle

      void MyFilledCircle( Mat img, Point center )
      {
       int thickness = -1;
       int lineType = 8;
      
       circle( img,
               center,
               w/32.0,
               Scalar( 0, 0, 255 ),
               thickness,
               lineType );
      }
      

      与椭圆函数类似,我们可以看到circle的参数:

      • 将显示圆圈的图像(img)
      • 表示为点中心的圆center
      • 圆的半径:w/32.0
      • 圆圈的颜色:Scalar(0,0,255),表示BGR中的红色
      • 由于thickness = -1,因此将绘制填充圆。
    • MyPolygon

      void MyPolygon( Mat img )
      {
        int lineType = 8;
      
        /** Create some points */
        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 );
       }
      

      要绘制填充多边形,我们使用函数 fillPoly。我们注意到:

      • 多边形将在 img 上绘制
      • 多边形的顶点是ppt中的点集
      • 要绘制的顶点总数为 npt
      • 要绘制的多边形数仅为 1
      • 多边形的颜色由Scalar( 255, 255, 255)定义,这是白色的 BGR 值
    • rectangle

      rectangle( rook_image,
                 Point( 0, 7*w/8.0 ),
                 Point( w, w),
                 Scalar( 0, 255, 255 ),
                 -1,
                 8 );
      

      最后,我们有rectangle函数(我们没有为这个家伙创建一个特殊的函数)。我们注意到:

      • 矩形将绘制在rook_image
      • 矩形的两个相反顶点由Point( 0, 7*w/8.0Point( w, w) 定义
      • 矩形的颜色由Scalar(0, 255, 255)给出,这是黄色的BGR值
      • 由于厚度值由 -1 给出,因此将填充矩形。

结果

1.png

posted @ 2022-06-27 10:09  帝皇の惊  阅读(42)  评论(0)    收藏  举报