1. 学习目标:
绘图内容 | OpenCV函数 |
Line(线) | line() |
Ellipse(椭圆) | ellipse() |
Rectangle(矩形框) | rectangle() |
Circle(圆) | circle() |
Filled polygon(填充多边形) | fillPoly() |
2. OpenCV理论
该部分主要使用两个结构 cv::Point and cv::Scalar
2.1 Point
这是一个2D点,坐标设置为Point p(x,y);
定义
Point point;
point.x = 10;
point.y = 8;
or
Point point(10,8);
2.2 Scalar
颜色-3通道BGR
Scalar( a, b, c )
Blue = a,Green = b, and Red = c
3 Code
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#define w 400 //宏定义
using namespace cv;
void MyEllipse( Mat img, double angle ); //绘制椭圆
void MyFilledCircle( Mat img, Point center ); //填充圆
void MyPolygon( Mat img ); //多边形
void MyLine( Mat img, Point start, Point end ); //线
int main( void ){
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( atom_image, 90 );
MyEllipse( atom_image, 0 );
MyEllipse( atom_image, 45 );
MyEllipse( atom_image, -45 );
MyFilledCircle( atom_image, Point( w/2, w/2) );
MyPolygon( rook_image );
//矩形框
rectangle( rook_image,
Point( 0, 7*w/8 ),
Point( w, w),
Scalar( 0, 255, 255 ),
FILLED,
LINE_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 ) );
imshow( atom_window, atom_image );
moveWindow( atom_window, 0, 200 );
imshow( rook_window, rook_image );
moveWindow( rook_window, w, 200 );
waitKey( 0 );
return(0);
}
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 ); //设置线宽
}
void MyFilledCircle( Mat img, Point center )
{
circle( img,
center,
w/32,
Scalar( 0, 0, 255 ),
FILLED, //是否填充 FILLED为填充
LINE_8 );
}
void MyPolygon( Mat img )//多边形
{
int lineType = LINE_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为填充多边形
fillPoly( img,
ppt,//起始点
npt,//结束点
1,
Scalar( 255, 255, 255 ),
lineType );
}
void MyLine( Mat img, Point start, Point end )
{
int thickness = 2;
int lineType = LINE_8;
line( img,
start,
end,
Scalar( 0, 0, 0 ),
thickness,
lineType );
}
4 代码详解
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:
MyEllipse( atom_image, 90 );
MyEllipse( atom_image, 0 );
MyEllipse( atom_image, 45 );
MyEllipse( atom_image, -45 );
MyFilledCircle( atom_image, Point( w/2, w/2) );
下面,主要介绍绘制函数
Myline
void MyLine( Mat img, Point start, Point end )
{
int thickness = 2;
int lineType = LINE_8;
line( img,
start,
end,
Scalar( 0, 0, 0 ),
thickness,
lineType );
}
我们可以看到,MyLine只调用函数line(),它执行以下操作:
从Point start到Point end画一条线
该行显示在图像img中
线颜色由(0,0,0)定义,它是对应于黑色的RGB值
线条粗细设置为厚度(在这种情况下为2)
该行是一个8连接的(lineType = 8)
MyEllipse
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 );
}
从上面的代码中,我们可以观察到函数ellipse()绘制一个椭圆,使得:
椭圆显示在图像img中
椭圆中心位于点(w / 2,w / 2),并被封装在一个大小的盒子中(w / 4,w / 16)
椭圆旋转角度 angle
椭圆在0到360度之间延伸
图的颜色将是(255,0,0),这意味着BGR值为蓝色。( 255, 0, 0 )
椭圆的厚度为2。thickness=2;
MyFilledCircle
void MyFilledCircle( Mat img, Point center )
{
circle( img,
center,
w/32,
Scalar( 0, 0, 255 ),
FILLED,
LINE_8 );
}
与椭圆函数类似,我们可以观察到圆圈作为参数接收:
将显示圆圈的图像(img)
圆心表示为点中心
圆的半径:w / 32
圆的颜色:(0,0,255),表示BGR中的红色
由于厚度= -1,因此将绘制圆圈。
MyPolygon
void MyPolygon( Mat img )
{
int lineType = LINE_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中的点集
多边形的颜色由(255,255,255)定义,这是白色的BGR值
rectangle
rectangle( rook_image,
Point( 0, 7*w/8 ),
Point( w, w),
Scalar( 0, 255, 255 ),
FILLED,
LINE_8 );
最后我们有了cv :: rectangle函数(我们没有为这个人创建一个特殊的函数)。 我们注意到:
矩形将在rook_image上绘制
矩形的两个相对顶点由(0,7 * w / 8)和(w,w)定义
矩形的颜色由(0,255,255)给出,它是黄色的BGR值
由于厚度值由FILLED(-1)给出,因此矩形将被填充。