0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

二值图像的欧拉数计算公式

OpenCV学堂 来源:OpenCV学堂 作者:OpenCV学堂 2022-06-30 11:08 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

欧拉数定义

二值图像分析中欧拉数重要的拓扑特征之一,在图像分析与几何对象识别中有着十分重要的作用,二值图像的欧拉数计算公式表示如下:
E = N – H 其中
E表示计算得到欧拉数
N表示联通组件的数目
H表示在联通组件内部的洞的数目
下图是二值图像,白色背景,两个对象、分析计算得到欧拉数的例子:

01d926cc-f7bf-11ec-ba43-dac502259ad0.png

可以看到通过简单的欧拉数属性就可以对它们进行区分。左侧对象中有两个联通区域,所以N=2,没有洞孔区域,所以H=0, 计算得到欧拉数目为 2 – 0 = 。右侧是大写字母B,它只有一个联通区域所以N = 1, 内部有两个洞孔区域所以H = 2,最终计算得到欧拉数为 2 – 1 = -1。对于任意一个几何形状来说,如果我们要求得它的欧拉数,就首先要分析它的轮廓结构,然后根据轮廓层次结构计算得到N与H值。

欧拉数是图像几何识别中重要的属性,举例如下图中三个英文字母

01f57b74-f7bf-11ec-ba43-dac502259ad0.png 对字母A来说它的内部有一个黑色孔洞,所以它的H=1,其本身是一个联通组件所以N =1,最终计算得到欧拉数为 E = 1 -1 = 0,同样可以计算B与C它们的欧拉数分布为-1与1,可见通过欧拉数属性可以轻而易举的区分ABC三个英文字母。

二:轮廓层次信息获取

在OpenCV对二值图像进行轮廓分析输出的层次结构会保存在一个Vec4i的结构体中,这里有必要首先看一下轮廓发现API及其相关参数的解释:

voidcv::findContours(
InputOutputArrayimage,
OutputArrayOfArrayscontours,
OutputArrayhierarchy,
intmode,
intmethod,
Pointoffset=Point()
)
image参数表示输入的二值图像
contours表示所有的轮廓信息,每个轮廓是一系列的点集合
hierarchy表示对应的每个轮廓的层次信息,我们就是要用它实现对最大轮廓欧拉数的分析
mode表示寻找轮廓拓扑的方法,如果要寻找完整的层次信息,要选择参数RETR_TREE
method表示轮廓的编码方式,一般选择简单链式编码,参数CHAIN_APPROX_SIMPLE
offset表示是否有位移,一般默认是0

上面的参数中最重要的是hierarchy信息,它的输出是vector每个轮廓对应的Vec4i结构体里面四个值解释如下:

02138222-f7bf-11ec-ba43-dac502259ad0.png

上面的索引如果是负数就表示没有相关层次信息,如果是非负数就表示有相关的层次关系信息。此外轮廓发现函数对输入image图像的要求必须满足

  • 背景是黑色 ,0表示

  • 对象或者前景是白色,1表示

三:欧拉数计算方法

有了轮廓的层次信息与每个轮廓的信息之后,尝试遍历每个轮廓,首先通过调用findContours就可以获取二值图像的轮廓层次信息,然后遍历每个轮廓,进行层次遍历,获得每层子轮廓的总数,最终根据轮廓层级不同分为孔洞与连接轮廓的计数,二者想减得到每个独立外层轮廓的欧拉数。

二值化与轮廓发现的代码如下:

Matgray,binary;
cvtColor(src,gray,COLOR_BGR2GRAY);
threshold(gray,binary,0,255,THRESH_BINARY|THRESH_OTSU);
vectorhireachy;
vector<vector>contours;
findContours(binary,contours,hireachy,RETR_TREE,CHAIN_APPROX_SIMPLE,Point());

获取同层轮廓的代码如下:

vector<int>current_layer_holes(vector<Vec4i>layers,intindex){
intnext=layers[index][0];
vector<int>indexes;
indexes.push_back(index);
while(next>=0){
indexes.push_back(next);
next=layers[next][0];
}
returnindexes;
}

使用队列迭代寻找遍历每层的代码如下:

while(!nodes.empty()){
//当前层总数目
if(index%2==0){//联通组件对象
n_total+=nodes.size();
}
else{//孔洞对象
h_total+=nodes.size();
}
index++;
//计算下一层所有孩子节点
intcurr_ndoes=nodes.size();
for(intn=0;n< curr_ndoes; n++) {
        intvalue=nodes.front();
nodes.pop();
//获取下一层节点第一个孩子
intchild=hireachy[value][2];
if(child>=0){
nodes.push(child);
}
}
}

四:运行与测试结果

测试图一(ABC)与运行结果:

022be9de-f7bf-11ec-ba43-dac502259ad0.jpg

测试图二与运行结果

024b4b1c-f7bf-11ec-ba43-dac502259ad0.jpg

五:完整源代码

#include
#include

usingnamespacecv;
usingnamespacestd;

vector<int>current_layer_holes(vectorlayers,intindex);

intmain(intargc,char**argv){
Matsrc=imread("D:/holes.png");
if(src.empty()){
printf("couldnotloadimage...
");
return-1;
}
namedWindow("input",CV_WINDOW_AUTOSIZE);
imshow("input",src);

Matgray,binary;
cvtColor(src,gray,COLOR_BGR2GRAY);
threshold(gray,binary,0,255,THRESH_BINARY|THRESH_OTSU);

vectorhireachy;
vector<vector>contours;
findContours(binary,contours,hireachy,RETR_TREE,CHAIN_APPROX_SIMPLE,Point());
Matresult=Mat::zeros(src.size(),src.type());
for(size_tt=0;t< contours.size(); t++) {
        intnext=hireachy[t][0];//nextatthesamehierarchicallevel
intprev=hireachy[t][1];//prevatthesamehierarchicallevel
intchild=hireachy[t][2];//firstchild
intparent=hireachy[t][3];//parent
printf("next%d,previous%d,children:%d,parent:%d
",next,prev,child,parent);
drawContours(result,contours,t,Scalar(0,255,0),2,8);
//startcalculateeulernumber
inth_total=0;
intn_total=1;
intindex=1;
vector<int>all_children;
if(child>=0&&parent< 0){
//计算当前层
queue<int>nodes;
vector<int>indexes=current_layer_holes(hireachy,child);
for(inti=0;i< indexes.size(); i++) {
                nodes.push(indexes[i]);
            }
            while(!nodes.empty()){
//当前层总数目
if(index%2==0){//联通组件对象
n_total+=nodes.size();
}
else{//孔洞对象
h_total+=nodes.size();
}
index++;
//计算下一层所有孩子节点
intcurr_ndoes=nodes.size();
for(intn=0;n< curr_ndoes; n++) {
                    intvalue=nodes.front();
nodes.pop();
//获取下一层节点第一个孩子
intchild=hireachy[value][2];
if(child>=0){
nodes.push(child);
}
}
}
printf("holenumber:%d
",h_total);
printf("connectionnumber:%d
",n_total);
//计算欧拉数
inteuler_num=n_total-h_total;
printf("numberofeuler:%d
",euler_num);
drawContours(result,contours,t,Scalar(0,0,255),2,8);
//显示欧拉数
Rectrect=boundingRect(contours[t]);
putText(result,format("euler:%d",euler_num),rect.tl(),FONT_HERSHEY_SIMPLEX,1.0,Scalar(255,255,0),2,8);
}
if(child< 0&&parent< 0){
printf("holenumber:%d
",h_total);
printf("connectionnumber:%d
",n_total);
inteuler_num=n_total-h_total;
printf("numberofeuler:%d
",euler_num);
drawContours(result,contours,t,Scalar(255,0,0),2,8);
Rectrect=boundingRect(contours[t]);
putText(result,format("euler:%d",euler_num),rect.tl(),FONT_HERSHEY_SIMPLEX,1.0,Scalar(255,255,0),2,8);
}

}

imshow("result",result);
waitKey(0);
return0;
}

vector<int>current_layer_holes(vectorlayers,intindex){
intnext=layers[index][0];
vector<int>indexes;
indexes.push_back(index);
while(next>=0){
indexes.push_back(next);
next=layers[next][0];
}
returnindexes;
}

PS:代码未经更多严格测试,仅供参考!

审核编辑 :李倩


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 二值图像
    +关注

    关注

    0

    文章

    14

    浏览量

    8903
  • OpenCV
    +关注

    关注

    33

    文章

    651

    浏览量

    44420
  • 欧拉
    +关注

    关注

    1

    文章

    14

    浏览量

    1906

原文标题:OpenCV轮廓层次分析实现欧拉数计算

文章出处:【微信号:CVSCHOOL,微信公众号:OpenCV学堂】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    贴片电容的精度是怎么计算出来的?

    贴片电容的精度通过 实际电容与标称电容的偏差范围 计算得出,其核心计算逻辑和关键要点如下: 一、精度定义与计算公式 贴片电容的精度表示实
    的头像 发表于 10-11 15:01 720次阅读
    贴片电容的精度是怎么<b class='flag-5'>计算</b>出来的?

    开源社区AI联合工作组正式成立

    近日,2025开放原子开源生态大会——开源生态分论坛在北京国家会议中心期顺利举办。来自产、学、研、用领域的社区成员与开发者齐聚一堂,共探南北向生态拓展与国际协作,深入解析AI生态使能与落地、边
    的头像 发表于 07-28 17:20 963次阅读

    电力变压器空载及短路功率因数计算公式及应用

    的定义得出: PF=P/S。 P为有功功率,S为视在功率。 上述功率因数计算公式只有在已知有功功率和视在功率(或电压和电流的有效)的情况下才能使用。 对于一般的电力设备而言,不同的工作点下有不同的功率因数。因此,许多设备会在铭牌上标识额定运行状态下
    的头像 发表于 07-15 10:00 2130次阅读
    电力变压器空载及短路功率因数<b class='flag-5'>计算公式</b>及应用

    如何计算孔板流量计和平衡流量计的流量?计算公式一样吗?

    平衡流量计与孔板流量计作为差压式流量计的典型代表,虽均基于压力差与流量的数学关系进行计算,但是平衡流量计计算公式和孔板流量计的计算公式大不相同,其核心公式、参数修正及适用场景存在显著差
    的头像 发表于 07-09 13:54 556次阅读
    如何<b class='flag-5'>计算</b>孔板流量计和平衡流量计的流量?<b class='flag-5'>计算公式</b>一样吗?

    自己动手绕线圈电感详细计算公式(建议收藏!)

    *2.047)+(40*3.74)}]÷2.047=19圈空心电感计算公式:L(mH)=(0.08D.D.N.N)/(3D+9W+10H)D------线圈直径N------线圈匝数d-----线径H----
    发表于 05-28 16:57

    电机选型计算公式与知识点汇总

    纯分享帖,需要者可点击附件获取完整资料~~~*附件:电机选型计算公式与知识点汇总.pdf 【免责声明】内容转自今日电机,因转载众多,无法确认真正原始作者,故仅标明转载来源。版权归原出处所有,纯分享帖,侵权请联系删除内容以保证您的权益。
    发表于 04-29 16:10

    压敏电阻器选型计算公式解析

    在电子电路设计中,压敏电阻器作为一种重要的过电压保护元件,其选型至关重要。合理的选型不仅能有效保护电路免受浪涌电压的损害,还能确保电路的稳定运行。以下介绍压敏电阻器选型的关键计算公式。 压敏电压计算
    的头像 发表于 04-21 16:48 1060次阅读
    压敏电阻器选型<b class='flag-5'>计算公式</b>解析

    如何选择合适的水位流量计算公式?

    的适用场景、参数测量方法及公式选择要点,帮助用户精准匹配计算公式。一、第一步:明确堰型结构选择公式前,需通过现场检查或设计图纸确认堰的几何形状:注意:若堰口形状与上
    的头像 发表于 04-02 16:32 1116次阅读
    如何选择合适的水位流量<b class='flag-5'>计算公式</b>?

    压敏电阻型号及电感计算公式

    )) + ( 40 * 圈长(吋))}] ÷ 圈直径 (吋) 圈 = [8.116 * {(18*2.047) + (40*3.74)}] ÷ 2.047 = 19 圈 空心电感计算公式空心
    发表于 04-01 14:09

    【峟思应变计】应力计算公式及其符号意义

    介绍应力的计算公式及其公式中各符号的意义。应力的基本计算公式为σ=F/A,其中:σ代表应力。应力是反映材料内部抵抗外部变形能力的量度,其单位通常使用帕斯卡(Pa)
    的头像 发表于 02-26 14:39 3056次阅读
    【峟思应变计】应力<b class='flag-5'>计算公式</b>及其符号意义

    特性阻抗是什么意思,特性阻抗计算公式

    在高速电路设计和信号传输领域,特性阻抗(Characteristic Impedance)是一个至关重要的概念。它描述了信号在传输线上传输的行为和特性,对于确保信号完整性、减少信号反射和提高系统性能具有关键作用。本文将深入探讨特性阻抗的定义、意义以及计算公式,为工程师提供全面的理解。
    的头像 发表于 01-29 14:28 5866次阅读

    电工常用的计算公式

    电工常用的计算公式,帮助大家更好地理解和解决这些问题。 1、欧姆定律、焦耳定律、电功率、电能 首先,我们来看看欧姆定律。欧姆定律是电学的基础定律之一,它描述了电流、电压和电阻之间的关系。欧姆定律的公式为:I=V/R,
    的头像 发表于 01-21 09:32 2656次阅读
    电工常用的<b class='flag-5'>计算公式</b>

    位移计基础知识:计算公式与操作要点

    位移计,包括裂缝计等振弦式监测设备,在实际应用中常会受到环境温度的干扰。因此,在监测位移变动时,我们应尽量降低温度对结果的影响。值得注意的是,位移计的计算公式是建立在忽略外界温度变化的基础之上的。当
    的头像 发表于 12-17 14:42 1399次阅读
    位移计基础知识:<b class='flag-5'>计算公式</b>与操作要点

    LM567C的真正的中心频率计算公式是什么?

    1、LM567C的datasheet中,中心频率的计算公式为:f0=1.1/RC,而LM567C的百度百科中,中心频率的计算公式为:f0=1/1.1RC,那么LM567C的真正的中心频率计算公式
    发表于 12-13 07:23

    TDC1000的测量范围计算公式是什么?

    TDC1000的测量范围计算公式是什么
    发表于 12-10 06:19