目标
在本教程中,将学习如何:
- 使用OpenCV函数行()绘制一行
- 使用OpenCV函数椭圆()绘制椭圆
- 使用OpenCV函数矩形()绘制一个矩形
- 使用OpenCV函数圈()绘制一个圆
- 使用OpenCV函数fillPoly()绘制一个填充的多边形
OpenCV理论
对于本教程,大量使用两个结构:cv :: Point和cv :: Scalar:
point
2D point, 由图像 x, y坐标确定,可以定义成:
Point pt;
pt.x = 10;
pt.y = 8;
或
Point pt = Point(10, 8);
Scalar
代表一个4元素向量。Scalar类型广泛用于OpenCV中,用于传递像素值。
在本教程中,我们将广泛使用它来表示BGR颜色值(3个参数)。如果不使用最后一个参数,则无需定义最后一个参数。
让我们看一个例子,如果我们被要求一个颜色参数,我们给:
Scalar(a, b, c)
将定义一个BGR颜色,例如:Blue = a,Green = b和Red = c.
代码实现
#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);
}
解释
绘制两个例子(一个原子和一个车),我们必须创建两个图像和两个窗口来显示它们。
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只是调用函数line(),它执行以下操作:
- 从开始点到结束点绘制一条线
- 该行显示在图像img中
- 线颜色由(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, 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)
- 定义椭圆旋转角度
- 椭圆延伸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);
}
要绘制一个填充的多边形,我们使用函数fillPoly()。我们注意到:
- 多边形将在img上绘制
- 多边形的顶点是ppt中的一组点
- 多边形的颜色由(255,255,255)定义,它是白色的BGR值