OpenCV绘制图形功能

本文实例为大家分享了OpenCV绘制图形功能的具体代码,供大家参考,具体内容如下

1、绘制直线

绘制直线函数是cv::line,函数完整形式如下

void line(InputOutputArray img, Point pt1, Point pt2, const Scalar& color, int thickness = 1, int lineType = LINE_8, int shift = 0);
/*
@param img 图像
@param pt1 线段端点1
@param pt2 线段端点2
@param color 线段颜色
@param thickness 线宽
@param lineType 线的类型
@param shift 点坐标的小数位偏移
*/

color可以使用cv::Scalar构造,但是传入参数的顺序是BGR,使用CV_RGB宏更直观,以RGB顺序传入;

lineType取值有LINE_4、LINE_8和LINE_AA,分别表示4连接线,8连接线,抗锯齿线,是以不同的算法产生直线(也可以是FILLED=-1,直接填充);

shift是指点坐标的二进制表示的位偏移,每加1坐标值减一半,实验的结果,不知道理解的对不对,使用默认值0就可以了;

在两个点之间绘制线宽为1的红色直线定义为一个函数

void DrawLine(const cv::Mat& destImg, const cv::Point& pt1, const cv::Point& pt2)
{
    cv::line(destImg, pt1, pt2, CV_RGB(255, 0, 0), 1);
}

下面的实例在鼠标两次点击位置中间画一根直线,绘制完成可以按Enter键保存图像。

cv::Mat g_originImage;//原始图像
cv::Mat g_editImage;//编辑的图像
std::vector<cv::Point> g_editPoints;//正在绘制的图形的点
std::vector<std::vector<cv::Point>> g_lines;//所有的线段
 
void RedrawAllLines()
{
    g_originImage.copyTo(g_editImage);//恢复背景图像
    for (int i = 0; i < g_lines.size(); i++)
    {
        if (g_lines[i].size() >= 2)
        {
            DrawLine(g_editImage,g_lines[i][0], g_lines[i][1]);
        }
    }
}
void OnDrawLineMouseEvent(int event, int x, int y, int flags, void* userdata)
{
    if (event == cv::EVENT_LBUTTONDOWN)
    {
        if (g_editPoints.size() > 0)
        {
            //在第二个点按下鼠标之后添加到线段列表中,并重绘图像
            g_editPoints.push_back(cv::Point(x, y));
            g_lines.push_back(g_editPoints);
            RedrawAllLines();
            g_editPoints.clear();
            imshow("image", g_editImage);
        }
        else
        {
            g_editPoints.push_back(cv::Point(x, y));//第一个点
        }
    }
    else if (event == cv::EVENT_MOUSEMOVE)
    {
        if (g_editPoints.size() > 0)
        {
            //鼠标移动中,绘制到鼠标位置的直线,但鼠标当前点不加入到g_editPoints中
            RedrawAllLines();
            DrawLine(g_editImage,g_editPoints[g_editPoints.size() - 1], cv::Point(x, y));
            imshow("image", g_editImage);
        }
    }
}
 
int main(int argc, char **arv)
{
    g_originImage = cv::imread("walkers.jpg");
    g_originImage.copyTo(g_editImage);
    cv::namedWindow("image");
    imshow("image", g_editImage);
    cv::setMouseCallback("image", OnDrawLineMouseEvent);
    int key = cv::waitKey(0);
    while (key != 27)
    {
        if (key == 13)
        {
            cv::imwrite("testsave.png", g_editImage);
        }
        key = cv::waitKey(0);
    }
    return 0;
}

2、绘制圆

绘制圆的函数cv::circle

void circle(InputOutputArray img, Point center, int radius,const Scalar& color, int thickness = 1,int lineType = LINE_8, int shift = 0);
/*
@param img 图像
@param center 圆心
@param radius 半径
@param color 线颜色
@param thickness 线宽,如果小于0则填充圆
@param lineType 线类型
@param shift 圆心和半径值的位偏移
*/

以两个点画一个圆,第一个点为圆心,两点距离为圆半径,定义为一个函数DrawCircle

void DrawCircle(const cv::Mat& destImg, const cv::Point& pt1, const cv::Point& pt2)
{
    cv::Point deltaPt = pt2 - pt1;
    float radius = cv::sqrt(deltaPt.x*deltaPt.x + deltaPt.y*deltaPt.y);
    cv::circle(destImg, pt1, radius, CV_RGB(255, 0, 0), 1);
}

以下示例实现鼠标点击两次绘制如上的一个圆,main函数与画直线一样,只要将鼠标事件回调改成OnDrawCircleMouseEvent

std::vector<std::vector<cv::Point>> g_circles;//所有的圆
 
void RedrawAllCircles()
{
    g_originImage.copyTo(g_editImage);//恢复背景图像
    for (int i = 0; i < g_circles.size(); i++)
    {
        if (g_circles[i].size() >= 2)
        {
            DrawCircle(g_editImage, g_circles[i][0], g_circles[i][1]);
        }
    }
}
void OnDrawCircleMouseEvent(int event, int x, int y, int flags, void* userdata)
{
    if (event == cv::EVENT_LBUTTONDOWN)
    {
        if (g_editPoints.size() > 0)
        {
            g_editPoints.push_back(cv::Point(x, y));
            g_circles.push_back(g_editPoints);
            RedrawAllCircles();
            g_editPoints.clear();
            imshow("image", g_editImage);
        }
        else
        {
            g_editPoints.push_back(cv::Point(x, y));//第一个点
        }
    }
    else if (event == cv::EVENT_MOUSEMOVE)
    {
        if (g_editPoints.size() > 0)
        {
            RedrawAllCircles();
            DrawCircle(g_editImage, g_editPoints[g_editPoints.size() - 1], cv::Point(x, y));
            imshow("image", g_editImage);
        }
    }
}

3、绘制椭圆

绘制椭圆的函数cv::ellipse,有两种形式,其中一个定义如下

void ellipse(InputOutputArray img, const RotatedRect& box, const Scalar& color,int thickness = 1, int lineType = LINE_8);
/*
@param img 图像
@param box 可以调整旋转角度的矩形
@param color 线颜色
@param thickness 线宽,如果小于0则填充椭圆
@param lineType 线类型
*/

以两个点组成的矩形内画一个椭圆,定义为函数DrawEllipse,这里不考虑矩形的旋转,固定为0

void DrawEllipse(const cv::Mat& destImg, const cv::Point& pt1, const cv::Point& pt2)
{
    cv::Point2f center = cv::Point2f((pt1.x + pt2.x) / 2.0, (pt1.y + pt2.y) / 2.0);
    cv::Point2f size = cv::Point2f(cv::abs(pt2.x - pt1.x), cv::abs(pt2.y - pt1.y));
    cv::ellipse(destImg,cv::RotatedRect(center, size, 0),CV_RGB(255, 0, 0), 1);
}

以下示例实现在鼠标两次点击位置中间画一个椭圆,main函数与画直线一样,将鼠标事件回调改成OnDrawEllipseMouseEvent

std::vector<std::vector<cv::Point>> g_ellipses;//所有的椭圆
void RedrawAllEllipses()
{
    g_originImage.copyTo(g_editImage);//恢复背景图像
    for (int i = 0; i < g_ellipses.size(); i++)
    {
        if (g_ellipses[i].size() >= 2)
        {
            DrawEllipse(g_editImage, g_ellipses[i][0], g_ellipses[i][1]);
        }
    }
}
void OnDrawEllipseMouseEvent(int event, int x, int y, int flags, void* userdata)
{
    if (event == cv::EVENT_LBUTTONDOWN)
    {
        if (g_editPoints.size() > 0)
        {
            g_editPoints.push_back(cv::Point(x, y));
            g_ellipses.push_back(g_editPoints);
            RedrawAllEllipses();
            g_editPoints.clear();
            imshow("image", g_editImage);
        }
        else
        {
            g_editPoints.push_back(cv::Point(x, y));//第一个点
        }
    }
    else if (event == cv::EVENT_MOUSEMOVE)
    {
        if (g_editPoints.size() > 0)
        {
            RedrawAllEllipses();
            DrawEllipse(g_editImage, g_editPoints[g_editPoints.size() - 1], cv::Point(x, y));
            imshow("image", g_editImage);
        }
    }
}

4、绘制矩形

绘制矩形的函数cv::rectangle,有两种形式,其中一个定义如下

void rectangle(InputOutputArray img, Rect rec,const Scalar& color, int thickness = 1,int lineType = LINE_8, int shift = 0);
/*
@param img 图像
@param rec 矩形坐标
@param color 线颜色
@param thickness 线宽,如果小于0则填充椭圆
@param lineType 线类型
@param shift  点坐标位偏移
*/

在两个点间画一个矩形,定义为函数DrawRectangle

void DrawRectangle(const cv::Mat& destImg, const cv::Point& pt1, const cv::Point& pt2)
{
    cv::rectangle(destImg, cv::Rect(pt1, pt2), CV_RGB(255, 0, 0), 1);
}

以下示例实现在鼠标两次点击位置中间画一个矩形,main函数与画直线一样,将鼠标事件回调改成OnDrawRectangleMouseEvent

 std::vector<std::vector<cv::Point>> g_rectangles;//所有的矩形
void RedrawAllRectangles()
{
    g_originImage.copyTo(g_editImage);//恢复背景图像
    for (int i = 0; i < g_rectangles.size(); i++)
    {
        if (g_rectangles[i].size() >= 2)
        {
            DrawRectangle(g_editImage, g_rectangles[i][0], g_rectangles[i][1]);
        }
    }
}
void OnDrawRectangleMouseEvent(int event, int x, int y, int flags, void* userdata)
{
    if (event == cv::EVENT_LBUTTONDOWN)
    {
        if (g_editPoints.size() > 0)
        {
            g_editPoints.push_back(cv::Point(x, y));
            g_rectangles.push_back(g_editPoints);
            RedrawAllRectangles();
            g_editPoints.clear();
            imshow("image", g_editImage);
        }
        else
        {
            g_editPoints.push_back(cv::Point(x, y));//第一个点
        }
    }
    else if (event == cv::EVENT_MOUSEMOVE)
    {
        if (g_editPoints.size() > 0)
        {
            RedrawAllRectangles();
            DrawRectangle(g_editImage, g_editPoints[g_editPoints.size() - 1], cv::Point(x, y));
            imshow("image", g_editImage);
        }
    }
}

5、绘制多边形轮廓

绘制多边形的函数cv::polylines,有两种形式,其中一个定义如下

void polylines(InputOutputArray img, InputArrayOfArrays pts,bool isClosed, const Scalar& color,int thickness = 1, int lineType = LINE_8, int shift = 0 );
/*
@param img 图像
@param pts 多边形坐标数组
@param isClosed 是否绘制闭合多边形
@param color 线颜色
@param thickness 线宽
@param lineType 线类型
@param shift  点坐标位偏移
*/

这里的pts是一个2维数组,表示多个多边形,以下分别实现绘制多个多边形和单个多边形的函数

void DrawMultiPolys(const cv::Mat& destImg, const std::vector<std::vector<cv::Point>>& points, bool bClose)
{
    cv::polylines(destImg, points, bClose, CV_RGB(255, 0, 0), 1);
}
void DrawOnePoly(const cv::Mat& destImg, const std::vector<cv::Point>& points,bool bClose)
{
    if (points.size() >= 2)
    {
        std::vector<std::vector<cv::Point>> polyPoints;
        polyPoints.push_back(points);
        DrawMultiPolys(destImg,polyPoints,bClose);
    }
}

以下示例实现在鼠标多次点击的位置绘制多边形,main函数与画直线一样,将鼠标事件回调改成OnDrawPolyMouseEvent

std::vector<std::vector<cv::Point>> g_polys;//所有的多边形
void RedrawAllPolys()
{
    g_originImage.copyTo(g_editImage);//恢复背景图像
    DrawMultiPolys(g_editImage,g_polys,true);
}
void OnDrawPolyMouseEvent(int event, int x, int y, int flags, void* userdata)
{
    if (event == cv::EVENT_LBUTTONDOWN)
    {
        if (g_editPoints.size() > 0)
        {
            g_editPoints.push_back(cv::Point(x, y));
            RedrawAllPolys();
            DrawOnePoly(g_editImage, g_editPoints, false);//正在绘制的多边形要单独画,而且不能闭合
            imshow("image", g_editImage);
        }
        else
        {
            g_editPoints.push_back(cv::Point(x, y));//第一个点
        }
    }
    else if (event == cv::EVENT_MOUSEMOVE)
    {
        if (g_editPoints.size() > 0)
        {
            RedrawAllPolys();
            DrawOnePoly(g_editImage,g_editPoints,false);//正在绘制的多边形要单独画,而且不能闭合
            DrawLine(g_editImage, g_editPoints[g_editPoints.size() - 1], cv::Point(x, y));//绘制一根到鼠标位置的直线
            imshow("image", g_editImage);
        }
    }
    else if (event == cv::EVENT_RBUTTONDOWN)
    {
        //右键按下结束多边形绘制,加入到g_polys
        g_polys.push_back(g_editPoints);
        RedrawAllPolys();
        g_editPoints.clear();
        cv::imshow("image", g_editImage);
    }
}

6、绘制填充多边形

绘制填充多边形函数cv::fillPoly,有两种形式,其中一个定义如下

void fillPoly(InputOutputArray img, InputArrayOfArrays pts,const Scalar& color, int lineType = LINE_8, int shift = 0,Point offset = Point() );
/*
@param img 图像
@param pts 多边形坐标数组
@param color 线颜色
@param lineType 线类型
@param shift  点坐标位偏移
@param offset 所有多边形点的偏移
*/

绘制填充多边形与绘制多边形轮廓差不多,只要将polylines换成fillpoly

void DrawMultiPolys(const cv::Mat& destImg, const std::vector<std::vector<cv::Point>>& points)
{
    cv::fillPoly(destImg, points,CV_RGB(255, 0, 0));
}
void DrawOnePoly(const cv::Mat& destImg, const std::vector<cv::Point>& points)
{
    if (points.size() >= 2)
    {
        std::vector<std::vector<cv::Point>> polyPoints;
        polyPoints.push_back(points);
        DrawMultiPolys(destImg,polyPoints);
    }
}

