轮廓图像与 Canny 图像的区别

一个轮廓一般对应一系列的点,也就是图像中的一条曲线。轮廓图像和 Canny 图像乍看起来表现几乎是一致的,但其实组成两者的数据结构差别很大:

  • Canny 边缘图像是一个点的集合,点与点之间没有联系。

  • 轮廓图像是一个点集的集合,每个点集(即轮廓)内的点都是相邻的,点集与点集之间也存在前后、父内等关系。

寻找轮廓:findContours 函数

findContours 函数用于在二值图像中寻找轮廓。

void findContours(InputArray image, OutputArrays contours, OutputArray hierarchy, int mode, int method, Point offset = Point());

  • image,输入图像,即源图像,填 Mat 类的对象即可,可以是灰度图(非零像素被视为 1),但更常用的是二值图像,一般是经过Canny、拉普拉斯等边缘检测算子处理过的二值图像。
  • contours,检测到的所有轮廓均会被存在这里。每个轮廓为一个点集,用 Point 类型的 vector 表示。所以会被定义为

vector<vector<Point> > contours

  • hierarchy,每个轮廓 contours[i] 对应四个 hierarchy[i][0] ~ hierarchy[i][3],分别表示与当前轮廓平级的后一个轮廓的的索引编号、与当前轮廓平级的前一个轮廓的索引编号、当前轮廓的子轮廓的索引编号、当前轮廓的父轮廓的索引编号。如果没有对应项,hierarchy[i][x] = -1。
  • mode,轮廓检索模式,取值如下:

标识符 含义
RETR_EXTERNAL

只检测最外层轮廓,包含在外围轮廓内的内围轮廓被忽略。不存在父轮廓或内嵌轮廓

(hierarchy[i][2] = hierarchy[i][3] = -1)。

RETR_LIST

提取所有轮廓,并且放置在 list 中。不存在父轮廓或内嵌轮廓

(hierarchy[i][2] = hierarchy[i][3] = -1)。

再举个例子:

RETR_CCOMP

提取所有轮廓,无论嵌套个数多少,都将其组织为双层结构(外层、内层)。

再举个例子:

RETR_TREE

提取所有轮廓,并建立网状的轮廓结构(最外层轮廓为根)。

再举个例子:

  • method,轮廓的近似办法,取值如下:
标识符 含义
CHAIN_APPROX_NONE 获取每个轮廓的每个像素,相邻的两个像素位差不超过 1 像素。
CHAIN_APPROX_SIMPLE 仅保存轮廓的拐点信息,拐点与拐点之间直线段上的信息点不予保留。例如一个矩形轮廓只需 4 个点来保留轮廓信息。

CHAIN_APPROX_TC89_L1

CHAIN_APPROX_TC89_KCOS

使用 teh-Chinl chain 近似算法。
  • offset,所有的轮廓信息相对于原始图像对应点的偏移量,相当于在每一个检测出的轮廓点上加上该偏移量,有默认值 Point() 。对 ROI 区域(感兴趣区域)中找出的轮廓,并要在整个图像中进行分析时,这个参数便可派上用场。

绘制轮廓:drawContours 函数

void drawContours(InputOutputArray image, InputOutputArrays contours, int contourIdx, const Scalar& color, int thickness = 1, int lineType = 8, InputArray hierarchy = noArray(), int maxLevel = INT_MAX, Point offset = Point());

  • image,目标图像,填 Mat 类对象即可。
  • contours,输入的轮廓,每个轮廓都是一组点集,可用 Point 类型的 vector 表示。
  • contourIdx,轮廓的索引编号。若为负值,则绘制所有轮廓。
  • color,轮廓颜色。
  • thickness,轮廓线条的粗细程度,有默认值 1。若其为负值,便会填充轮廓内部空间。
  • lineType,线条的类型,有默认值 8。可去类型如下:
类型 含义
8 8 连通线型
4 4 连通线型
LINE_AA 抗锯齿线型
  • hierarchy,可选的层次结构信息,有默认值 noArray()。
  • maxLevel,用于绘制轮廓的最大等级,有默认值 INT_MAX。
  • offset,轮廓信息相对于目标图像对应点的偏移量,相当于在每一个轮廓点上加上该偏移量,有默认值 Point() 。在 ROI 区域(感兴趣区域)绘制轮廓时,这个参数便可派上用场。

代码示例:

  1. #include<opencv.hpp>
  2. #include<iostream>
  3. #include<vector>
  4. using namespace std;
  5. using namespace cv;
  6. int main() {
  7. Mat src = imread("C:/Users/齐明洋/Desktop/3.jpg");
  8. imshow("src", src);
  9.  
  10. Mat canny_img;
  11. Canny(src, canny_img, , , );
  12. //闭操作,先膨胀后腐蚀,可消除小黑点
  13. Mat kernel = getStructuringElement(MORPH_RECT, Size(, ));
  14. morphologyEx(canny_img, canny_img, MORPH_CLOSE, kernel);
  15. imshow("canny_img", canny_img);
  16.  
  17. Mat dst = Mat(src.rows, src.cols, CV_8UC3, Scalar(, , ));
  18. vector<vector<Point> >contours;
  19.  
  20. ////写法一
  21. //vector<Vec4i>hierarchy;
  22. //findContours(canny_img, contours,hierarchy, RETR_TREE, CHAIN_APPROX_NONE);
  23. //for (int i = 0; i < contours.size(); i++) {
  24. // drawContours(dst, contours, i, Scalar(0, 0, 255), 1, 8, hierarchy);
  25. //}
  26.  
  27. //写法二
  28. findContours(canny_img, contours, RETR_TREE, CHAIN_APPROX_NONE);
  29. drawContours(dst, contours, -, Scalar(, , ), );
  30.  
  31. imshow("dst", dst);
  32.  
  33. waitKey();
  34. }

效果演示:

借鉴博客:https://www.cnblogs.com/GaloisY/p/11062065.html

https://blog.csdn.net/qq_35239859/article/details/99676501

opencv —— findContours、drawContours 寻找并绘制轮廓的更多相关文章

  1. opencv 6 图像轮廓与图像分割修复 1 查找并绘制轮廓 寻找物体的凸包

    查找并绘制轮廓 寻找轮廓(findContours)函数 绘制轮廓(drawContours()函数) 基础实例程序:轮廓查找 #include <opencv2/opencv.hpp> ...

  2. 查找并绘制轮廓[OpenCV 笔记XX]

    好久没有更新了,原谅自己放了个假最近又在赶进度,所以...更新的内容是很靠后的第八章,因为最近工作要用就先跳了,后面会更新笔记编号...加油加油! 在二值图像中寻找轮廓 void cv::findCo ...

  3. 机器学习进阶-图像金字塔与轮廓检测-轮廓检测 1.cv2.cvtColor(图像颜色转换) 2.cv2.findContours(找出图像的轮廓) 3.cv2.drawContours(画出图像轮廓) 4.cv2.contourArea(轮廓面积) 5.cv2.arcLength(轮廓周长) 6.cv2.aprroxPloyDP(获得轮廓近似) 7.cv2.boudingrect(外接圆)..

    1. cv2.cvtcolor(img, cv2.COLOR_BGR2GRAY) # 将彩色图转换为灰度图 参数说明: img表示输入的图片, cv2.COLOR_BGR2GRAY表示颜色的变换形式 ...

  4. 【OpenCV函数】轮廓提取;轮廓绘制;轮廓面积;外接矩形

    FindContours 在二值图像中寻找轮廓  int cvFindContours( CvArr* image, CvMemStorage* storage, CvSeq** first_cont ...

  5. OpenCV探索之路(十一):轮廓查找和多边形包围轮廓

    Canny一类的边缘检测算法可以根据像素之间的差异,检测出轮廓边界的像素,但它没有将轮廓作为一个整体.所以要将轮廓提起出来,就必须将这些边缘像素组装成轮廓. OpenCV中有一个很强大的函数,它可以从 ...

  6. Python+OpenCV图像处理(十六)—— 轮廓发现

    简介:轮廓发现是基于图像边缘提取的基础寻找对象轮廓的方法,所以边缘提取的阈值选定会影响最终轮廓发现结果. 代码如下: import cv2 as cv import numpy as np def c ...

  7. OpenCV应用(3) 简单轮廓匹配的小例子

    具体应用 https://blog.csdn.net/kyjl888/article/details/85060883 OpenCV中提供了几个与轮廓相关的函数: findContours():从二值 ...

  8. Python 图像处理 OpenCV (15):图像轮廓

    前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...

  9. 第十七节,OpenCV(学习六)图像轮廓检测

    1.检测轮廓 轮廓检测是图像处理中经常用到的,OpenCV-Python接口中使用cv2.findContours()函数查找检测物体的轮廓. cv2.findContours(image, mode ...

随机推荐

  1. 调用Excel.Application报错的解决方法

    之前由于装了WPS后,VBA和python调用某些OFFICE的端口一直报错.网上找了无数的解决办法.也没有解决. 将注册表清理.不行. 将WPS卸载.不行. 将office重装.不行. 之后找到了个 ...

  2. test api formdata

  3. Java容器解析系列(15) HashTable Dictionary & Properties

    HashTable的实现原理与HashMap没有什么区别; 其与HashMap的主要区别如下: 添加进入jdk时间:HashTable在jdk1.0时添加,HashMap在jdk1.2时添加; 类签名 ...

  4. Shrio | java.io.IOException: Resource [classpath:shiro.ini] could not be found

    案例 今天项目启动时一直报异常,看了错误日志发现是shrio文件找不到引起的,异常: java.io.IOException: Resource [classpath:shiro.ini] could ...

  5. WPF另类实现摄像头录像

    WPF中使用第三方控件来直接进行录像的控件没有找到(aforgenet好像不维护了?WPFMediaKit好像只能实现摄像头拍照.收费的控件没有使用,不做评论.) 通过百度(感谢:https://ww ...

  6. 构建一个学生Student,根据类Student的定义,创建五个该类的对象,输出每个学生的信息,计算并输出这五个学生Java语言成绩的平均值,以及计算并输出他们Java语言成绩的最大值和最小值。

    定义一个表示学生信息的类Student,要求如下: (1)类Student的成员变量: sNO 表示学号: sName表示姓名: sSex表示性别: sAge表示年龄: sJava:表示Java课程成 ...

  7. LUA学习笔记(第1-4章)

    需要一种简单的脚本语言来代替批处理,它需要足够小巧,同时功能上也应该足够强劲,自然选择了LUA语言. 第一章 Hello World print('Hello World') print(" ...

  8. C语言的puts(),gets(),putchar(),getchar()

    其实puts(),gets()属于字符串输入函数. putchar()与getchar()属于字符输入函数. 1.字符函数 #include<stdio.h> int main(){ ch ...

  9. POJ_1042_贪心

    题目描述: 每组数据给你n个胡,h小时时间,每个湖一次可钓鱼数量,每个湖每次钓鱼后下次可钓鱼数量的减少量,从每个湖到下一个湖所需时间.求最大钓鱼量. 要注意的是,刚开始在第一个湖,每次移动只能往下一个 ...

  10. Codeforces_540_C

    http://codeforces.com/problemset/problem/540/C 简单bfs,注意结束条件. #include<iostream> #include<cs ...