基本图形绘制

基本图形的绘制函数


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;
}

运行结果如下:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值