基本图形的绘制函数
OpenCv 中用于绘制基本图形的函数接口如下所示:
- 用于绘制直线的 line 函数;
- 用于绘制椭圆的 ellipse 函数;
- 用于绘制矩形的 rectangle 函数;
- 用于绘制圆的 circle 函数;
- 用于绘制文字的函数 putText 函数;
- 用于绘制多边形的 fillPoly 函数;
绘制线段的函数原型:
/*绘制线段*/
void cv::line (InputOutputArray img, Point pt1, Point pt2, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0);
Params:
- InputOutputArray img: 输入的图片;
- Point pt1: 线段的起始点坐标;
- Point pt2: 线段的终止点坐标;
- const Scalar &color: 线段的颜色;
- int thickness = 1: 线段的宽度;
- int lineType = LIEN_8: 线段的类型;
- int shift = 0: 点坐标中的小数位数;
常见的用法
void drawLine(Mat img, Point start, Point end)
{
int thickness = 2;
int lineType = 8;
line(img, start, end, Scalar(0, 0, 0), thickness, lineType);
}
绘制椭圆弧函数原型:
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);
Params:
- InputOutArray img: 输入的图片;
- Point center:center of the size of the ellipse;
- Size axes: Half of the size of the ellipse main axes;
- double angle: Ellipse rotation angle in degrees;
- double startAngle: Starting angle of the elliptic arc in degrees;
- double endAngle: Ending angle of the elliptic arc in degrees;
- const Scalar &color: Ellipse color;
- int thickness = 1: Thickness of the ellipse arc outline, if positive. Otherwise, this indicates that a filled ellipse sector is to be drawn;
- int lineType = LINE_8: Type of the ellipse boundary. See LineTypes;
- int shift = 0: Number of fractional bits in the coordinates of the center and values of axes.
常用的椭圆绘制函数如下:
/*实现了绘制不同角度,相同尺寸的椭圆*/
#define WINDOW_WIDTH 600 // 定义窗口大小的宏
void DrawEllipse(Mat img, double angle)
{
cv::Point center(WINDOW_WIDTH/2, WINDOW_WIDTH/2);
cv::Size size(WINDOW_WIDTH/4, WINDOW_WIDTH/16);
double startAngle = 0; // 形成一个闭合的椭圆弧线:就是圆弧
double endAngle = 360;
Scalar color = Scalar(255, 129, 0);
int thickness = 2;
ellipse(img, center, size, angle, startAngle, endAngle, thickness);
}
绘制矩形的函数原型:
/*绘制矩形*/
void cv::rectangle (InputOutputArray img, Rect rec, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)
Params:
- InputOutArray img: 输入的图片;
- Rect rect: 矩形;
- const Scalar &color: 矩形的颜色;
- int thickness = 1: 矩形的宽度;
- int lineType = LINE_8: Type of the ellipse boundary. See LineTypes;
- int shift = 0: Number of fractional bits in the coordinates of the center and values of axes。
常见的用法如下:
/*实现了绘制不同尺寸的矩形*/
void DrawRectangle(Mat img, Rect rect)
{
Scalar color = Scalar(0, 0, 255); // 红色
int thickness = 2;
cv::rectangle (img, rect, color, thickness);
}
绘制圆形的函数原型
void cv::circle (InputOutputArray img, Point center, int radius, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0);
Params:
- InputOutputArray img: Image where the circle is drawn.
- Point center: Center of the circle.
- int radius: Radius of the circle.
- const Scalar &color: Circle color.
- int thickness = 1: Thickness of the circle outline, if positive. Negative values, like FILLED, mean that a filled circle is to be drawn.
- int lineType = LINE_8: Type of the circle boundary. See LineTypes
- int shift = 0: Number of fractional bits in the coordinates of the center and in the radius value.
常见的使用用法为:
/*实现了实心圆的绘制*/
void drawCircle(Mat img, Point center)
{
int radius = 15; // 半径
Scalar color(0, 0, 255); // 红色
int thickness = -1; // thickness 为负数时表示绘制实心图
int lineType = 8;
circle(img, center, radius, color, thickness, lineType);
}
添加文字的函数原型:
void cv::putText (InputOutputArray img, const String &text, Point org, int fontFace, double fontScale, Scalar color, int thickness=1, int lineType=LINE_8, bool bottomLeftOrigin=false);
Parameters
- InputOutputArray img: Image.
- const String &text: Text string to be drawn.
- Point org: Bottom-left corner of the text string in the image.
- int fontFace: Font type, see HersheyFonts.
- double fontScale: Font scale factor that is multiplied by the font-specific base size.
- Scalar color: Text color.
- int thickness = 1: Thickness of the lines used to draw a text.
- int lineType = LINE_8: Line type. See LineTypes
- int bottomLeftOrigin = false: When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner.
常见的使用方法如下:
/*实现了添加文字*/
void drawText(Mat img, String text)
{
cv::Point org(10, 20);
int fontFace = cv::FONT_HERSHEY_SIMPLEX;
double fontScalar = 0.8;
cv::Scalar color(0, 0, 255);
cv::putText(img, text, org, fontFace, fontScalar, color);
}
填充多边形的函数原型:
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())
Parameters
- InputOutArray img:输入的图形;
- const Point **pts:多边形的顶点集合;
- const int *npts:多边形顶点的数目;
- int ncontours:要绘制的多边形的数量;
- const Scalar &color:多边型的颜色;
- 其他选择默认值就可以了;
使用的例子如下:
/*实现一个多边形*/
void drawPolygon(Mat img)
{
// 创建点集
cv::Point rootPoints[1][4] =
rootPoints[0][0] = cv::Point(10, 10); rootPoints[0][1] = cv::Point(10, 50);
rootPoints[0][2] = cv::Point(30, 10); rootPoints[0][3] = cv::Point(30, 50);
const Point *ppt[1] = {rootPoints[0]};
int npt[] = {4}; // 第一个多边形点集数量
int ncontours = 1;
cv::Scalar color(0, 0, 255); // 红色
cv::fillPoly(img, ppt, npt, ncontours, color);
}
官方例子
第一个例子:
#include <opencv2/opencv.hpp>
#define W (400)
void MyEllipse(cv::Mat img, double angle); // 画弧线
void MyFilledCircle(cv::Mat img, cv::Point center); // 画圆
void MyPolygon(cv::Mat img); // 画多边形
void MyLine(cv::Mat img, cv::Point start, cv::Point end); // 画线段
int main(void)
{
char atom_window[] = "Drawing 1: Atom";
char rook_window[] = "Drawing 2: Rook";
cv::Mat atom_image = cv::Mat::zeros(W, W, CV_8UC3);
cv::Mat rook_image = cv::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, cv::Point(W / 2, W / 2));
MyPolygon(rook_image);
cv::Point rectPoint1(0, 7*W/8);
cv::Point rectPoint2(W, W);
cv::Scalar color(0, 255, 255);
int thickness = cv::FILLED;
int lineType = cv::LINE_8;
rectangle(rook_image, rectPoint1, rectPoint2, color, thickness, lineType);
MyLine(rook_image, cv::Point(0, 15 * W / 16), cv::Point(W, 15 * W / 16));
MyLine(rook_image, cv::Point(W / 4, 7 * W / 8), cv::Point(W / 4, W));
MyLine(rook_image, cv::Point(W / 2, 7 * W / 8), cv::Point(W / 2, W));
MyLine(rook_image, cv::Point(3 * W / 4, 7 * W / 8), cv::Point(3 * W / 4, W));
int showWidth = 0, showHeight = 200;
cv::imshow(atom_window, atom_image);
cv::moveWindow(atom_window, showWidth, showHeight); // 把图形显示在窗口指定的位置
showWidth = W; showHeight = 200;
cv::imshow(rook_window, rook_image);
cv::moveWindow(rook_window, showWidth, showHeight); // 把图像显示在窗口指定的位置
cv::waitKey(0);
return(0);
}
/*绘制弧线*/
void MyEllipse(cv::Mat img, double angle)
{
cv::Point center(W / 2, W / 2); // 中心
cv::Size size(W / 4, W / 16); // 长短轴的半轴
double startAngle = 0; // 起始角度
double endAngle = 360; // 终止角度
cv::Scalar color = cv::Scalar(255, 0, 0); // 颜色
int thickness = 2; // 线条粗细
int lineType = 8; // 线条类型
cv::ellipse(img, center, size, angle, startAngle, endAngle, color, thickness, lineType);
}
/*绘制填充的圆形*/
void MyFilledCircle(cv::Mat img, cv::Point center)
{
int radius = W / 32;
cv::Scalar color(0, 0, 255);
int thickness = cv::FILLED;
int lineType = cv::LINE_8;
circle(img, center, radius, color, thickness, lineType);
}
/*绘制多边形*/
void MyPolygon(cv::Mat img)
{
cv::Point rook_points[1][20];
rook_points[0][0] = cv::Point(W / 4, 7 * W / 8);
rook_points[0][1] = cv::Point(3 * W / 4, 7 * W / 8);
rook_points[0][2] = cv::Point(3 * W / 4, 13 * W / 16);
rook_points[0][3] = cv::Point(11 * W / 16, 13 * W / 16);
rook_points[0][4] = cv::Point(19 * W / 32, 3 * W / 8);
rook_points[0][5] = cv::Point(3 * W / 4, 3 * W / 8);
rook_points[0][6] = cv::Point(3 * W / 4, W / 8);
rook_points[0][7] = cv::Point(26 * W / 40, W / 8);
rook_points[0][8] = cv::Point(26 * W / 40, W / 4);
rook_points[0][9] = cv::Point(22 * W / 40, W / 4);
rook_points[0][10] = cv::Point(22 * W / 40, W / 8);
rook_points[0][11] = cv::Point(18 * W / 40, W / 8);
rook_points[0][12] = cv::Point(18 * W / 40, W / 4);
rook_points[0][13] = cv::Point(14 * W / 40, W / 4);
rook_points[0][14] = cv::Point(14 * W / 40, W / 8);
rook_points[0][15] = cv::Point(W / 4, W / 8);
rook_points[0][16] = cv::Point(W / 4, 3 * W / 8);
rook_points[0][17] = cv::Point(13 * W / 32, 3 * W / 8);
rook_points[0][18] = cv::Point(5 * W / 16, 13 * W / 16);
rook_points[0][19] = cv::Point(W / 4, 13 * W / 16);
const cv::Point* ppt[1] = { rook_points[0] };
int npt[] = { 20 };
cv::Scalar color(255, 255, 255);
int ncontours = 1;
int lineType = cv::LINE_8;
cv::fillPoly(img, ppt, npt, ncontours, color, lineType);
}
/*绘制直线*/
void MyLine(cv::Mat img, cv::Point start, cv::Point end)
{
int thickness = 2;
int lineType = cv::LINE_8;
cv::Scalar color(0, 0, 0);
cv::line(img, start, end, color, thickness, lineType);
}
结果如下:
官方的第二个例子:
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
int imgIndex = 1;
std::string imgName;
const int NUMBER = 5; // 每种图形绘制的个数
const int DELAY = 5; // 延迟时间
const int window_width = 900; // 图像尺寸
const int window_height = 600;
int x_1 = -window_width / 2;
int x_2 = window_width * 3 / 2;
int y_1 = -window_width / 2;
int y_2 = window_width * 3 / 2;
static cv::Scalar randomColor(cv::RNG& rng); // 产生随机颜色
int Drawing_Random_Lines(cv::Mat image, char* window_name, cv::RNG rng);
int Drawing_Random_Rectangles(cv::Mat image, char* window_name, cv::RNG rng);
int Drawing_Random_Ellipses(cv::Mat image, char* window_name, cv::RNG rng);
int Drawing_Random_Polylines(cv::Mat image, char* window_name, cv::RNG rng);
int Drawing_Random_Filled_Polygons(cv::Mat image, char* window_name, cv::RNG rng);
int Drawing_Random_Circles(cv::Mat image, char* window_name, cv::RNG rng);
int Displaying_Random_Text(cv::Mat image, char* window_name, cv::RNG rng);
int Displaying_Big_End(cv::Mat image, char* window_name, cv::RNG rng);
int main(void)
{
int c;
char window_name[] = "Drawing_2 Tutorial";
cv::RNG rng(0xFFFFFFFF); // 获取随机对象
cv::Mat image = cv::Mat::zeros(window_height, window_width, CV_8UC3);
cv::imshow(window_name, image);
cv::waitKey(DELAY);
c = Drawing_Random_Lines(image, window_name, rng);
if (c != 0) return 0;
c = Drawing_Random_Rectangles(image, window_name, rng);
if (c != 0) return 0;
c = Drawing_Random_Ellipses(image, window_name, rng);
if (c != 0) return 0;
c = Drawing_Random_Polylines(image, window_name, rng);
if (c != 0) return 0;
c = Drawing_Random_Filled_Polygons(image, window_name, rng);
if (c != 0) return 0;
c = Drawing_Random_Circles(image, window_name, rng);
if (c != 0) return 0;
c = Displaying_Random_Text(image, window_name, rng);
if (c != 0) return 0;
c = Displaying_Big_End(image, window_name, rng);
if (c != 0) return 0;
cv::waitKey(0);
return 0;
}
/*产生随机颜色*/
static cv::Scalar randomColor(cv::RNG& rng)
{
int icolor = (unsigned)rng; // 返回一个[0, 0xFFFFFFFF] 之间的随机整数
return cv::Scalar(icolor & 255, (icolor >> 8) & 255, (icolor >> 16) & 255);
}
/*绘制随机颜色的线段*/
int Drawing_Random_Lines(cv::Mat image, char* window_name, cv::RNG rng)
{
cv::Point pt1, pt2;
for (int i = 0; i < NUMBER; i++) {
pt1.x = rng.uniform(x_1, x_2); // 返回[x_1, x_2] 之间的一个均匀分布的随机数
pt1.y = rng.uniform(y_1, y_2);
pt2.x = rng.uniform(x_1, x_2);
pt2.y = rng.uniform(y_1, y_2);
cv::line(image, pt1, pt2, randomColor(rng), rng.uniform(1, 10), 8);
cv::imshow(window_name, image);
std::stringstream ss;
ss << imgIndex++;
imgName = "img" + ss.str() + ".jpg";
cv::imwrite(imgName, image);
if (cv::waitKey(DELAY) >= 0) return -1; // 在延迟时间内,没有按下按键
}
return 0;
}
/*绘制随机颜色的矩形*/
int Drawing_Random_Rectangles(cv::Mat image, char* window_name, cv::RNG rng)
{
cv::Point pt1, pt2;
int lineType = 8;
int thickness = rng.uniform(-3, 10);
for (int i = 0; i < NUMBER; i++) {
pt1.x = rng.uniform(x_1, x_2);
pt1.y = rng.uniform(y_1, y_2);
pt2.x = rng.uniform(x_1, x_2);
pt2.y = rng.uniform(y_1, y_2);
cv::rectangle(image, pt1, pt2, randomColor(rng), MAX(thickness, -1), lineType);
cv::imshow(window_name, image);
std::stringstream ss;
ss << imgIndex++;
imgName = "img" + ss.str() + ".jpg";
cv::imwrite(imgName, image);
if (cv::waitKey(DELAY) >= 0) return -1;
}
return 0;
}
/*绘制椭圆形*/
int Drawing_Random_Ellipses(cv::Mat image, char* window_name, cv::RNG rng)
{
int lineType = 8;
for (int i = 0; i < NUMBER; i++) {
cv::Point center;
center.x = rng.uniform(x_1, x_2);
center.y = rng.uniform(y_1, y_2);
cv::Size axes;
axes.width = rng.uniform(0, 200);
axes.height = rng.uniform(0, 200);
double angle = rng.uniform(0, 180);
cv::ellipse(image, center, axes, angle, angle - 100, angle + 200, randomColor(rng), rng.uniform(-1, 9), lineType);
cv::imshow(window_name, image);
std::stringstream ss;
ss << imgIndex++;
imgName = "img" + ss.str() + ".jpg";
cv::imwrite(imgName, image);
if (cv::waitKey(DELAY) >= 0) return -1;
}
return 0;
}
/*绘制多边形*/
int Drawing_Random_Polylines(cv::Mat image, char* window_name, cv::RNG rng)
{
int lineType = 8;
for (int i = 0; i< NUMBER; i++) {
cv::Point pt[2][3];
pt[0][0].x = rng.uniform(x_1, x_2);
pt[0][0].y = rng.uniform(y_1, y_2);
pt[0][1].x = rng.uniform(x_1, x_2);
pt[0][1].y = rng.uniform(y_1, y_2);
pt[0][2].x = rng.uniform(x_1, x_2);
pt[0][2].y = rng.uniform(y_1, y_2);
pt[1][0].x = rng.uniform(x_1, x_2);
pt[1][0].y = rng.uniform(y_1, y_2);
pt[1][1].x = rng.uniform(x_1, x_2);
pt[1][1].y = rng.uniform(y_1, y_2);
pt[1][2].x = rng.uniform(x_1, x_2);
pt[1][2].y = rng.uniform(y_1, y_2);
const cv::Point* ppt[2] = { pt[0], pt[1] };
int npt[] = { 3, 3 };
cv::polylines(image, ppt, npt, 2, true, randomColor(rng), rng.uniform(1, 10), lineType);
cv::imshow(window_name, image);
std::stringstream ss;
ss << imgIndex++;
imgName = "img" + ss.str() + ".jpg";
cv::imwrite(imgName, image);
if (cv::waitKey(DELAY) >= 0) return -1;
}
return 0;
}
/*绘制填充的多边形*/
int Drawing_Random_Filled_Polygons(cv::Mat image, char* window_name, cv::RNG rng)
{
int lineType = 8;
for (int i = 0; i < NUMBER; i++) {
cv::Point pt[2][3];
pt[0][0].x = rng.uniform(x_1, x_2);
pt[0][0].y = rng.uniform(y_1, y_2);
pt[0][1].x = rng.uniform(x_1, x_2);
pt[0][1].y = rng.uniform(y_1, y_2);
pt[0][2].x = rng.uniform(x_1, x_2);
pt[0][2].y = rng.uniform(y_1, y_2);
pt[1][0].x = rng.uniform(x_1, x_2);
pt[1][0].y = rng.uniform(y_1, y_2);
pt[1][1].x = rng.uniform(x_1, x_2);
pt[1][1].y = rng.uniform(y_1, y_2);
pt[1][2].x = rng.uniform(x_1, x_2);
pt[1][2].y = rng.uniform(y_1, y_2);
const cv::Point* ppt[2] = { pt[0], pt[1] };
int npt[] = { 3, 3 };
cv::fillPoly(image, ppt, npt, 2, randomColor(rng), lineType);
cv::imshow(window_name, image);
std::stringstream ss;
ss << imgIndex++;
imgName = "img" + ss.str() + ".jpg";
cv::imwrite(imgName, image);
if (cv::waitKey(DELAY) >= 0) return -1;
}
return 0;
}
/*绘制随机的圆形*/
int Drawing_Random_Circles(cv::Mat image, char* window_name, cv::RNG rng)
{
int lineType = 8;
for (int i = 0; i < NUMBER; i++) {
cv::Point center;
center.x = rng.uniform(x_1, x_2);
center.y = rng.uniform(y_1, y_2);
cv::circle(image, center, rng.uniform(0, 300), randomColor(rng), rng.uniform(-1, 9), lineType);
cv::imshow(window_name, image);
std::stringstream ss;
ss << imgIndex++;
imgName = "img" + ss.str() + ".jpg";
cv::imwrite(imgName, image);
if (cv::waitKey(DELAY) >= 0) return -1;
}
return 0;
}
/*绘制随机的文字*/
int Displaying_Random_Text(cv::Mat image, char* window_name, cv::RNG rng)
{
int lineType = 8;
for (int i = 1; i < NUMBER; i++) {
cv::Point org;
org.x = rng.uniform(x_1, x_2);
org.y = rng.uniform(y_1, y_2);
cv::putText(image, "Testing text rendering", org, rng.uniform(0, 8),
rng.uniform(0, 100)*0.05 + 0.1, randomColor(rng), rng.uniform(1, 10), lineType);
cv::imshow(window_name, image);
std::stringstream ss;
ss << imgIndex++;
imgName = "img" + ss.str() + ".jpg";
cv::imwrite(imgName, image);
if (cv::waitKey(DELAY) >= 0) return -1;
}
return 0;
}
/*绘制结束语*/
int Displaying_Big_End(cv::Mat image, char* window_name, cv::RNG rng)
{
cv::Size textsize = cv::getTextSize("OpenCV forever!", cv::FONT_HERSHEY_COMPLEX, 3, 5, 0);
cv::Point org((window_width - textsize.width) / 2, (window_height - textsize.height) / 2);
int lineType = 8;
cv::Mat image2;
for (int i = 0; i < 255; i += 2) {
image2 = image - cv::Scalar::all(i);
cv::putText(image2, "OpenCV forever!", org, cv::FONT_HERSHEY_COMPLEX, 3,
cv::Scalar(i, i, 255), 5, lineType);
cv::imshow(window_name, image2);
if (cv::waitKey(DELAY) >= 0) return -1;
}
std::stringstream ss;
ss << imgIndex++;
imgName = "img" + ss.str() + ".jpg";
cv::imwrite(imgName, image2);
return 0;
}
运行结果如下: