【OpenCV學習】之基本繪圖

目的

本節你將學到:

  • 如何用 Point 在圖像中定義 2D 點
  • 如何以及爲何使用 Scalar
  • 用OpenCV的函數 line 繪 直線
  • 用OpenCV的函數 ellipse 繪 橢圓
  • 用OpenCV的函數 rectangle 繪 矩形
  • 用OpenCV的函數 circle 繪
  • 用OpenCV的函數 fillPoly 繪 填充的多邊形

OpenCV 原理

本節中,我門將大量使用 Point 和 Scalar 這兩個結構:

Point

次數據結構表示了由其圖像座標 x 和 y 指定的2D點。可定義爲:

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

或者

Point pt =  Point(10, 8);

Scalar

  • 表示了具有4個元素的數組。次類型在OpenCV中被大量用於傳遞像素值。

  • 本節中,我們將進一步用它來表示RGB顏色值(三個參數)。如果用不到第四個參數,則無需定義。

  • 我們來看個例子,如果給出以下顏色參數表達式:

    Scalar( a, b, c )

    那麼定義的RGB顏色值爲: Red = cGreen = b and Blue = a

代碼分析

  1. 我們打算畫兩個例子(原子和賭棍), 所以必須創建兩個圖像和對應的窗口以顯示。

    /// 窗口名字
    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 );

    創建用來畫不同幾何形狀的函數。比如用 MyEllipse 和 MyFilledCircle 來畫原子。

  2. /// 1. 畫一個簡單的原子。
    
    /// 1.a. 創建橢圓
    MyEllipse( atom_image, 90 );
    MyEllipse( atom_image, 0 );
    MyEllipse( atom_image, 45 );
    MyEllipse( atom_image, -45 );
    
    /// 1.b. 創建圓
    MyFilledCircle( atom_image, Point( w/2.0, w/2.0) );

    接下來用 MyLine*,*rectangle 和 a MyPolygon 來畫賭棍:

  3. /// 2. 畫一個賭棍
    
    /// 2.a. 創建一個凸多邊形
    MyPolygon( rook_image );
    
    /// 2.b. 創建矩形
    rectangle( rook_image,
               Point( 0, 7*w/8.0 ),
               Point( w, w),
               Scalar( 0, 255, 255 ),
               -1,
               8 );
    
    /// 2.c. 畫幾條直線
    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 ) );

    現在來看看每個函數內部如何定義:

  • 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) 來定義,在此其相應RGB值爲 黑色

線的粗細由 thickness 設定(此處設爲 2)

此線爲8聯通 (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, 255, 0) ,既藍色

    • 繪橢圓的線粗爲 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;

  /** 創建一些點 */
  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 );
 }
 我們用函數 :fill_poly:`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:rectangle <> (我們並沒有爲這傢伙創建特定函數)。請注意:

  • 矩形將被畫到圖像 rook_image 上
  • 矩形兩個對角頂點爲 Point( 0, 7*w/8.0 ) 和 Point( w, w)
  • 矩形的顏色爲 Scalar(0, 255, 255) ,既BGR格式下的 黃色
  • 由於線粗爲 -1, 此矩形將被填充

結果

編譯並運行例程,你將看到如下結果:

                                   Drawing Tutorial 1 - Final Result

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章