opencv —— findContours、drawContours 寻找并绘制轮廓
轮廓图像与 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 区域(感兴趣区域)绘制轮廓时,这个参数便可派上用场。
代码示例:
#include<opencv.hpp>
#include<iostream>
#include<vector>
using namespace std;
using namespace cv;
int main() {
Mat src = imread("C:/Users/齐明洋/Desktop/3.jpg");
imshow("src", src); Mat canny_img;
Canny(src, canny_img, , , );
//闭操作,先膨胀后腐蚀,可消除小黑点
Mat kernel = getStructuringElement(MORPH_RECT, Size(, ));
morphologyEx(canny_img, canny_img, MORPH_CLOSE, kernel);
imshow("canny_img", canny_img); Mat dst = Mat(src.rows, src.cols, CV_8UC3, Scalar(, , ));
vector<vector<Point> >contours; ////写法一
//vector<Vec4i>hierarchy;
//findContours(canny_img, contours,hierarchy, RETR_TREE, CHAIN_APPROX_NONE);
//for (int i = 0; i < contours.size(); i++) {
// drawContours(dst, contours, i, Scalar(0, 0, 255), 1, 8, hierarchy);
//} //写法二
findContours(canny_img, contours, RETR_TREE, CHAIN_APPROX_NONE);
drawContours(dst, contours, -, Scalar(, , ), ); imshow("dst", dst); waitKey();
}
效果演示:

借鉴博客:https://www.cnblogs.com/GaloisY/p/11062065.html
https://blog.csdn.net/qq_35239859/article/details/99676501
opencv —— findContours、drawContours 寻找并绘制轮廓的更多相关文章
- opencv 6 图像轮廓与图像分割修复 1 查找并绘制轮廓 寻找物体的凸包
查找并绘制轮廓 寻找轮廓(findContours)函数 绘制轮廓(drawContours()函数) 基础实例程序:轮廓查找 #include <opencv2/opencv.hpp> ...
- 查找并绘制轮廓[OpenCV 笔记XX]
好久没有更新了,原谅自己放了个假最近又在赶进度,所以...更新的内容是很靠后的第八章,因为最近工作要用就先跳了,后面会更新笔记编号...加油加油! 在二值图像中寻找轮廓 void cv::findCo ...
- 机器学习进阶-图像金字塔与轮廓检测-轮廓检测 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表示颜色的变换形式 ...
- 【OpenCV函数】轮廓提取;轮廓绘制;轮廓面积;外接矩形
FindContours 在二值图像中寻找轮廓 int cvFindContours( CvArr* image, CvMemStorage* storage, CvSeq** first_cont ...
- OpenCV探索之路(十一):轮廓查找和多边形包围轮廓
Canny一类的边缘检测算法可以根据像素之间的差异,检测出轮廓边界的像素,但它没有将轮廓作为一个整体.所以要将轮廓提起出来,就必须将这些边缘像素组装成轮廓. OpenCV中有一个很强大的函数,它可以从 ...
- Python+OpenCV图像处理(十六)—— 轮廓发现
简介:轮廓发现是基于图像边缘提取的基础寻找对象轮廓的方法,所以边缘提取的阈值选定会影响最终轮廓发现结果. 代码如下: import cv2 as cv import numpy as np def c ...
- OpenCV应用(3) 简单轮廓匹配的小例子
具体应用 https://blog.csdn.net/kyjl888/article/details/85060883 OpenCV中提供了几个与轮廓相关的函数: findContours():从二值 ...
- Python 图像处理 OpenCV (15):图像轮廓
前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...
- 第十七节,OpenCV(学习六)图像轮廓检测
1.检测轮廓 轮廓检测是图像处理中经常用到的,OpenCV-Python接口中使用cv2.findContours()函数查找检测物体的轮廓. cv2.findContours(image, mode ...
随机推荐
- POJ Expanding Rods
点击打开题目 题目大意 给定L,n,C,L为红色线段,L(1+n*C)为绿色弧,求两者中点的距离 二分圆心角度数,接下来就是几何的能力了 根据正弦定理,可得: Lsinθ=rsin(90°−θ) 则弧 ...
- php--->把json传来的stdClass Object类型转array
php把json传来的stdClass Object类型转array 1.Php中stdClass.object.array的概念 stdClass是PHP的一个基类,即一个空白的类,所有的类几乎都继 ...
- 安装MySQL出现[Errno 256] No more mirrors to try
今天安装数据库时出现错误提示,如下图: 解决办法如下: yum clean all #清除仓库缓存 yum makecache #将服务器包信息缓存到本地 然后再执行数据库安装指令 yum insta ...
- Java:谈谈控制线程的几种办法
目录 Java:谈谈控制线程的几种办法 join() sleep() 守护线程 主要方法 需要注意 优先级 弃用三兄弟 stop() resume suspend 中断三兄弟 interrupt() ...
- ROS之服务
服务(service)是另一种在节点之间传递数据的方法,服务其实就是同步的跨进程函数调用,它能够让一个节点调用运行在另一个节点中的函数. 我们就像之前消息类型一样定义这个函数的输入/输出.服务端(提供 ...
- 在VMware中如何清理多余的空间
问题描述 平时用的编程计算机只有250G空间,c盘和d盘,今天准备做实验,发现删除虚拟机中系统的内容不但没有减少空间,反而增加了,这时我意识到虚拟机内部可能与咱们想象的操作模式不一样. 解决办法 我的 ...
- nginx配置文件的通用语法介绍
nginx的配置文件是ascii文本文件. 比如http{ }这种的是指令块,include mime.types: 这种是指令,include是指令,mime.types指令的参数,指令和参数之 ...
- ORB-SLAM2 初体验 —— 配置安装
转载请注明出处,谢谢 原创作者:MingruiYU 原创链接:https://www.cnblogs.com/MingruiYu/p/12286752.html ORB-SLAM2作为目前应用最广泛的 ...
- lua学习之类型与值篇
类型与值 lua 是动态类型的语言 在语言中没有类型定义的语法 每个值都携带有它的类型信息 8种基础类型 用 type 可以返回这个值的类型的名称 将一个变量用于不同类型,通常会导致混乱的代码 但合理 ...
- 关于求最长子串,使得最大减最小小于k的问题-以POJ4003为例
问题 给出一个长度为\(n\)的序列\(a[i]\),有\(m\)次询问, 每次给你一个\(k\),让你求一个最长子串\([l,r]\),使得\(max_l^r\{a_i\}-min_l^r\{a_i ...

再举个例子:
再举个例子:
再举个例子: