一、背景
cv.findContours()中的mode有什么用?cv.findContours()中的mode hierarchy是什么?有什么效果?
阅读官方文档,熟悉cv.findContours(),
我们可以知道,mode指定的是轮廓索引方式。
那么有哪些索引方式呢?
这是定义在C++中的枚举类型,
将就参考一下
特别说明 ,FLOODFILL用的不多,本文咱不作探究;
有兴趣的朋友可以看看这个 In opencv’s findContours, what does cv.RETR_FLOODFILL do?
二、分析
光看mode的枚举,很难看出是什么意思,比如CCOMP,TREE,跟轮廓有什么关系?
下面我将一步步手工学习并比较其中的不同。
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
from enum import Enum
img = cv.imread('find_c.png', cv.IMREAD_COLOR)
_ret, img2 = cv.threshold(cv.cvtColor(img,cv.COLOR_BGR2GRAY), 0, 255, cv.THRESH_BINARY)
# enum cv::RetrievalModes {
# cv::RETR_EXTERNAL = 0,
# cv::RETR_LIST = 1,
# cv::RETR_CCOMP = 2,
# cv::RETR_TREE = 3,
# cv::RETR_FLOODFILL = 4
# }
# 本文主要对前四种mode进行演示
class Mode(Enum):
RETR_EXTERNAL = 0
RETR_LIST = 1
RETR_CCOMP = 2
RETR_TREE = 3
# Since opencv 3.2 source image is not modified by this function.
contours = [-1 for i in range(5)]
hierarchy = [-1 for i in range(5)]
drawImg = []
for i in range(4):
_img, contours[i], hierarchy[i] = cv.findContours(img2, i, cv.CHAIN_APPROX_NONE)
drawImg.append(
cv.cvtColor(
cv.drawContours(img.copy(), contours[i], -1, (0, 0, 255), thickness=5),
code=cv.COLOR_BGR2RGB)
)
plt.figure(0)
plt.subplot(231), plt.imshow(img, cmap='gray'), plt.title('Org'), plt.axis('off')
# 这个图像我本来就往黑白画的 所以二值化图像和原图像应该是一样的表现
plt.subplot(232), plt.imshow(img2, cmap='gray'), plt.title('BINARY'), plt.axis('off')
for i in range(4):
plt.subplot(233 + i), plt.imshow(drawImg[i]), plt.title(Mode(i).name), plt.axis('off')
我们可以看到,除了EXTERNAL是只检查外部轮廓之外,其他七个轮廓肉眼看起来都差不多。
阅读资料,发现应该是hierarchy存在不同。
检查hierarchy:
注:
hierarchy 共四个参数,分别是:
下一个 、前一个、第一个、父轮廓的索引的编号
- RETR_EXTERNAL
- 我们可以从 hierarchy中看出,只有三个轮廓 符合定义
- RETR_LIST
最后两个值都是-1,也不构成层次关系
- RETR_CCOMP
这个不太容易立交CCOMP的意义,
查了一些资料
retrieves all of the contours and organizes them into a two-level hierarchy. At the top level, there are external boundaries of the components. At the second level, there are boundaries of the holes. If there is another contour inside a hole of a connected component, it is still put at the top level…
大概就是说,建立了两个层次的轮廓,一个内轮廓,一个外轮廓。
- RETR_TREE
从这里来看,似乎不太明显,我决定再换一个具体代表性的图像来测试 RETR_TREE
这下子就可以清楚的看清楚树形是怎么回事了
画出来大概就是
主要注意的是,节点中数字只代表编号,不代表顺序,顺序需要有hierarchy的前几位定。
mode、 hierarchy的学习笔记大致如上,希望能够帮到您~