笔记(三)maxflow push relabel与图像分割

笔记(三)maxflow push relabel与图像分割

  • 1. Push-Relabel算法思想
  • 2.Push-Relabel算法原理示意图
  • 3.Push-Relabel算法具体实例
  • 4. push relabel与图割

1. Push-Relabel算法思想

对于一个网络流图: 该算法直观可以这样理解,先在源节点处加入充足的流(跟源节点 s s s相连的所有边的容量之和),然后开始按一定规则进行流渗透,一个边一个边的向汇点渗透,直到没法再渗透(类似于Ford-Fulkerson算法中找不到增广路径了),那么这时再把一些剩余的流回收到源节点 s s s就可。
主要分为两个步骤:push和relabel。push表示从所有节点找出一个存水量大于0的节点 u u u,将它所存的水尽可能推向与它相邻的节点 v v v。要实现该push的操作必须满足下面条件:该点存水量 e ( u ) > 0 e(u)>0 e(u)>0,节点 u u u的高度大于节 v v v的高度。本次推送的流值 ( u , v ) . f = min ⁡ e ( u ) , ( u , v ) . c a p a c i t y \mathbf{(u,v).f}= \min \mathbf{e(u)},\mathbf{(u,v).capacity} (u,v).f=mine(u),(u,v).capacity为边 e d g e ( u , v ) \mathbf{edge(u,v)} edge(u,v)的当前容量,这个值在推进过程中会一直变换。relabel表示某一个节点存水量大于0但水流不出去时,我们对该节点高度增加1,这就是所谓relabel操作,使得该节点的存水量流入比它低的节点。一开始的时候我们设置源节点高度为 N N N,此处 N N N为节点数,其他所有节点高度为0,并且汇节点的高度固定为0,其他节点高度在算法执行过程中高度 h h h会改变。

算法步骤:
1.初始化前置流:将与源点s相连的管道流量 f ( 0 , i ) f(0,i) f(0,i)设为该管道的容量,即 f ( 0 , i ) = c ( 0 , i ) f(0,i)=c(0,i) f(0,i)=c(0,i);将源点 s s s的高度 h ( 0 ) = V h(0)=V h(0)=V,( V V V表示图的顶点个数),其余顶点高度 h ( i ) = 0 h(i)=0 h(i)=0;将源的点余量 e ( 0 ) e(0) e(0)设为源容量减去源的流出量,即 e ( 0 ) = − ∑ f ( 0 , i ) = − ∑ c ( 0 , i ) e(0)=-∑f(0,i)=-∑c(0,i) e(0)=f(0,i)=c(0,i),与源 s s s相连的点余量设为该点的流入量 e ( i ) = c ( 0 , i ) e(i)=c(0,i) e(i)=c(0,i),其余点都为0。

2.搜索是否有节点的点余量 e ( u ) > 0 e(u)>0 e(u)>0,如果存在,表示要对该点进行操作——重标记或者压入流:检查与该点 u u u全部的相邻点 v v v,若该点比它相邻点的高度大 h ( u ) > h ( v ) h(u)>h(v) h(u)>h(v),该管道的当前容量为 c ( u , v ) c(u,v) c(u,v),将该点 u u u的余量以最大方式压入该管道 d e l t a = m i n ( e ( u ) , c ( u , v ) ) delta=min(e(u),c(u,v)) delta=min(e(u),c(u,v)),然后对节点 u u u, v v v的余量 e e e、边 ( u , v ) (u,v) (u,v)的容量进行相应的进行减加操作;如果找不到高度比自己低的相邻节点 v v v,则对节点 u u u的高度增加1,即 h ( u ) = h ( u ) + 1 h(u)=h(u)+1 h(u)=h(u)+1。如此继续进行Push操作。以上的重标记或压入流操作循环进行,直至该点的余量 e ( u ) e(u) e(u)为0。

3.重复第2步,直找不到余量大于0的节点,停止算法,最后输出汇点 t t t的余量 e ( t ) e(t) e(t),该值就是最后所求的最大流。最小割。

2.Push-Relabel算法原理示意图

给定的网络流图如下:

在这里插入图片描述
第一步:初始化操作:
在这里插入图片描述
第一次Push不成功,进行Relabel
在这里插入图片描述

第二次Push,成功

在这里插入图片描述

继续Push

在这里插入图片描述
继续Push

在这里插入图片描述
继续Push
在这里插入图片描述
至此结束。

3.Push-Relabel算法具体实例

求解下面网络流图的最大流:

在这里插入图片描述
源节点为s
,汇节点为t

具体程序实现如下:

/****************************************************
Description:Push-Relabel算法求解网络最大流
Author:Robert.TY
Date:2016.12.10 
****************************************************/ 
#include<iostream>
#include<limits>
#include<iomanip> 
using namespace std;
struct Point{
    char ch;//节点标识 
    int e;//存货量
    int h;//高度 
};    
Point point[6];               
int graph[6][6]={{0,10,10,0,0,0},
                 {0,0,2,8,4,0},
                 {0,0,0,9,0,0},
                 {0,0,0,0,9,10},
                 {0,0,0,0,0,10},
                 {0,0,0,0,0,0}} ;        
int Push_Relabel(int s, int t,int n); //参数为 起点  端点  节点数 

int main(){  
    int  n=6;  
    point[0].ch='s';  point[0].e=0; point[0].h=0; 
    point[1].ch='u';  point[1].e=0; point[1].h=0; 
    point[2].ch='v';  point[2].e=0; point[2].h=0; 
    point[3].ch='a';  point[3].e=0; point[3].h=0; 
    point[4].ch='b';  point[4].e=0; point[4].h=0; 
    point[5].ch='t';  point[5].e=0; point[5].h=0; 
    cout<<"原始网络图邻接矩阵:"<<endl;
    for(int i=0;i<=5;i++){
        for(int j=0;j<=5;j++){
            cout<<setw(6)<<graph[i][j]<<" ";

        }cout<<endl;
    } 
    cout<<"max_flow="<<Push_Relabel(0, n-1,n)<<endl; 
    cout<<"graph流图矩阵:"<<endl;
    for(int i=0;i<=5;i++){
        for(int j=0;j<=5;j++){
            cout<<setw(6)<<graph[i][j]<<" ";

        }cout<<endl;
    } 
    return 0;  
} 

int Push_Relabel(int s, int t,int n)  
{  
    int  max_flow;
    point[s].h = n;  //起始点高度置为n 最高
    //初始化 将start点的库存 流出去 update剩余图 
    for (int u = 1; u <= t; u++) {  
        if (graph[s][u] > 0) {  
            point[u].e = graph[s][u];  
            point[s].e -= graph[s][u];  
            graph[u][s] = graph[s][u];  
            graph[s][u] = 0;  
        }   
    }
    while(1) {  
        int finishflag = 1;  
        for (int u = s+1; u < t; u++) {  //搜索除  节点s 节点t以外的节点 
            if (point[u].e > 0) {  //发现库存量大于0的节点 u  进行push 
                finishflag = 0;  
                int relabel = 1;   //先假设顶点u需要relabel  提高高度h 
                for (int v = s; v <= t && point[u].e > 0; v++) {   //搜索能push的顶点   
                    if (graph[u][v] > 0 && point[u].h >point[v].h) {  //发现节点v 
                        relabel = 0;  //顶点u不需要relabel
                        int bottleneck = min(graph[u][v], point[u].e);  
                        point[u].e -= bottleneck; //u节点库存量减少 
                        point[v].e += bottleneck; //v节点库存量减少
                        graph[u][v] -= bottleneck;  
                        graph[v][u] += bottleneck;  

                    }  
                }  
                if (relabel==1) {  //没有可以push的顶点,u节点需要relabel 提高高度
                    point[u].h += 1;   
                }  
            }  
        }  
        if (finishflag==1) { // 除源点和汇点外,每个顶点的e[i]都为0 
            max_flow = 0;  
            for (int u = s; u <= t; u++) {  
                if (graph[t][u] > 0) {  
                    max_flow += graph[t][u];  
                }  
            }  
            //cout<<"max_flow="<<max_flow<<endl;
            break;  
        }  
    }  
    return max_flow;  
}  

结果如下:

原始网络图邻接矩阵:
     0     10     10      0      0      0
     0      0      2      8      4      0
     0      0      0      9      0      0
     0      0      0      0      9     10
     0      0      0      0      0     10
     0      0      0      0      0      0
max_flow = 19
graph 流图矩阵:
     0      0      1      0      0      0
    10      0      2      2      0      0
     9      0      0      0      0      0
     0      6      9      0      4      0
     0      4      0      5      0      1
     0      0      0     10      9      0

--------------------------------
Process exited after 0.04971 seconds with return value 0

Press ANY key to exit...

最大流可以通过最后一行的数值得到,即与t直接相关联的流量。

参考:最大流网络之Push-Relabel算法

4. push relabel与图割

Push-relabel算法是一种用于求解最大流问题的算法,也可以应用于图像分割领域。下面是将Push-relabel算法应用于图像分割的基本步骤:

构建图:首先,将输入图像转换为图的形式。每个像素被表示为一个节点,每个相邻的像素之间存在一条边,边的权重可以表示像素之间的差异或相似度。
初始化:对图进行初始化,通常将每个节点的标签初始化为一个唯一的整数。
推送流:从源节点开始,通过不断地推送流和重新标签化的操作,将流从源节点推送到汇节点。在这个过程中,Push-relabel算法会尝试将更多的流推送到已经饱和的节点,直到无法再推送更多的流为止。
重新标签:在推送流的过程中,当一个节点接收到的流超过其容量时,该节点会变得“饱和”。Push-relabel算法会为这个节点分配一个新的标签,并将这个节点与新标签之间的边进行更新。
更新残量网络:在推送流和重新标签的过程中,Push-relabel算法会不断更新残量网络,即还没有被推送到的边的集合。
判断终止条件:如果无法再找到新的增广路径(即无法再推送更多的流),则算法终止。
后处理:在得到最大流后,需要将结果映射回原始的图像。通常,可以将每个节点的标签映射为其所属的集合(即分割结果),或者将每个边的流量映射为边缘检测结果。
输出结果:最后,根据映射后的结果进行适当的后处理,如去除小面积的区域、平滑边缘等,以提高分割的质量。
通过以上步骤,可以使用Push-relabel算法进行图像分割。需要注意的是,Push-relabel算法通常会得到多解,因此需要进行合适的后处理和参数调整,以获得最佳的分割结果。

伪代码:

Push-relabel算法的伪代码如下:

初始化:

对于每个节点u,设置low_water_mark[u] = 0和high_water_mark[u] = INF(一个很大的数)
对于每个节点u,设置label[u] = 0和delta[u] = 0
对于每条边(u,v),设置residual_capacity[u,v] = capacity[u,v],residual_flow[u,v] = 0
while there is a path from source to sink in the residual graph:

从源节点开始,使用DFS或BFS等搜索算法搜索增广路径
在搜索过程中,维护一个当前节点的集合C和一条从源节点到集合C的最小割
对于每个节点u,如果u不在C中且delta[u] > 0,执行push操作:
从集合C中选择一个节点v,使得(u,v)在residual_graph中且residual_capacity[u,v] > 0
将流从u推送到v,即令delta[v] = delta[v] + delta[u],residual_flow[u,v] = residual_flow[u,v] + delta[u],residual_capacity[u,v] = residual_capacity[u,v] - delta[u]
将low_water_mark[v]更新为low_water_mark[u] + delta[v],high_water_mark[v]更新为high_water_mark[u] + delta[v],label[v]更新为label[u] + delta[v]
将low_water_mark[u]更新为max(low_water_mark[u], high_water_mark[v]),high_water_mark[u]更新为max(high_water_mark[u], label[v]),label[u]更新为label[v] - delta[u]
输出结果:将每个节点的标签映射为其所属的集合(即分割结果),或者将每个边的流量映射为边缘检测结果。

需要注意的是,Push-relabel算法通常会得到多解,因此需要进行合适的后处理和参数调整,以获得最佳的分割结果。

