OpenCV_Tutorials——CORE MODULE.THE CORE FUNCTIONALITY—— Basic Drawing
2.6基础绘画
目标
在这里我们会学习:
1、在图像中使用Point 来定义2D点
2、使用Scalar以及为什么要使用它
3、使用OpenCV函数line来绘制一条直线
4、使用OpenCV函数ellipse来绘制一个椭圆
5、使用OpenCV函数rectangle来绘制一个矩形
6、使用OpenCV函数circle来绘制一个圆
7、使用OpenCV函数fillPoly来填充一个任意图形
OpenCV理论知识
在这个教程中,我们着重使用两种数据结构:Point和Scalar:
Point
它代表2D点,使用x和y指定他的图像中的坐标。我们可以使用如下来定义:
Point 平台;
pt.x=10;
pt.y=8;
或者
Point pt=Point(10,8);
Scalar
1、代表一个4个元素的向量。Scalar类型在OpenCV中被广泛适用于传递像素值。
2、在教程中,我们使用广泛的使用它来表示RGB色彩值(3个参数)。如果最后一个元素不会被使用,那就没有必要去定义它。
3、让我们来看一个例子,如果我们想要一个色彩参数,我们会给:
Scalar(a,b,c)
我们定义一个RGB颜色,例如:Red=c,Green=b,Blue=a
代码
/**
* @file Drawing_1.cpp
* @brief Simple sample code
*/
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#define w 400
using namespace cv;
/// Function headers
void MyEllipse( Mat img, double angle );
void MyFilledCircle( Mat img, Point center );
void MyPolygon( Mat img );
void MyLine( Mat img, Point start, Point end );
/**
* @function main
* @brief Main function
*/
int main( void ){
/// 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 );
/// 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, w/2) );
/// 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 ),
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 ) );
/// 3. Display your stuff!
imshow( atom_window, atom_image );
moveWindow( atom_window, 0, 200 );
imshow( rook_window, rook_image );
moveWindow( rook_window, w, 200 );
waitKey( 0 );
return(0);
}
/// Function Declaration
/**
* @function MyEllipse
* @brief Draw a fixed-size ellipse with different angles
*/
void MyEllipse( Mat img, double angle )
{
int thickness = 2;
int lineType = 8;
ellipse( img,
Point( w/2, w/2 ),
Size( w/4, w/16 ),
angle,
0,
360,
Scalar( 255, 0, 0 ),
thickness,
lineType );
}
/**
* @function MyFilledCircle
* @brief Draw a fixed-size filled circle
*/
void MyFilledCircle( Mat img, Point center )
{
int thickness = -1;
int lineType = 8;
circle( img,
center,
w/32,
Scalar( 0, 0, 255 ),
thickness,
lineType );
}
/**
* @function MyPolygon
* @function Draw a simple concave polygon (rook)
*/
void MyPolygon( Mat img )
{
int lineType = 8;
/** Create some points */
Point rook_points[1][20];
rook_points[0][0] = Point( w/4, 7*w/8 );
rook_points[0][1] = Point( 3*w/4, 7*w/8 );
rook_points[0][2] = Point( 3*w/4, 13*w/16 );
rook_points[0][3] = Point( 11*w/16, 13*w/16 );
rook_points[0][4] = Point( 19*w/32, 3*w/8 );
rook_points[0][5] = Point( 3*w/4, 3*w/8 );
rook_points[0][6] = Point( 3*w/4, w/8 );
rook_points[0][7] = Point( 26*w/40, w/8 );
rook_points[0][8] = Point( 26*w/40, w/4 );
rook_points[0][9] = Point( 22*w/40, w/4 );
rook_points[0][10] = Point( 22*w/40, w/8 );
rook_points[0][11] = Point( 18*w/40, w/8 );
rook_points[0][12] = Point( 18*w/40, w/4 );
rook_points[0][13] = Point( 14*w/40, w/4 );
rook_points[0][14] = Point( 14*w/40, w/8 );
rook_points[0][15] = Point( w/4, w/8 );
rook_points[0][16] = Point( w/4, 3*w/8 );
rook_points[0][17] = Point( 13*w/32, 3*w/8 );
rook_points[0][18] = Point( 5*w/16, 13*w/16 );
rook_points[0][19] = Point( w/4, 13*w/16 );
const Point* ppt[1] = { rook_points[0] };
int npt[] = { 20 };
fillPoly( img,
ppt,
npt,
1,
Scalar( 255, 255, 255 ),
lineType );
}
/**
* @function MyLine
* @brief Draw a simple line
*/
void MyLine( Mat img, Point start, Point end )
{
int thickness = 2;
int lineType = 8;
line( img,
start,
end,
Scalar( 0, 0, 0 ),
thickness,
lineType );
}
解释
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);
2、我们创建函数来画不同的几何形状。例如,画原子我们需要使用MyEllipse和MyFilledCircle:
MyEllipse(atom_image,90);
MyEllipse(atom_image,0);
MyEllipse(atom_image,45);
MyEllipse(atom_image,-45);
MyFilledCircle(atom_image,Point(w/2.0,w/2.0);
3、画棋子,我们需要使用MyLine,rectangle以及MyPolygon函数
MyPolygon(rook_image);
Rectangle(rook_image,Point(0,7*w/8.0),Point(w,w),Scalar(0,255,255),-1,8);
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.star.end,Scalar(0,0,0),thickness,lineType);
}
就像我们看到的,MyLine仅仅调用了line函数,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)在RGB颜色系统中是蓝色
-椭圆线的粗细为thickness,也就是2
MyFillCircle
void MyFilledCircle(Mat img,Point center)
{
int thickness=-1;
int lineType=8;
Circle(img,center,w/32.0,Scalar(0,0,255),thickness,lineType);
}
和ellipse函数相似,我们可以看到circle函数中接受的参数:
-img就是circle将要在哪个图像中显示
-center就是圆心
-w/32.0就是半径
-Scalar(0,0,255)就是颜色;在RGB中就是红色。
-因为thickness=-1,圆将要被填充。
MyPolygon
void MyPolygon(Mat img)
{
int lineType=8;
Point rook_points[1][20];
rook_points[0][0] = Point( w/4, 7*w/8 );
rook_points[0][1] = Point( 3*w/4, 7*w/8 );
rook_points[0][2] = Point( 3*w/4, 13*w/16 );
rook_points[0][3] = Point( 11*w/16, 13*w/16 );
rook_points[0][4] = Point( 19*w/32, 3*w/8 );
rook_points[0][5] = Point( 3*w/4, 3*w/8 );
rook_points[0][6] = Point( 3*w/4, w/8 );
rook_points[0][7] = Point( 26*w/40, w/8 );
rook_points[0][8] = Point( 26*w/40, w/4 );
rook_points[0][9] = Point( 22*w/40, w/4 );
rook_points[0][10] = Point( 22*w/40, w/8 );
rook_points[0][11] = Point( 18*w/40, w/8 );
rook_points[0][12] = Point( 18*w/40, w/4 );
rook_points[0][13] = Point( 14*w/40, w/4 );
rook_points[0][14] = Point( 14*w/40, w/8 );
rook_points[0][15] = Point( w/4, w/8 );
rook_points[0][16] = Point( w/4, 3*w/8 );
rook_points[0][17] = Point( 13*w/32, 3*w/8 );
rook_points[0][18] = Point( 5*w/16, 13*w/16 );
rook_points[0][19] = Point( w/4, 13*w/16 );
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),在RGB色彩系统中就是白色
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色彩中就是黄色。
-由于thickness这个参数被置-1,所以矩形被填充。
结果
编译并运行程序,你会得到下面的结果