文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏

目的

在这个教程中我们将学到:

  • 使用 Point 来定义图像中的二维点
  • 使用 Scalar 并且了解它为什么有用
  • 使用 OpenCV 的 line 函数来绘制线
  • 使用 OpenCV 的 ellipse 函数来绘制椭圆
  • 使用 OpenCV 的 rectangle 函数来绘制矩形
  • 使用 OpenCV 的 circle 函数来绘制圆
  • 使用 OpenCV 的 fillPoly 函数来绘制并填充多边形

OpenCV 理论

在这个教程中,我们重度使用了两个结构:PointScalar:

Point

表示一个 2D 点,专门针对图像的坐标

定义方法:

第 1 段(可获 2 积分)
Point pt;
pt.x = 10;
pt.y = 8;

或者

Point pt =  Point(10, 8);

Scalar

  • 表示一个4维向量。Scalar 类型在 OpenCV 中广泛用于传递传递像素值。
  • 在这个教程里,我们将扩展它来表示 BGR 颜色值(3 个参数)。如果最后一个参数没有使用的话,就必要定义了。
  • 在看一个例子,如果我们想要得到一个颜色参数,则会给出:
    Scalar( a, b, c )

    这里定义 BGR 颜色为:Blue = aGreen = bRed = c。

 代码

  • 这部分代码在你的 OpenCV sample 文件夹里。其他的你可以在这里找到。
第 2 段(可获 2 积分)

解释

  1. 由于我们打算演示两个示例(原子和车),我们需要创建两个图像以及两个窗口来显示他们。

  2. /// 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 );
    Mat rook_image = Mat::zeros( w, w, CV_8UC3 );
    
  3. 我们创建两个函数来画出不同的几何形状。例如,为了画出原子我们使用MyEllipse 和MyFilledCircle:

    /// 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) );
    
  4. 使用 MyLine, rectangle 以及 MyPolygon画出车:

    /// 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 ) );
    
  5. 让我们看看在每个函数里面都写了什么:

    • 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 函数,进行如下操作:

      • 从开始点到结束点画一条直线
      • 直线在 img图像中显示
      • 直线颜色用 Scalar( 0, 0, 0) 表示,显像出来为黑色
      • 线的宽度设置为 thickness (此时为 2)
      • 线为八邻域连通 (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) 表现为蓝色.
      • 椭圆宽度为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) 红色
      • 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) 白色
    • 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.0 )** 和Point( w, w)
      • 颜色为 (0, 255, 255) 黄色
      • 由于宽度设置为-1,因此矩形将被填充

结果

编译并运行程序你会得到如下结果:

Drawing Tutorial 1 - Final Result

第 3 段(可获 2 积分)

文章评论