参考:
参考:
参考:

参考:
参考:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/191327.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

WordPress无需插件禁用WP生成1536×1536和2048×2048尺寸图片

我们在使用WordPress上传图片媒体文件的时候&#xff0c;是不是看到媒体库中有15361536和20482048的图片文件&#xff0c;当然这么大的文件会占用我们的服务器空间&#xff0c;如何禁止掉呢&#xff1f; function remove_default_image_sizes( $sizes) {unset( $sizes[1536x15…

人力资源管理后台 === 组织架构

目录 1.组织架构-树组件应用 2.组织架构-树组件自定义结构 3.组织架构-获取组织架构数据 4.组织架构-递归转化树形结构 5.组织架构-添加子部门-新建弹层组件 6.组织架构-添加子部门-表单结构 7.组织架构-添加子部门-表单基本校验 8.组织架构-添加子部门-表单业务校验 9…

ATK-ESP8266 WIFI模块串口通信通用实现方案

ATK-ESP8266 WIFI模块是一种常用的无线模块&#xff0c;它可以通过串口与外部设备进行通信&#xff0c;实现数据的收发和控制。本文将介绍一种通用的实现方案&#xff0c;帮助您在项目中使用ATK-ESP8266 WIFI模块进行串口通信。 【方案概述】 这个通用实现方案涵盖了ATK-ESP82…

VMWare虚拟机ubuntu克隆打不开

ubuntu克隆打不开 复制的存有ubuntu克隆的文件夹&#xff0c;导入vmware打不开 说找不到这个文件&#xff0c;那就到目录把它的删掉 的删掉 换000001.vmdk后缀的

Android 10.0 mtp模式下连接pc后显示的文件夹禁止删除copy重命名功能实现

1.前言 在10.0的系统开发中,usb连接pc端的时候有好几种模式,在做otg连接pc端的时候,改成mtp模式的时候,在pc端可以看到产品设备 的显示的文件夹的内容,对于产品设备里面的文件在pc端禁止做删除重命名拷贝等操作功能的实现 2.mtp模式下连接pc后显示的文件夹禁止删除copy重命…

在我国干独立游戏开发有多难?

游戏独立开发在中国&#xff0c;一直以来都是一条充满挑战的道路。尽管有着无限的激情和创意&#xff0c;但面对市场、资金、政策等多方面的困难&#xff0c;许多独立开发者在这条路上艰难前行。 首先&#xff0c;市场竞争激烈是中国游戏独立开发者面临的首要挑战。随着游戏产…

Unsupervised MVS论文笔记(2019年)

Unsupervised MVS论文笔记&#xff08;2019年&#xff09; 摘要1 引言2 相关工作3 实现方法3.1 网络架构3.2 通过光度一致性学习3.3 MVS的鲁棒光度一致性3.4 学习设置和实施的细节3.5.预测每幅图像的深度图 4 实验4.1 在DTU上的结果4.2 消融实验4.3 在ETH3D数据集上的微调4.4 在…

BUUCTF [MRCTF2020]Ez_bypass 1

题目环境&#xff1a;F12查看源代码 I put something in F12 for you include flag.php; $flagMRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}; if(isset($_GET[gg])&&isset($_GET[id])) { $id$_GET[id]; $gg$_GET[gg]; if (md5($id) md5($gg) && $id ! $gg) { …

显示Excel功能区或工具栏的方法不少,其中快捷方式最快

Microsoft Excel是Office套件中最复杂的工具之一&#xff0c;它提供了大量功能&#xff0c;其中大部分都是使用工具栏操作的。缺少工具栏使Excel很难完成工作。 如果Excel中没有这些关键元素&#xff0c;你将无法快速完成工作&#xff0c;因此&#xff0c;可以理解的是&#x…

算法基础之合并集合

合并集合 核心思想:并查集: 1.将两个集合合并2.询问两个元素是否在一个集合当中 基本原理:每个集合用一棵树表示 树根的编号就是整个集合的编号 每个节点存储其父节点&#xff0c;p[x]表示x的父节点 #include<iostream>using namespace std;const int N100010;int p[N];…

RESTful API 架构快速入门 Flask实现

RESTful 简介 1.1 为什么要使用 RESTful 架构&#xff1f; Representational State Transfer&#xff08;REST&#xff09;是一种面向资源的架构风格&#xff0c;广泛应用于网络服务的设计和开发。使用RESTful架构有以下几个优点&#xff1a; 简单性和可扩展性&#xff1a; RE…

springboot 拦截器中使用@Value注解为null

拦截器中获取配置参数为null 代码如下&#xff1a; 解决方式一&#xff1a; 检查你的WebMvcConfigurer实现类&#xff0c;比如我的是CCBWebMvcConfig 将拦截器以bean的形式注入&#xff1a; 我之前的写法是new 一个放进去的&#xff0c;这种会导致Value为null AutowiredJSCCB…

图像分割模型及架构选型介绍(MMSegmentation|sssegmentation等)

参考&#xff1a; https://zhuanlan.zhihu.com/p/618226513 0. 图像分割概述 图像分割通过给出图像中每个像素点的标签&#xff0c;将图像分割成若干带类别标签的区块&#xff0c;可以看作对每个像素进行分类。图像分割是图像处理的重要组成部分&#xff0c;也是难点之一。随…

二次创作Z01语言

目录 一&#xff0c;字符集 二&#xff0c;编译分词 三&#xff0c;token含义 四&#xff0c;Z01翻译成C 五&#xff0c;执行翻译后的代码 六&#xff0c;打印Hello World! 一&#xff0c;字符集 假设有门语言叫Z01语言&#xff0c;代码中只有0和1这两种字符。 二&#…

使用花生壳外网远程ssh访问内网主机 亲测有效

经常会遇到远程访问其他电脑的需求&#xff0c;一般首选向日葵软件&#xff0c;傻瓜式的连接远程桌面控制&#xff0c;非常方便。但是仅限于远程桌面远程协助这种。 对于程序员来说最佳的登录方式是ssh&#xff0c;同时远程桌面连过来的时候分辨率比较低&#xff0c;图形效果相…

上海交通大学生存手册

强烈推荐所有大学生去阅读《上海交通大学生存手册》。虽然它可能有些冗长&#xff0c;但非常重要&#xff0c;因为它道出了大学教育的本质。 如果几年前我能够看到这本书&#xff0c;也许我的大学生活会有所不同。现在我将向正在上大学或者将要上大学的你推荐这本书。 无论你…

Less的函数的介绍

文章目录 前言描述style.less输出后言 前言 hello world欢迎来到前端的新世界 &#x1f61c;当前文章系列专栏&#xff1a;Sass和Less &#x1f431;‍&#x1f453;博主在前端领域还有很多知识和技术需要掌握&#xff0c;正在不断努力填补技术短板。(如果出现错误&#xff0c;…

python--获取每张切片的不同PEF区间值的百分比

在全直径数字岩心中&#xff0c;如何获取每张切片的不同PEF区间值的百分比&#xff1f; import os import datetime from PIL import Image import numpy as np import csv import easygui as gclass Table(object):def __init__(self, table_data_path):self.table_data_path…

MySQL进阶_10.锁

文章目录 一、概述二、MySQL并发事务访问相同记录2.1、读-读2.2、写-写2.3、读-写2.4、并发问题的解决方案 三、锁的不同角度分类3.1、 读锁、写锁3.1.1、 锁定读 3.2、表级锁、页级锁、行锁3.2.1、表锁3.2.2、意向锁3.2.2.1、意向锁的作用3.2.2.2、意向锁的互斥性 3.2.3、自增…

正则表达式例题-PTA

PTA-7-55 判断指定字符串是否合法-CSDN博客 7-54 StringBuffer-拼接字符串 题目&#xff1a; 输入3个整数n、begin、end。 将从0到n-1的数字拼接为字符串str。如&#xff0c;n12&#xff0c;则拼接出来的字符串为&#xff1a;01234567891011 最后截取字符串str从begin到end(包…
最新文章