当前位置:网站首页>(十二) findContours函数的hierarchy详解
(十二) findContours函数的hierarchy详解
2022-08-10 19:05:00 【恒友成】
欢迎访问个人网络日志知行空间
1.基本用法
获取对象的轮廓,一般最好先对图像进行灰度化再进行阈值处理,然后用来检测轮廓。
void cv::findContours(
InputOutputArray image,
OutputArrayOfArrays contours,
OutputArray hierarchy,
int mode,
int method,
Point offset = Point()
)
- image: 8位单通道图像
- contours: 检测到的轮廓,
vector<vector<cv::Point>>
- hierarchy: 检测到的轮廓之间的嵌套和邻近关系,
vector<cv::Vec4i>
- mode: 不同的轮廓检测算法,常用的有
RETR_EXTERNAL/RETR_LIST/RETR_CCOMP/RETR_TREE
四种 - method: 轮廓逼近方法,见,可使用更少的点表示轮廓,减少内存占用。
- offset: 轮廓点应该偏移的量,当在
roi
上提取轮廓后想还原到原图上时比较有用。
2.轮廓提取模式
第四个参数mode
,可以选择不同的轮廓提取算法,常用的有RETR_EXTERNAL/RETR_LIST/RETR_CCOMP/RETR_TREE
四种。下面分别进行介绍。在findContours
函数中,其第3个参数hierarchy
表示的轮廓之间的层级关系,对于不同mode
的轮廓提取算法,其返回的值是不同的。如下图【来自于OpenCV Doc】:
图中不同的轮廓有层级嵌入关系,我们将外部的轮廓称为父,内部的轮廓称为子,hierarchy
就是表示轮廓的父子和邻近关系的矩阵。上图中有0/1/2/3/4/5/2a/3a
8 个轮廓,其中0,1,2
是最外侧的轮廓,可记为它们在层级0hierarchy-0
。而2a
是轮廓2
的子轮廓,记为其在层级1hierarchy 1
。同样轮廓3
是轮廓2a
的子轮廓,记为其在层级2hierarchy 2
。同样轮廓3a
是轮廓3
的子轮廓,记为其在层级3hierarchy 3
。4/5
是3a
的子轮廓,其构成层级4hierarchy 4
。 属于每个层的轮廓都有其自己的信息,如它的子轮廓是什么,父轮廓是什么,OpenCV
通过一个四个元素的数组来表示每个轮廓与其他轮廓的关系,这个四维数组中的值分别表示**[Next, Previous, First_Child, Parent]
, Next
表示属于同一个层级hierarchy
的下一个轮廓,以上图轮廓0
为例,0,1,2
属于同个层级hierarchy-0
的轮廓,因此0
的Next
是1
,1
的Next
是2
。同一个层级中轮廓2
已经是最后一个了,因此其Next
是-1
。同样对于上图的轮廓4
,与其同属于层级4hierarchy-4
的轮廓是5
,因此4
的Next=5
,而5
的Next=-1
。Previous
表示同一层级中之前的的那个轮廓**,如上图,1
的Previous=0
, 2
的Previous=1
,0
的Previous=-1
。First_Child
表示当前轮廓的第一个子轮廓,如上图,0
的First_Child=-1
,2
的First_Child=2a
,3a
的First_Child=4
。Parent
表示当前轮廓的父轮廓,如上图,4
和5
的父轮廓都是3a
,3a
的父轮廓是3
,3
的父轮廓是2a
,2
的Parent=-1
。
findContours
方法中的mode
参数会返回不同的hierarchy
信息,因为有些算法会找出轮廓间的嵌套和邻近关系,有些则只是把轮廓找出来而不会解析轮廓之间的信息。
2.1 RETR_LIST
RETR_LIST
算法只会返回轮廓信息,而没有轮廓间的嵌套信息。因此,所有的轮廓都属于同个层级hierarchy
没有父子关系, hierarchy
返回值中只有Next
和Previous
,Parent
和First_Child
都为-1
。四维数组的第3和第4个元素都是-1
。如上图运行findContours
后的输出:
findContours(image, contours, hierarchy, cv::RETR_LIST, cv::CHAIN_APPROX_SIMPLE);
>>> hierarchy
[1, -1, -1, -1]
[2, 0, -1, -1]
[3, 1, -1, -1]
[4, 2, -1, -1]
[5, 3, -1, -1]
[6, 4, -1, -1]
[7, 5, -1, -1]
[-1, 6, -1, -1]
这里的0/1/2/3/4/5/6/7
对应的是轮廓在contours
中的下标。
2.2 RETR_EXTERNAL
RETR_EXTERNAL
算法,只会返回最外侧的轮廓信息,所有的子轮廓都不会返回,如上图,使用RETR_EXTERNAL
算法将只会返回hierarchy-0
层级0
的3个轮廓。当然hierarchy
中也只有3
个轮廓之间的邻近信息,Parent
和First_Child
依然都为-1
。
findContours(image, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
[1, -1, -1, -1]
[2, 0, -1, -1]
[-1, 1, -1, -1]
2.3 RETR_CCOMP
RETR_CCOMP
算法会找到图中所有的轮廓,但只会将轮廓组织成两层hierarchy=2
。物体的外轮廓属于hierarchy-0
,内轮廓属于hierarchy-1
,如上图0/1/2/3/4/5
都属于hierarchy-0
,而2a/3a
属于hierarchy-1
。
findContours(image, contours, hierarchy, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE);
[1, -1, -1, -1]
[2, 0, -1, -1]
[4, 1, 3, -1]
[-1, -1, -1, 2]
[6, 2, 5, -1]
[-1, -1, -1, 4]
[7, 4, -1, -1]
[-1, 6, -1, -1]
值得注意的是对于轮廓2a
和3a
,其hierarchy
分别是[-1, -1, -1, 2]
和[-1, -1, -1, 4]
。这是因为2a
和3a
虽然属于hierarchy-1
,但中间还隔着轮廓3
,因此2a
和3a
之间没有邻近关系。
再来看个例子,如下图:【来自于OpenCV Doc】
轮廓0
是外轮廓,1
和2
分别是轮廓0
所围成物体的内轮廓,4
属于内轮廓,3
属于外轮廓,6
属于内轮廓,5
属于外轮廓,7
和8
也都属于外轮廓。对于轮廓0
其属于hierarchy-1
,两个内轮廓1
和2
属于hierarchy-2
。故对于轮廓0
,其Next=3
,同个层级hierarchy level
的下一个,previous=-1
,‵First-Child=1,故轮廓
0的
hierarchy=[3,-1, 1, -1]`。
轮廓1
属于层级2
,hierarchy-2
,其同一层级的下一个(与1
在同个父外轮廓中)轮廓是2
,其他均为-1
,因此轮廓1
的hierarchy=[2, -1, -1, 0]
。
轮廓2
属于层级2
,hierarchy-2
,其前一个轮廓是同个父外轮廓下的1
,其余为-1
,因此轮廓2
的hierarchy=[-1, 1, -1, 0]
。
轮廓3
在hierarchy-1
中的Next=5,Previous=0,First-Child=4,Parent=-1
。
>>> hierarchy
array([[[ 3, -1, 1, -1],
[ 2, -1, -1, 0],
[-1, 1, -1, 0],
[ 5, 0, 4, -1],
[-1, -1, -1, 3],
[ 7, 3, 6, -1],
[-1, -1, -1, 5],
[ 8, 5, -1, -1],
[-1, 7, -1, -1]]])
2.4 RETR_TREE
RETR_TREE
算法提取所有的轮廓,并返回所有轮廓之间的嵌套关系。如上图,使用RETR_TREE
得到的轮廓hierarchy
之间的关系为:【来自于OpenCV Doc】括号中的绿色字表示轮廓所属的层级hierarchy
。
以轮廓0
为例,其属于hierarchy-0
,‵Next=7, Previous=-1, First_Child=1, Parent=-1`。
>>> hierarchy
array([[[ 7, -1, 1, -1],
[-1, -1, 2, 0],
[-1, -1, 3, 1],
[-1, -1, 4, 2],
[-1, -1, 5, 3],
[ 6, -1, -1, 4],
[-1, 5, -1, 4],
[ 8, 0, -1, -1],
[-1, 7, -1, -1]]])
findContours(image, contours, hierarchy, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE);
[3, -1, 1, -1]
[2, -1, -1, 0]
[-1, 1, -1, 0]
[5, 0, 4, -1]
[-1, -1, -1, 3]
[6, 3, -1, -1]
[-1, 5, -1, -1]
3.测试代码
#include <opencv2/opencv.hpp>
#include <common.h>
using namespace std;
int main(int argc, char **argv)
{
cv::RNG rng(12345);
cout << "Usage: " << argv[0] << "\n";
cv::String img_dir = "/images/OpenCV/2findContours/hole-hierarchy.png";
cv::Mat image = cv::imread(img_dir, cv::IMREAD_GRAYSCALE);
vector<cv::Vec4i> hierarchy;
vector<vector<cv::Point> > contours;
findContours(image, contours, hierarchy, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE);
cv::cvtColor(image, image, cv::COLOR_GRAY2BGR);
std::cout << "Contours Size: " << contours.size() << std::endl;
for(size_t i=0; i<contours.size(); i++)
{
cv::Scalar clr = cv::Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
cv::drawContours(image, contours, i, clr, 3);
}
for(auto &v : hierarchy)
{
std::cout << v << std::endl;
}
std::cout << image.channels() << std::endl;
cv::imwrite("contours.png", image);
cv::imshow("Img", image);
cv::waitKey(0);
return 0;
}s
参考资料
欢迎访问个人网络日志知行空间
边栏推荐
- 陕西CAS:1244028-50-9_Biotin-PEG3-SCO-PPh3 固体
- 网络虚拟化
- 越折腾越好用的 3 款开源 APP
- [教你做小游戏] 只用几行原生JS,写一个函数,播放音效、播放BGM、切换BGM
- 大家要的Biotin-PEG3-Br/acid/NHS ester/alcohol/amine合集分享
- 转铁蛋白Tf功能化β-榄香烯-雷公藤红素/紫杉醇PLGA纳米粒/雷公藤甲素脂质体(化学试剂)
- 电脑重装系统Win11格式化硬盘的详细方法
- LeetCode·27.移除元素·双指针
- 什么是企业知识库?有什么作用?如何搭建?
- QoS Quality of Service Six Router Congestion Management
猜你喜欢
随机推荐
redis 事件
Today's bug, click on the bug that the Windows dynamic wallpaper disappears in the win10 taskbar, and no solution has been found yet.
电脑如何去掉u盘写保护的状态
第14章_MySQL事务日志
TDD、FDD是什么意思?
大家要的Biotin-PEG3-Br/acid/NHS ester/alcohol/amine合集分享
云渲染的应用正在扩大,越来越多的行业需要可视化服务
转铁蛋白Tf功能化β-榄香烯-雷公藤红素/紫杉醇PLGA纳米粒/雷公藤甲素脂质体(化学试剂)
argparse——命令行参数解析
魔方电池如何“躺赢”?解锁荣威iMAX8 EV“头等舱”安全密码
Rider调试ASP.NET Core时报thread not gc-safe的解决方法
【深度学习前沿应用】图像风格迁移
We used 48h to co-create a web game: Dice Crush, to participate in international competitions
Hangdian Multi-School Seven 1003-Counting Stickmen (Combination Mathematics)
JVM基本结构
[Teach you how to do mini-games] How to lay out the hands of Dou Dizhu?See what the UP master of the 250,000 fan game area has to say
哈工大软件构造Lab3(2022)
状态压缩dp蒙德里安的梦想
servlet映射路径匹配解析
常见端口及服务