OpenCV基本绘图
目标
在本教程中,您将学习如何:
- 使用cv :: Point定义图像中的2D点。
- 使用cv :: Scalar,为什么它是有用的
- 画一条线使用OpenCV的函数CV ::线
- 画一个椭圆利用OpenCV的功能CV ::椭圆形
- 绘制一个矩形,使用OpenCV的功能CV ::矩形
- 画一个圆圈使用OpenCV的功能CV ::圈
- 使用OpenCV函数cv :: fillPoly绘制一个填充的多边形
OpenCV理论
对于本教程,我们将大量使用两个结构:cv :: Point和cv :: Scalar:
Point
它表示由其图像坐标和指定的2D点。我们可以将其定义为:xy
Point pt;
pt.x = 10;
pt.y = 8;
or
Point pt = Point(10,8);
Scalar
- 代表一个4元素的向量。Scalar类型广泛用于OpenCV中,用于传递像素值。
- 在本教程中,我们将广泛使用它来表示BGR颜色值(3个参数)。如果不使用最后一个参数,则无需定义最后一个参数。
- 让我们看一个例子,如果我们被要求一个颜色参数,我们给出:
Scalar( a, b, c )
我们将定义一个BGR颜色,如:Blue = a,Green = b和Red = c
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,
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( 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 );
}
说明
- 由于我们计划绘制两个例子(an atom and a rook),我们必须创建两个图像和两个窗口来显示它们。
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,矩形和MyPolygon:
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 ) );
- 我们来检查一下这些功能的内容:
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只是调用函数cv :: line,它执行以下操作:
- 从点开始到点结束绘制一条线
- 该行显示在图像img中
- 线颜色由Scalar(0,0,0)定义,它是与Black相对应的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 );
}
从上面的代码,我们可以看到函数cv :: ellipse绘制一个椭圆,使得:
- 椭圆显示在图像img中
- 椭圆中心位于**(w / 2,w / 2)**的点,并且被包围在大小为**(w / 4,w / 16)**
- 椭圆旋转角度
- 椭圆延伸0到360度之间的圆弧
- 图中的颜色将为标量(255,0,0),表示BGR值为蓝色。
- 椭圆的厚度为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 );
}
要绘制一个填充的多边形,我们使用函数cv :: fillPoly。我们注意到:
- 多边形将在img上绘制
- 多边形的顶点是ppt中的一组点
- 要绘制的顶点总数为npt
- 要绘制的多边形的数量只有1
- 多边形的颜色由Scalar(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)**定义
- 矩形的颜色由Scalar(0,255,255)给出,它是黄色的BGR值
- 由于厚度值由FILLED(-1)给出,矩形将被填充。
结果
编译和运行你的程序应该给你一个这样的结果: