AI学习者 · 2020年10月16日

技巧 | OpenCV中如何绘制与填充多边形

来源:OpenCV学堂

很多人都问过我这个问题,OpenCV中是怎么绘制与填充多边形的,特别是填充多边形的。因为根据OpenCV中的多边形绘制函数,他们发现这是一个无解的问题。其实我在2017底做一个项目的时候当时会对得到的一个多边形边缘轮廓进行填充,我就发现OpenCV中的多边形绘制函数无法填充,但是其实换个函数就会顺利搞定,只是大家被OpenCV官方的教程误导思维定势,没有想到而已。下面我们就来详细说一下,OpenCV中的多边形绘制与填充问题。

多边形绘制

OpenCV中支持常见的点、线、圆、椭圆与矩形的绘制与填充都是通过设置thickness这个参数来实现绘制与填充,当thickness是正数的时就会绘制;当thickness为非正数时就会填充。但是对多边形来说,polylines函数把thickness设置为非正数就会直接报错,无法通过修改thickness完成填充,该函数只能实现绘制。

void cv::polylines(         InputOutputArray  img,         InputArrayOfArrays       pts,         bool        isClosed,         const Scalar &        color,         int   thickness = 1,         int   lineType = LINE_8,         int   shift = 0)

参数解释

  • img表示绘制画布,图像
  • pts表示多边形的点
  • isClosed表示是否闭合,默认闭合
  • color表示颜色
  • thickness表示线宽,必须是正数
  • lineType表示线渲染类型
  • shift表示相对位移

绘制一个多边形的代码演示如下:

 1Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3); 2int w = canvas.cols; 3int h = canvas.rows; 4Point p1(100, 100); 5Point p2(300, 150); 6Point p3(300, 350); 7Point p4(250, 450); 8Point p5(50, 450); 9std::vector<Point> pts;10pts.push_back(p1);11pts.push_back(p2);12pts.push_back(p3);13pts.push_back(p3);14pts.push_back(p4);15pts.push_back(p5);16polylines(canvas, pts, true, Scalar(0, 255, 0), 1, 8, 0);

随机拾取5个点的坐标,然后完成绘制运行结果如下:

640.png

填充多边形

OpenCV中可以完成多边形填充的函数有两个,第一个填充多边形的函数为:

1void cv::fillPoly(     2         InputOutputArray  img,3         InputArrayOfArrays       pts,4         const Scalar &        color,5         int   lineType = LINE_8,6         int   shift = 0,7         Point       offset = Point()8)

该函数参数跟polylines很相似,唯一没有的就是thickness跟isClose参数,该函数会完成一个多边形的填充操作。代码演示如下:

 1Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3); 2int w = canvas.cols; 3int h = canvas.rows; 4Point p1(100, 100); 5Point p2(300, 150); 6Point p3(300, 350); 7Point p4(250, 450); 8Point p5(50, 450); 9std::vector<Point> pts;10pts.push_back(p1);11pts.push_back(p2);12pts.push_back(p3);13pts.push_back(p3);14pts.push_back(p4);15pts.push_back(p5);16fillPoly(canvas, pts, Scalar(255, 0, 255), 8, 0);17polylines(canvas, pts, true, Scalar(0, 255, 255), 2, 8, 0);

640-1.png

第二个一次可以填充/绘制任意数目的多边形函数,该函数来自轮廓分析的轮廓绘制,因此很多人不会注意到它其实是一个很强悍的多边形填充与绘制函数,函数说明如下:

 1void cv::drawContours (         2    InputOutputArray  image, 3    InputArrayOfArrays  contours, 4    int   contourIdx, 5    const Scalar &        color, 6    int   thickness = 1, 7    int   lineType = LINE_8, 8    InputArray      hierarchy = noArray(), 9    int   maxLevel = INT_MAX,10    Point       offset = Point()11)

该函数功能比较强大,一次可以完成多个多边形的填充与绘制,它本质上把每个多边形的顶点集作为轮廓看待,可以很方便的完成轮廓的绘制与填充,跟点、线、圆、椭圆与矩形的绘制与填充一样,都是通过设置thickness这个参数来实现绘制与填充。只是在输入的时候需要适当改一下。参数controus表示的多个多边形点集合,contourIdx大于零表示绘制指定索引的轮廓,-1表示绘制全部,thickness正数表示绘制,非正数表示填充。就这样一个函数就可以轻松搞定多边形的填充与绘制。代码实现如下:

 1Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3); 2int w = canvas.cols; 3int h = canvas.rows; 4Point p1(100, 100); 5Point p2(300, 150); 6Point p3(300, 350); 7Point p4(250, 450); 8Point p5(50, 450); 9std::vector<Point> pts;10pts.push_back(p1);11pts.push_back(p2);12pts.push_back(p3);13pts.push_back(p3);14pts.push_back(p4);15pts.push_back(p5);16std::vector<std::vector<Point>> contours;17contours.push_back(pts);18drawContours(canvas, contours, 0, Scalar(0, 0, 255), -1, 8);19drawContours(canvas, contours, 0, Scalar(255, 0, 255), 2, 8);

运行结果如下:

640-2.png

推荐专栏文章

更多嵌入式AI算法部署等请关注极术嵌入式AI专栏
推荐阅读
关注数
16328
内容数
1218
嵌入式端AI,包括AI算法在推理框架Tengine,MNN,NCNN,PaddlePaddle及相关芯片上的实现。欢迎加入微信交流群,微信号:aijishu20(备注:嵌入式)
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息