目的
本節你將學到:
- 如何用 Point 在圖像中定義 2D 點
- 如何以及爲何使用 Scalar
- 用OpenCV的函數 line 繪 直線
- 用OpenCV的函數 ellipse 繪 橢圓
- 用OpenCV的函數 rectangle 繪 矩形
- 用OpenCV的函數 circle 繪 圓
- 用OpenCV的函數 fillPoly 繪 填充的多邊形
OpenCV 原理
本節中,我門將大量使用 Point 和 Scalar 這兩個結構:
Point
次數據結構表示了由其圖像座標 和 指定的2D點。可定義爲:
Point pt;
pt.x = 10;
pt.y = 8;
或者
Point pt = Point(10, 8);
Scalar
-
表示了具有4個元素的數組。次類型在OpenCV中被大量用於傳遞像素值。
-
本節中,我們將進一步用它來表示RGB顏色值(三個參數)。如果用不到第四個參數,則無需定義。
-
我們來看個例子,如果給出以下顏色參數表達式:
Scalar( a, b, c )
那麼定義的RGB顏色值爲: Red = c, Green = b and Blue = a
代碼分析
-
我們打算畫兩個例子(原子和賭棍), 所以必須創建兩個圖像和對應的窗口以顯示。
/// 窗口名字 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 來畫原子。
-
/// 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 來畫賭棍:
-
/// 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, 此矩形將被填充
結果
編譯並運行例程,你將看到如下結果: