本文最后更新于:2024年5月7日 下午
虽然Canny.之类的边缘检测算法可以根据像素间的差异检测出轮廓边界的像素,但是它并没有将轮廓作为一个整体进行处理。下一步是要将这些边缘像素合成轮廓。本文记录 OpenCV 中的轮廓查找的相关操作。
轮廓查找概述
- 一个轮廓对应一系列点,这些点以某种方式表示图像中的一条曲线。在不同情况下,这种表示方式也有所不同。有多种方式可以表示一条曲线。
- OpenCV 中用一系列二维顶点表示一个轮廓
- 函数
cv2.findContours()
从二维图像中计算轮廓。它处理的图像可以是从cv2.Canny()
函数得到的有边缘像素的图像,或是从cv2.threshold()
及cv2.adaptiveThreshold()
函数得到的图像,这时边缘是正负区域之间的边界。
轮廓层次
- 在了解到底如何提取轮廓之前,有必要花一些时间来理解轮廓到底是什么以及一组轮廓之间如何互相关联。特别要注意轮廓树的概念,这对于理解其中一种最有效的方法
cv2.findContours()
非常重要。
- 上图为一张输入
cv2.findContours()
函数的测试图像(左图)。图中有五块颜色区域(分别标记为$A,B,C,D,E$), 每块区域的外部边界和内部边界都各自组成轮廓。因此共有9条轮廓。每条轮廓都由一组输出列表表示(右上角图一轮廓参数)。也可以选择生成一组层次表达(右下角图一层次参数)。在右下角的图中(对应构筑的轮廓树),每一个节点就是一条轮廓。根据每个节点在层次队列中的四元数组索引,图中的链接都做了相应标记。
cv2.findContours
找出二值图中的轮廓。
- 函数使用:
1 |
|
-
method:ContourApproximationModes
取值 含义 cv2.CHAIN_APPROX_NONE 存储了所有的轮廓点。也就是说,等高线的任意2个后续点$(x1,y1)$和$(x2,y2)$将是水平、垂直或对角线邻居,即$ max (abs (x1-x2),abs (y2-y1)) = 1$。 cv2.CHAIN_APPROX_SIMPLE 压缩水平、垂直和对角线段,只留下它们的端点。例如,一个直立的矩形轮廓用 4 个点进行编码。 cv2.CHAIN_APPROX_TC89_L1 运用了 Teh-Chin 连锁近似演算法的一种 cv2.CHAIN_APPROX_TC89_KCOS 运用了 Teh-Chin 连锁近似演算法的一种 -
mode: RetrievalModes
取值 含义 cv2.RETR_EXTERNAL 只检索最外层的轮廓。它为所有的轮廓设置层次$[i][2] = hierarchy [i][3] =-1$。 cv2.RETR_LIST 检索所有的轮廓,没有建立任何层次关系。 cv2.RETR_CCOMP 检索所有的轮廓,并把它们组织成一个两层的结构。在顶层,有组件的外部边界。在第二层,有洞的边界。如果在连接元件(图论)的洞里面还有一个等高线,它仍然被放在顶层。 cv2.RETR_TREE 检索所有轮廓并重建嵌套轮廓的完整层次结构。 cv2.RETR_FLOODFILL -
示例代码
1 |
|
绘制轮廓
获得一列轮廓后,一个最常用的功能是在屏幕上绘制检测到的轮廓。绘制轮廓可以用cv2.drawContours()
函数完成。
cv2.drawContours
绘制等高线轮廓或填充等高线。
- 函数使用
1 |
|
- 示例代码
1 |
|
快速连通区域分析
-
与轮廓分析紧密相关的另一种方法是连通区域分析。采用阈值化等方法分割一张图像后,我们可以采用连通区域分析来有效地对返回图像逐张分离和处理。 OpenCV中的连通区域分析算法,输入要求是一张二值(黑白)图像,输出是一张像素标记图,其中属于同一连通区域的非零像素都是同一定值。
-
可以调用 findcontours 函数之后再使用 drawcontours 函数填充,但是这样比较慢,原因如下:
-
cv2.findContours()
函数首先为每条轮廓分配一个独立的标准模板库向量, 而图像中可能存在上百、甚至上千条轮廓。之后当你想填充一块由一条或多条轮廓包围的非凸区域时,cv2.drawContours()
也很慢,而且需要收集所有包围该区域的小线段并排序。最后,收集一块连通区域的基本信息(例如一块区域或一个包围框)需要更多、更耗时的函数调用。
cv2.connectedComponents / cv2.connectedComponentsWithAlgorithm
计算布尔图像的连接组件标记图像
- 函数使用
1 |
|
-
ccltype:包含
cv2.CCL_DEFAULT
,cv2.CCL_WU
,cv2.CCL_GRANA
,cv2.CCL_BOLELLI
,cv2.CCL_SAUF
,cv2.CCL_BBDT
,cv2.CCL_SPAGHETTI
-
示例代码
1 |
|
参考资料
- 《学习 OpenCV3》 第十四章
文章链接:
https://www.zywvvd.com/notes/study/image-processing/opencv/opencv-outline/opencv-histogram/
“觉得不错的话,给点打赏吧 ୧(๑•̀⌄•́๑)૭”
微信支付
支付宝支付