OpenCV绘制几何图形
一、学习目标
- 了解点和颜色标量的数据结构对象
- 学会使用OpenCV画直线段
- 学会使用OpenCV画椭圆
- 学会使用OpenCV画矩形
- 学会使用OpenCV画圆
- 学会使用OpenCV画封闭的任意多边形
二、OpenCV中点和颜色标量的表示
1、点的表示
在OpenCV中,cv::Point它表示一个二维点,由其图像坐标x和y指定,我们可以定义为:
Point pt;
pt.x = 10;
pt.y = 8;
或者:
Point pt = Point(10, 8);
2、颜色标量的表示
cv::Scalar 表示一个包含4个元素的向量。在OpenCV中,标量类型被广泛用于传递像素值。在本教程中,我们将广泛地使用它来表示BGR颜色值(3个参数)。如果不使用最后一个实参,则不需要定义它。
让我们看一个例子,如果我们定义一个颜色参数,我们给出:
Scalar( a, b, c )
我们将定义一个BGR颜色,例如:蓝色= a,绿色= b,红色= c
三、绘制不同的几何形状
1、画直线段:cv::line函数
其函数原型为:
void cv::line(InputOutputArray img,
Point pt1,
Point pt2,
const Scalar & color,
int thickness = 1,
int lineType = LINE_8,
int shift = 0 )
- 参数 img: 绘制线段的对象,即将直线绘制在哪个图像上
- 参数 pt1: 线段的第一个点,Point类型对象
- 参数 pt2: 线段的第二个点
- 参数 color: 线段的颜色,Scalar类型对象
- 参数 thickness: 线段的粗细
- 参数 lineType: 线段的类型
- 参数 shift: 点坐标中的小数位数
cv::line函数线绘制图像中pt1和pt2点之间的线段。这条线段可以被图像边界所截断。对于整数坐标的非反锯齿线,使用8连接或4连接的Bresenham算法。粗线以圆角结尾。反锯齿线是用高斯滤波绘制的。
参数 lineType枚举自以下值:
参数取值 | 取值说明 |
---|---|
FILLED | 取值-1,一般表示填充相应的几何图形 |
LINE_4 | 4-connected line |
LINE_8 | 8-connected line |
LINE_AA | 抗锯齿线 |
使用实例如下:
void drawLine(Mat& src, Point start, Point end)
{
int thickNess = 50;
int lineType = LINE_8;
line(src, start, end, Scalar(0, 0, 0), thickNess, lineType);
}
2、画椭圆:cv::ellipse 函数
其函数原型为:
void cv::ellipse(InputOutputArray img,
Point center,
Size axes,
double angle,
double startAngle,
double endAngle,
const Scalar & color,
int thickness = 1,
int lineType = LINE_8,
int shift = 0)
- 参数 img: 绘制椭圆的对象,即将椭圆绘制在哪个图像上
- 参数 center: 椭圆的中心,Point点类型
- 参数 axes: 椭圆主轴大小的一半,包含长轴和短轴的值
- 参数 angle: 椭圆旋转角的角度
- 参数 startAngle: 椭圆圆弧的起始角度,以度为单位
- 参数 endAngle: 椭圆圆弧的结束角度,以度为单位
- 参数 color: 绘制椭圆的颜色
- 参数 thickness: 取正值时表示椭圆弧轮廓的厚度,否则表示要绘制一个填充的椭圆扇区
- 参数 lineType: 绘制椭圆线段的类型
- 参数 shift: 中心坐标和坐标轴值的小数位数
带有更多参数的cv::ellipse 函数绘制椭圆轮廓、填充的椭圆、椭圆弧或填充的椭圆扇区。采用分段线性曲线逼近椭圆弧边界。如果你需要更多的控制椭圆渲染,你可以使用ellipse2Poly检索曲线,然后用polyline渲染它或用fillPoly填充它。如果你使用函数的第一个变体,并希望绘制整个椭圆,而不是弧,传递startAngle=0和endAngle=360。如果startAngle大于endAngle,它们就交换了。下图说明了绘制蓝色弧线的参数含义。
使用实例如下:
void drawEllipse(Mat& src, double angle)
{
int thickNess = 2;
int lineType = LINE_8;
ellipse(src, Point(width / 2, height / 2), Size(width / 2, height / 2), angle, 0, 360, Scalar(255, 0, 0), thickNess, lineType);
}
3、画矩形: cv::rectangle 函数
其函数原型为:
void cv::rectangle(InputOutputArray img,
Point pt1,
Point pt2,
const Scalar & color,
int thickness = 1,
int lineType = LINE_8,
int shift = 0)
- 参数 img: 绘制矩形的对象,即将矩形绘制在哪个图像上
- 参数 pt1: 矩形的第一个顶点
- 参数 pt2: 与pt1相对的矩形的顶点
- 参数 color: 矩形颜色或亮度(灰度图像)
- 参数 thickness: 正值表示矩形线条的粗细。负值意味着函数会绘制一个填充的矩形
- 参数 lineType: 矩形线条的类型
- 参数 shift: 点坐标中的小数位数
函数cv::rectangle绘制一个矩形轮廓线或两个相对的角为pt1和pt2的填充矩形
使用实例如下:
void drawRectangle(Mat& src, Point start, Point end)
{
int thickNess = 2;
int lineType = LINE_8;
rectangle(src, start, end, Scalar(0, 255, 0), thickNess, lineType);
}
4、画圆:cv::circle函数
其函数原型为:
void cv::circle (InputOutputArray img,
Point center,
int radius,
const Scalar & color,
int thickness = 1,
int lineType = LINE_8,
int shift = 0)
- 参数 img: 绘制圆的对象,即将圆绘制在哪个图像上
- 参数 center: 圆的中心
- 参数 radius: 圆的半径
- 参数 color: 圆的颜色
- 参数 thickness: 正值表示圆轮廓的厚度。负值意味着要绘制一个填充的圆
- 参数 lineType: 圆边界的线条类型
- 参数 shift: 中心坐标和半径值中的小数位数
函数cv::circle以给定的圆心和半径绘制一个简单的或已填充的圆
使用实例如下:
void drawCircle(Mat& src, Point center)
{
int thickNess = FILLED;
int lineType = LINE_AA;
circle(src, center, width / 32, Scalar(255, 0, 0), thickNess, lineType);
}
5、画封闭多边形:cv::fillPoly 函数
其函数原型为:
void cv::fillPoly(InputOutputArray img,
const Point ** pts,
const int * npts,
int ncontours,
const Scalar & color,
int lineType = LINE_8,
int shift = 0,
Point offset = Point())
- 参数 img: 绘制多边形的对象,即将多边形绘制在哪个图像上
- 参数 pts: 多边形顶点的数组,其中每个多边形都表示为点的数组,二维数组的一行表示一个多边形,有几行就表示有几个多边形
- 参数 npts: 每个多边形顶点的个数,是一维数组的形式
- 参数 color: 绘制多边形的颜色
- 参数 lineType: 绘制多边形轮廓的类型
- 参数 shift: 顶点坐标的小数位数
- 参数 offset: 所有的点的轮廓的偏移
使用实例如下:
void drawPoly(Mat& src, Point** pts, int npts)
{
const Point* ppt[1] = { pts[0] };
int npt[] = { npts };
int lineType = LINE_AA;
fillPoly(src, ppt, npt, 1, Scalar(255, 255, 255), lineType);
}
四、完整代码示例
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
// 定义背景画布的尺寸
#define w 800
// 提前声明自定义的绘制函数
void drawLine(Mat& src, Point start, Point end);
void drawEllipse(Mat& src, double angle);
void drawRectangle(Mat& src, Point start, Point end);
void drawCircle(Mat& src, Point center);
void drawPoly(Mat& src, Point** pts, int npts);
int main(int argc, char** argv)
{
// 定义两个窗体名称
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);
// 绘制椭圆
drawEllipse(atom_image, 90);
drawEllipse(atom_image, 0);
drawEllipse(atom_image, 45);
drawEllipse(atom_image, -45);
// 绘制圆
drawCircle(atom_image, Point(w / 2, w / 2));
// 定义多边形的顶点
Point **rook_points=new Point*[1];
rook_points[0] = new Point[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);
// 绘制多边形
drawPoly(rook_image, rook_points, 20);
// 绘制直线
drawLine(rook_image, Point(0, 15 * w / 16), Point(w, 15 * w / 16));
drawLine(rook_image, Point(w / 4, 7 * w / 8), Point(w / 4, w));
drawLine(rook_image, Point(w / 2, 7 * w / 8), Point(w / 2, w));
drawLine(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);
system("pause");
return EXIT_SUCCESS;
}
// 自定义函数绘制直线
void drawLine(Mat& src, Point start, Point end)
{
int thickNess = 50;
int lineType = LINE_8;
line(src, start, end, Scalar(0, 0, 0), thickNess, lineType);
}
// 自定义函数绘制椭圆
void drawEllipse(Mat& src, double angle)
{
int thickNess = 2;
int lineType = LINE_8;
ellipse(src, Point(w / 2, w / 2), Size(w / 4, w / 16), angle, 0, 360, Scalar(255, 0, 0), thickNess, lineType);
}
// 自定义函数绘制矩形
void drawRectangle(Mat& src, Point start, Point end)
{
int thickNess = 2;
int lineType = LINE_8;
rectangle(src, start, end, Scalar(0, 255, 0), thickNess, lineType);
}
// 自定义函数绘制圆
void drawCircle(Mat& src, Point center)
{
int thickNess = FILLED;
int lineType = LINE_AA;
circle(src, center, w / 32, Scalar(255, 0, 0), thickNess, lineType);
}
// 自定义函数绘制多边形
void drawPoly(Mat& src, Point** pts, int npts)
{
const Point* ppt[1] = { pts[0] };
int npt[] = { npts };
int lineType = LINE_AA;
fillPoly(src, ppt, npt, 1, Scalar(255, 255, 255), lineType);
}