MFC类库中的CDC类有划线,画矩形,画椭圆,画多边形,文字等绘图函数,OpenCV也有类似的绘图函数。二者的区别在于MFC画图是在一定的区域内绘制图形,而OpenCV则是在图像上绘制,主要用于图像标注。
OpenCV的常用绘图函数有arrowedLine,circle ,drawContours, drawMarker, drawMarker, ellipse,fillConvexPoly, fillPoly , line, polylines , putText ,rectangle 。下面详细介绍这些函数及其用法。
arrowedLine()
arrowedLine()函数的原型如下:
参数:
img 装载有图像的Mat对象
pt1 第一点
pt2 第二点
color 绘制箭头线段颜色
thickness 圆形轮廓的厚度(如果为正)。负值(例如 FILLED)表示要绘制实心圆。
line_Type 线的类型,有FILLED,LINE_4,LINE_8,LINE_AA几种.
shift 点坐标中小数位数
tipLength 箭头尖端的长度与箭头长度的比例关系
用法示例
新建一个控制台程序,在程序中加入如下代码:
#include <iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
//std::cout << "Hello World!\n";
Mat bgn(Size(2048, 1024), CV_8UC3, Scalar(0));
arrowedLine(bgn, Point(50, 50), Point(300, 100), Scalar(0, 0, 255), 2, 8, 0, 0.08);
imshow("Background", bgn);
waitKey(0);
return 0;
}
试运行,结果如下:
circle()
circle()函数的原型如下:
函数参数:
img 图像,如载有图像的Mat对象
center 圆心(点)
color 颜色
thickness 圆形轮廓的厚度(如果为正)。负值(例如 FILLED)表示要绘制实心圆。
lineType 线条类型
shift 中心坐标和半径值中的小数位数。
示例程序
上面程序中加入画圆代码,如下:
#include <iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
//std::cout << "Hello World!\n";
Mat bgn(Size(2048, 1024), CV_8UC3, Scalar(0));
arrowedLine(bgn, Point(50, 50), Point(300, 100), Scalar(0, 0, 255), 2, 8, 0, 0.08);
circle(bgn, Point(200, 200), 100, Scalar(0, 0, 255), 2,8,0);
imshow("Background", bgn);
waitKey(0);
return 0;
}
试运行,结果如下:
drawContours()
drawContours() 函数的原型如下:
函数参数:
image 图像
conturs 所有输入轮廓。每个轮廓存储为点向量
conturIdx 指示要绘制的轮廓的参数。如果为负数,则绘制所有轮廓
color 颜色
thickness 圆形轮廓的厚度(如果为正)。负值(例如 FILLED)表示要绘制实心圆。
lineType 线条类型
hierarchy 有关层次结构的可选信息。仅当您只想绘制一些轮廓时才需要它(请参阅 maxLevel )
maxLevel 绘制轮廓的最大级别。如果为0,则只绘制指定的轮廓。如果为 1,该函数将绘制轮廓 和所有嵌套轮廓。如果为 2,则该函数绘制轮廓、所有嵌套轮廓、所有嵌套到嵌套轮廓, 依此类推。仅当存在可用的层次结构时才考虑此参数。
offset 可选的轮廓移动参数。将所有绘制的轮廓移动指定的 offset=(dx,dy) 。
该函数绘制轮廓轮廓或填充轮廓。 如果厚度≥0,则该函数在图像中绘制轮廓轮廓;如果厚度<0,则填充轮廓所包围的区域。
示例程序
修改上面的代码,如下:
#include <iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
//std::cout << "Hello World!\n";
Mat bgn(Size(2048, 1024), CV_8UC3, Scalar(0));
arrowedLine(bgn, Point(50, 50), Point(300, 100), Scalar(0, 0, 255), 2, 8, 0, 0.08);
circle(bgn, Point(200, 200), 100, Scalar(0, 0, 255), 2,8,0);
Mat src = imread("2.webp");
if (src.empty())
return -1;
cvtColor(src, src, COLOR_BGR2GRAY);
threshold(src, src, 235, 255, THRESH_BINARY_INV);
imshow("Source", src);
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(src, contours, hierarchy,
RETR_CCOMP, CHAIN_APPROX_SIMPLE);
int idx = 0;
for (; idx >= 0; idx = hierarchy[idx][0])
{
Scalar color(rand() & 255, rand() & 255, rand() & 255);
drawContours(bgn, contours, idx, color, FILLED, 8, hierarchy);
}
imshow("Background", bgn);
waitKey(0);
return 0;
}
试运行,结果如下:
drawMarker()
drawMarker()函数的原型如下:
函数参数:
img 图像
position 十字准线的位置
color 线条颜色
markerType 您要使用的特定标记类型,缺省是十字标记,有以下几种类型:
makerSize 标记轴的长度 [默认 = 20 像素]
thickness 线条厚度,缺省是1
lineType 线条类型,缺省是8
该函数的作用是在图像中的预定义位置绘制标记。
示例程序:
在上面的示例程序中加入draw maker示例代码,如下:
#include <iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
//std::cout << "Hello World!\n";
Mat bgn(Size(2048, 1024), CV_8UC3, Scalar(0));
arrowedLine(bgn, Point(50, 50), Point(300, 100), Scalar(0, 0, 255), 2, 8, 0, 0.08); //draw arrow line
circle(bgn, Point(200, 200), 100, Scalar(0, 0, 255), 2,8,0); //draw circle
Mat src = imread("2.webp");
if (src.empty())
return -1;
cvtColor(src, src, COLOR_BGR2GRAY);
threshold(src, src, 235, 255, THRESH_BINARY_INV);
imshow("Source", src);
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(src, contours, hierarchy,
RETR_CCOMP, CHAIN_APPROX_SIMPLE);
int idx = 0;
RNG rng(0xFFFFFFFF);
for (; idx >= 0; idx = hierarchy[idx][0])
{
drawContours(bgn, contours, idx, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), FILLED, 8, hierarchy);
}
drawMarker(bgn, Point(500, 500), Scalar(255), MARKER_STAR, 40, 4, 8); //draw maker
imshow("Background", bgn);
waitKey(0);
return 0;
}
试运行,结果如下:
ellipse()
ellipse()函数的原型有两个, 如下:
函数参数:
img 图像
center 椭圆的中心
axes 椭圆长短主轴尺寸的一半
angle 椭圆旋转角度(以度为单位)
startAngle 椭圆弧的起始角度(以度为单位)
endAngle 椭圆弧的结束角度(以度为单位)
box 通过 RotatedRect 的替代椭圆表示。这意味着该函数绘制一个内切于该旋转矩形的椭 圆。
color 椭圆线条颜色
thickness 椭圆弧轮廓的厚度(如果为正)。否则,这表明要绘制一个填充的椭圆扇区
lineType 椭圆边界的类型。请参阅线型。
示例程序
在上面的示例程序中添加画椭圆的代码,如下:
#include <iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
//std::cout << "Hello World!\n";
Mat bgn(Size(2048, 1024), CV_8UC3, Scalar(0));
//draw arrow line
arrowedLine(bgn, Point(50, 50), Point(300, 100), Scalar(0, 0, 255), 2, 8, 0, 0.08);
//draw circle
circle(bgn, Point(200, 200), 100, Scalar(0, 0, 255), 2,8,0);
//draw conturs test
Mat src = imread("2.webp");
if (src.empty())
return -1;
cvtColor(src, src, COLOR_BGR2GRAY);
threshold(src, src, 235, 255, THRESH_BINARY_INV);
imshow("Source", src);
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(src, contours, hierarchy,
RETR_CCOMP, CHAIN_APPROX_SIMPLE);
int idx = 0;
RNG rng(0xFFFFFFFF);
for (; idx >= 0; idx = hierarchy[idx][0])
{
drawContours(bgn, contours, idx, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), FILLED, 8, hierarchy);
}
//draw maker
drawMarker(bgn, Point(500, 500), Scalar(255), MARKER_STAR, 40, 4, 8);
//draw ellipse
ellipse(bgn, Point(500, 500), Size(400, 250), 0, 0, 360, Scalar(0,0,255),4, 8);
ellipse(bgn, RotatedRect(Point2f(500,500),Size2f(300,100),45), Scalar(0, 255, 0), -1, 8);
imshow("Background", bgn);
waitKey(0);
return 0;
}
试运行,结果如下:
fillConvexPoly()
fillConvexPoly() 函数的原型有两个,如下:
函数参数:
img 图像
points 多边形顶点。
pts 多边形的顶点的数组,其中每个多边形表示为点数组
npts 顶点的个数
color 多边形颜色
lineType 多边形线型
shift 顶点坐标中的小数位数
函数 cv::fillConvexPoly 绘制填充的凸多边形。此函数比函数 fillPoly 快得多。它不仅可以填充凸多边形,还可以填充任何没有自交的单调多边形,即轮廓与每条水平线(扫描线)最多相交两次的多边形(尽管其最顶部和/或底部边缘可以是水平的)。
示例程序
在上面示例程序的main函数中加入fillConvexPoly的代码,如下:
//fillConvexPoly
Point pt;
vector<Point2i> mpoints;
Point pts[6];
for (int i = 0; i < 18; i++)
{
pt.x = 1300 + 300 * cos(20 * i * CV_PI / 180);
pt.y = 500 + 300 * sin(20 * i * CV_PI / 180);
mpoints.push_back(pt);
}
for (int i = 0; i < 6; i++)
{
pt.x = 1300 + 200 * cos(60 * i * CV_PI / 180);
pt.y = 500 + 200 * sin(60 * i * CV_PI / 180);
pts[i] = pt;
}
fillConvexPoly(bgn, mpoints,Scalar(255,0,0));
fillConvexPoly(bgn, pts, 6,Scalar(255, 0, 255));
imshow("Background", bgn);
waitKey(0);
return 0;
}
试运行,结果如下:
fillPoly()
fillPoly函数的原型函数如下:
函数参数:
img 图像
pts 多边形顶点
color 多边形颜色
lineType 多边形线型
shift 顶点坐标中的小数位数。
offset 轮廓所有点的可选偏移。
函数 fillPoly 填充由多个多边形轮廓界定的区域。该函数可以填充复杂区域,例如,有孔的区域、具有自相交的轮廓(其中的某些部分)等等。
示例程序
在上面的示例程序中加入fillPoly代码, 如下:
//fillPoly
mpoints.clear();
for (int i = 0; i < 9; i++)
{
pt.x = 1000 + 100 * cos(40 * i * CV_PI / 180);
pt.y = 300 + 100 * sin(40 * i * CV_PI / 180);
mpoints.push_back(pt);
}
fillPoly(bgn, mpoints, Scalar(0, 255, 0));
imshow("Background", bgn);
waitKey(0);
return 0;
}
试运行,结果如下:
line()
line()函数的原型如下:
函数参数:
pt1 第一个点
p2 第二个点
color 线段颜色
thickness 线条厚度,缺省值为1
lineType 线的类型,缺省值为8
shift 点坐标中小数位数
函数 line 在图像中绘制 pt1 和 pt2 点之间的线段。该线被图像边界剪裁。对于具有整数坐标的非抗锯齿线,使用 8 连接或 4 连接 Bresenham 算法。粗线以圆角结尾绘制。抗锯齿线是使用高斯滤波绘制的。
示例程序:
在上面的示例程序中加入 line演示代码,如下:
//fillPoly
mpoints.clear();
for (int i = 0; i < 9; i++)
{
pt.x = 1000 + 100 * cos(40 * i * CV_PI / 180);
pt.y = 300 + 100 * sin(40 * i * CV_PI / 180);
mpoints.push_back(pt);
}
fillPoly(bgn, mpoints, Scalar(0, 255, 0));
//line
line(bgn, Point(100, 100), Point(600, 600), Scalar(255, 255, 0), 4, 8, 0);
imshow("Background", bgn);
waitKey(0);
return 0;
}
polylines()
polylines()函数的原型有两个,如下:
函数参数 :
img 图像
pts 点数组
isClosed 指示绘制的折线是否闭合。如果它们是闭合的,则该函数从每条曲线的最后一个顶 点到其第一个顶点绘制一条线。
thickness 线条厚度,缺省值为1
lineType 线条类型, 缺省值为8
shift 点坐标小数点位数
示例程序
在上面的示例函数中加入,画polines的代码,如下:
//polines
mpoints.clear();
RNG rng1;
for (int i = 0; i < 9; i++)
{
pt.x = rng1.uniform(300,1500);
pt.y = rng1.uniform(800, 1000);
mpoints.push_back(pt);
}
polylines(bgn, mpoints, 0, Scalar(0, 0, 255));
imshow("Background", bgn);
waitKey(0);
return 0;
}
试运行,结果如下:
putText()
putText()函数的原型如下:
函数参数:
img 图像
text 要绘制的字符串
org 图像中文本字符串的左下角。
fontFace 字体类型,请参见HersheyFonts。下面是Hershey fonts类型
fontScale 乘以字体特定基本大小的字体比例因子。
color 绘制文本颜色
thichness 线条厚度,缺省为1
lineType 线条类型
bottomLeftOrigin 如果为真,图像数据源位于左下角。否则,它位于左上角。
示例程序
在上面的示例程序中加入绘制字符串文本的代码, 如下:
//polines
mpoints.clear();
RNG rng1;
for (int i = 0; i < 9; i++)
{
pt.x = rng1.uniform(300,1500);
pt.y = rng1.uniform(800, 1000);
mpoints.push_back(pt);
}
polylines(bgn, mpoints, 0, Scalar(0, 0, 255));
//putText
putText(bgn, "Hello, OpenCV!, Hello World!", Point(500, 1000), FONT_ITALIC,1, Scalar(255,255,255), 4);
imshow("Background", bgn);
waitKey(0);
return 0;
}
试运行,结果如下:
rectangle()
rectangle()函数的原型有两个,如下:
函数参数:
img 图像
pt1 矩形的一个顶点
pt2 矩形的另一个对角点
rec 欲绘制的矩形
color 绘制矩形颜色
thickness 线条厚度,缺省为1
lineType 线条类型,缺省为8
shift 矩形顶点坐标的小数点位数,缺省为0
示例程序
在上面的示例程序中加入绘制矩形的代码,如下:
//putText
putText(bgn, "Hello, OpenCV!, Hello World!", Point(500, 1000), FONT_ITALIC,1, Scalar(255,255,255), 4);
//retangle
rectangle(bgn,Point(30, 850), Point(150, 1000), Scalar(255,255,255),4);
rectangle(bgn, Rect(Point(60,880),Size(60,90)), Scalar(127, 127, 127), 4);
imshow("Background", bgn);
waitKey(0);
return 0;
}
到这里,OpenCV常用绘图函数已介绍完毕。该博文的示例程序已上传到CSDN,若需仔细查看去下载到本地磁盘。其链接为:https://download.csdn.net/download/billliu66/89670302