如果将上面的所有功能以一定方式组合起来,就可以在图像上绘制多种形状图形并保存了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • C++ OpenCV绘制几何图形

    本文实例为大家分享了C++ OpenCV绘制几何图形的具体代码,供大家参考,具体内容如下 绘制几何图形 直线 矩形 多边形 圆形 椭圆 文字 API 直线 CV_EXPORTS_W void line(InputOutputArray img, Point pt1, Point pt2, const Scalar& color, int thickness = 1, int lineType = LINE_8, int shift = 0); 矩形 CV_EXPORTS_W void recta

  • 使用c++实现OpenCV绘制图形旋转矩形

    目录 功能函数 // 绘制旋转矩形 void DrawRotatedRect(cv::Mat mask,const cv::RotatedRect &rotatedrect,const cv::Scalar &color,int thickness, int lineType) { // 提取旋转矩形的四个角点 cv::Point2f ps[4]; rotatedrect.points(ps); // 构建轮廓线 std::vector<std::vector<cv::Poin

  • OpenCV 基本图形绘制函数详解

    用于绘制直线的line函数: 用于绘制椭圆的ellipse函数: 用于绘制矩形的rectangle函数: 用于绘制圆的circle函数: 用于绘制填充的多边形的fillPoly函数. #include <opencv2/core/core.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp> using namespace cv; using namespac

  • opencv3/C++绘制几何图形实例

    在图像上绘制几何图形 #include<iostream> #include<opencv2/opencv.hpp> using namespace cv; Mat src1, dst; void drawRectangle(); void drawLine(); void drawEllipse(); void drawCircle(); void tsxt(); int main() { src1 = imread("E:/image/image/daibola.jp

  • OpenCV绘制图形功能

    本文实例为大家分享了OpenCV绘制图形功能的具体代码,供大家参考,具体内容如下 1.绘制直线 绘制直线函数是cv::line,函数完整形式如下 void line(InputOutputArray img, Point pt1, Point pt2, const Scalar& color, int thickness = 1, int lineType = LINE_8, int shift = 0); /* @param img 图像 @param pt1 线段端点1 @param pt2

  • 使用c++实现OpenCV绘制旋转矩形图形

    目录 功能函数 测试代码 测试效果  功能函数 // 绘制旋转矩形 void DrawRotatedRect(cv::Mat mask,const cv::RotatedRect &rotatedrect,const cv::Scalar &color,int thickness, int lineType) { // 提取旋转矩形的四个角点 cv::Point2f ps[4]; rotatedrect.points(ps); // 构建轮廓线 std::vector<std::ve

  • Python OpenCV绘制各类几何图形详解

    目录 一.绘制直线 二.绘制矩形 三.绘制圆形 四.绘制椭圆 五.绘制多边形 六.绘制文字 七.总结 一.绘制直线 在OpenCV中,绘制直线需要获取直线的起点和终点坐标,调用cv2.line()函数实现该功能.该函数原型如下所示: img = line(img, pt1, pt2, color[, thickness[, lineType[, shift]]]) – img表示需要绘制的那幅图像 – pt1表示线段第一个点的坐标 – pt2表示线段第二个点的坐标 – color表示线条颜色,需

  • Python matplotlib绘制图形实例(包括点,曲线,注释和箭头)

    Python的matplotlib模块绘制图形功能很强大,今天就用pyplot绘制一个简单的图形,图形中包括曲线.曲线上的点.注释和指向点的箭头. 1. 结果预览: 2. 代码如下: from matplotlib import pyplot as plt import numpy as np # 绘制曲线 x = np.linspace(2, 21, 20) # 取闭区间[2, 21]之间的等差数列,列表长度20 y = np.log10(x) + 0.5 plt.figure() # 添加一

  • Python基于matplotlib实现绘制三维图形功能示例

    本文实例讲述了Python基于matplotlib实现绘制三维图形功能.分享给大家供大家参考,具体如下: 代码一: # coding=utf-8 import numpy as np import matplotlib.pyplot as plt import mpl_toolkits.mplot3d x,y = np.mgrid[-2:2:20j,-2:2:20j] #测试数据 z=x*np.exp(-x**2-y**2) #三维图形 ax = plt.subplot(111, project

  • Python使用matplotlib实现绘制自定义图形功能示例

    本文实例讲述了Python使用matplotlib实现绘制自定义图形功能.分享给大家供大家参考,具体如下: 一 代码 from matplotlib.path importPath from matplotlib.patches importPathPatch import matplotlib.pyplot as plt fig, ax = plt.subplots() #定义绘图指令与控制点坐标 #其中MOVETO表示将绘制起点移动到指定坐标 #CURVE4表示使用4个控制点绘制3次贝塞尔曲

  • Python实现的绘制三维双螺旋线图形功能示例

    本文实例讲述了Python实现的绘制三维双螺旋线图形功能.分享给大家供大家参考,具体如下: 代码: # -*- coding:utf-8 -*- #! python3 #绘制三维双螺旋线 import numpy as np import matplotlib.pyplot as plt import mpl_toolkits.mplot3d t=list(range(100,200)) r=[i*np.cos(60+i*360*5) for i in t] theta=[i*np.sin(60

  • python opencv常用图形绘制方法(线段、矩形、圆形、椭圆、文本)

    最近学了下 python opencv,分享下使用 opencv 在图片上绘制常用图形的方法. 案例中实现了在图片中添加线段.圆形.矩形.椭圆形以及添加文字的方法,使用 opencv2 实现的. 实现方法 1)画线段 cv.line 在图片中绘制一段直线 # 绘制线段 # 参数1:图片 # 参数2:起点 # 参数3:终点 # 参数4:BGR颜色 # 参数5:宽度 cv2.line(img, (60, 40), (90, 90), (255, 255, 255), 2); 参数说明 参数 值 说明

随机推荐