匈牙利算法

日萌社

人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新)


CNN:RCNN、SPPNet、Fast RCNN、Faster RCNN、YOLO V1 V2 V3、SSD、FCN、SegNet、U-Net、DeepLab V1 V2 V3、Mask RCNN

自动驾驶:车道线检测、车速检测、实时通行跟踪、基于视频的车辆跟踪及流量统计

车流量检测实现:多目标追踪、卡尔曼滤波器、匈牙利算法、SORT/DeepSORT、yoloV3、虚拟线圈法、交并比IOU计算

多目标追踪:DBT、DFT、基于Kalman和KM算法的后端优化算法、SORT/DeepSORT、基于多线程的单目标跟踪的多目标跟踪算法KCF

计算交并比IOU、候选框不同表示方式之间的转换

卡尔曼滤波器

卡尔曼滤波器实践

目标估计模型-卡尔曼滤波

匈牙利算法

数据关联:利用匈牙利算法对目标框和检测框进行关联

SORT、DeepSORT

多目标追踪

yoloV3模型

基于yoloV3的目标检测

叉乘:基于虚拟线圈法的车流量统计

视频中的车流量统计


4.5. 匈牙利算法

学习目标:

  • 了解匈牙利算法
  • 了解KM算法

匈牙利算法(Hungarian Algorithm)与KM算法(Kuhn-Munkres Algorithm)是用来解决多目标跟踪中的数据关联问题,匈牙利算法与KM算法都是为了求解二分图的最大匹配问题

有一种很特别的图,就做二分图,那什么是二分图呢?就是能分成两组,U,V。其中,U上的点不能相互连通,只能连去V中的点,同理,V中的点不能相互连通,只能连去U中的点。这样,就叫做二分图。

可以把二分图理解为视频中连续两帧中的所有检测框,第一帧所有检测框的集合称为U,第二帧所有检测框的集合称为V。同一帧的不同检测框不会为同一个目标,所以不需要互相关联,相邻两帧的检测框需要相互联通,最终将相邻两帧的检测框尽量完美地两两匹配起来。而求解这个问题的最优解就要用到匈牙利算法或者KM算法。

1.匈牙利算法

匈牙利算法是一种在多项式时间内求解任务分配问题的组合优化算法。美国数学家哈罗德·库恩于1955年提出该算法。此算法之所以被称作匈牙利算法,是因为算法很大一部分是基于以前匈牙利数学家Dénes Kőnig和Jenő Egerváry的工作之上创建起来的。

我们以目标跟踪的方法介绍匈牙利算法,以下图为例,假设左边的四张图是我们在第N帧检测到的目标(U),右边四张图是我们在第N+1帧检测到的目标(V)。红线连起来的图,是我们的算法认为是同一行人可能性较大的目标。由于算法并不是绝对理想的,因此并不一定会保证每张图都有一对一的匹配,一对二甚至一对多,再甚至多对多的情况都时有发生。这时我们怎么获得最终的一对一跟踪结果呢?我们来看匈牙利算法是怎么做的。

  • 第一步

首先给左1进行匹配,发现第一个与其相连的右1还未匹配,将其配对,连上一条蓝线。

  • 第二步

接着匹配左2,发现与其相连的第一个目标右2还未匹配,将其配对

  • 第三步

接下来是左3,发现最优先的目标右1已经匹配完成了,怎么办呢?

我们给之前右1的匹配对象左1分配另一个对象。

(黄色表示这条边被临时拆掉)

可以与左1匹配的第二个目标是右2,但右2也已经有了匹配对象,怎么办呢?

我们再给之前右2的匹配对象左2分配另一个对象(注意这个步骤和上面是一样的,这是一个递归的过程)。

此时发现左2还能匹配右3,那么之前的问题迎刃而解了,回溯回去。

左2对右3,左1对右2,左3对右1。

所以第三步最后的结果就是:

  • 第四步

最后是左4,很遗憾,按照第三步的节奏我们没法给左4腾出来一个匹配对象,只能放弃对左4的匹配,匈牙利算法流程至此结束。蓝线就是我们最后的匹配结果。至此我们找到了这个二分图的一个最大匹配。最终的结果是我们匹配出了三对目标,由于候选的匹配目标中包含了许多错误的匹配红线(边),所以匹配准确率并不高。可见匈牙利算法对红线连接的准确率要求很高,也就是要求我们运动模型、外观模型等部件必须进行较为精准的预测,或者预设较高的阈值,只将置信度较高的边才送入匈牙利算法进行匹配,这样才能得到较好的结果。

可以使用:

scipy.optimize.linear_sum_assignment(cost_matrix)

实现匈牙利算法,其中const_matrix表示代价矩阵。比如第一帧有a,b,c,d四个目标,第二帧图像有p,q,r,s四个目标,其相似度矩阵如下所示:

from scipy.optimize import linear_sum_assignment
import numpy as np
# 代价矩阵
cost =np.array([[1,2,3,4],[2,4,6,8],[3,6,9,12],[4,8,12,16]])
# 匹配结果
row_ind,col_ind=linear_sum_assignment(cost)
#对应的行索引
print("行索引:\n{}".format(row_ind))
#对应行索引的最优指派的列索引
print("列索引:\n{}".format(col_ind))
#提取每个行索引的最优指派列索引所在的元素,形成数组
print("匹配度:\n{}".format(cost[row_ind,col_ind]))

输出结果为:

匈牙利算法的流程大家看到了,有一个很明显的问题相信大家也发现了,按这个思路找到的最大匹配往往不是我们心中的最优。匈牙利算法将每个匹配对象的地位视为相同,在这个前提下求解最大匹配。这个和我们研究的多目标跟踪问题有些不合,因为每个匹配对象不可能是同等地位的,总有一个真实目标是我们要找的最佳匹配,而这个真实目标应该拥有更高的权重,在此基础上匹配的结果才能更贴近真实情况。

KM算法就能比较好地解决这个问题,我们下面来看看KM算法。


匈牙利算法(Hungarian Algorithm)与KM算法(Kuhn-Munkres Algorithm)
	1.匈牙利算法与KM算法:都是用来解决多目标跟踪中的数据关联问题
	2.匈牙利算法与KM算法:都是为了求解二分图的最大匹配问题
	
二分图
	1.有一种很特别的图,就做二分图,那什么是二分图呢?就是能分成两组,U,V。
	  其中,U上的点不能相互连通,只能连V中的点,同理,V中的点不能相互连通,只能连U中的点。
	  这样,就叫做二分图。
	2.可以把二分图理解为视频中连续两帧中的所有检测框,第一帧所有检测框的集合称为U,
	  第二帧所有检测框的集合称为V。同一帧的不同检测框不会为同一个目标,所以不需要互相关联,
	  相邻两帧的检测框需要相互联通,最终将相邻两帧的检测框尽量完美地两两匹配起来。
	  而求解这个问题的最优解就要用到匈牙利算法或者KM算法。
	  
匈牙利算法
	1.匈牙利算法是一种在多项式时间内求解任务分配问题的组合优化算法。
	2.我们以目标跟踪的方法介绍匈牙利算法,以下图为例,假设左边的四张图是我们在第N帧检测到的目标(U),
	  右边四张图是我们在第N+1帧检测到的目标(V)。
	  红线连起来的图,是我们的算法认为是同一人的可能性较大的目标。
	  由于算法并不是绝对理想的,因此并不一定要保证每张图都有一对一的匹配,
	  出现一对二甚至一对多的情况,再甚至多对多的情况都时有发生。
	  这时我们怎么获得最终的一对一跟踪结果呢?我们来看匈牙利算法是怎么做的。  
	3.匈牙利算法
		1.第一步:
			首先给左1进行匹配,发现左1与其相连的第一个目标右1还未匹配,将其配对,连上一条蓝线。  
		2.第二步:
			接着匹配左2,发现左2与其相连的第一个目标右2还未匹配,将其配对,连上一条蓝线。
		3.第三步:
			1.接下来匹配左3,发现左3与其相连的第一个目标(最优先的目标)右1已经匹配给左1了,怎么办呢?
			  那么我们给之前右1匹配的对象左1分配给另外一个对象,即把左1和右1的匹配关系取消掉,
			  黄色线表示这左1和右1的匹配关系被临时拆掉。
			2.可以与左1匹配的第二个目标是右2,但右2此时也已经有了其匹配对象左2,怎么办呢?
			  我们再给之前右2的匹配对象左2分配给另一个对象(注意这个步骤和上面是一样的,这是一个递归的过程),
			  即把左2和右2的匹配关系取消掉,黄色线表示这左2和右2的匹配关系被临时拆掉。
			3.此时发现左2还能匹配与其相连的第二个目标右3,发现左1还能匹配与其相连的第二个目标右2,
			  最终左2匹配右3,左1匹配右2,左3匹配右1。
		4.第四步:
			最后是左4,很遗憾,按照第三步的节奏我们没法给左4腾出来一个匹配对象,只能放弃对左4的匹配,
			匈牙利算法流程至此结束。蓝线就是我们最后的匹配结果。至此我们找到了这个二分图的一个最大匹配。
			最终的结果是我们匹配出了三对目标,由于候选的匹配目标中包含了许多错误的匹配红线(边),
			所以匹配准确率并不高。可见匈牙利算法对红线连接的准确率要求很高,
			也就是要求我们运动模型、外观模型等部件必须进行较为精准的预测,或者预设较高的阈值,
			只将置信度较高的线(边)才送入匈牙利算法进行匹配,这样才能得到较好的结果。	
			
实现匈牙利算法
	1.API:scipy.optimize.linear_sum_assignment(cost_matrix)
		其中 const_matrix 表示代价矩阵。
		比如第一帧有a,b,c,d四个目标,第二帧图像有p,q,r,s四个目标,其相似度矩阵如下所示.
	2.例子:	
		from scipy.optimize import linear_sum_assignment
		import numpy as np
		# 代价矩阵
		cost =np.array([[1,2,3,4],[2,4,6,8],[3,6,9,12],[4,8,12,16]])
		# 匹配结果
		row_ind, =linear_sum_assignment(cost)
		#对应的行索引
		print("行索引:\n{}".format(row_ind))
		#对应行索引的最优指派的列索引
		print("列索引:\n{}".format(col_ind))
		#提取每个行索引的最优指派列索引所在的元素,形成数组
		print("匹配度:\n{}".format(cost[row_ind,col_ind]))	
		打印结果:
			行索引:
			[0 1 2 3]
			列索引:
			[3 2 1 0]
			匹配度:
			[4 6 6 4]		
	
	3.结论:
		匈牙利算法的流程,有一个很明显的问题,按这个思路找到的最大匹配往往不是我们心中的最优。
		匈牙利算法将每个匹配对象的地位视为相同,在这个前提下求解最大匹配。
		这个和所研究的多目标跟踪问题有些不合,因为每个匹配对象不可能是同等地位的,
		总有一个真实目标是我们要找的最佳匹配,而这个真实目标应该拥有更高的权重,
		在此基础上匹配的结果才能更贴近真实情况。
		KM算法就能比较好地解决这个问题。
KM算法
	KM算法解决的是带权二分图的最优匹配问题。
	还是用上面的图来举例子,这次给每条连接关系加入了权重,权重也就是我们算法中其他模块给出的置信度分值。

KM算法解决带权二分图的最优匹配问题的步骤:
	1.左右两边的图匹配的原则是:
		左右两边的图只和"权重与左边图的分数(顶标)相同的"边进行匹配,
		若左边图根据与其分数(顶标)相同的最大权重的线(边)所连接到的右图已经被分配了某个左图的话,
		那么产生冲突,解决的方式是对产生冲突的左边的两个图的顶标减d,
		然后令产生冲突的右边的一个图的顶点值加d。参数d我们在这里取值为0.1。
		
	2.实现具体步骤:
		1.第一步
			首先对左右两边的每个图(顶点)进行赋值,该值分数称为顶标。
			将左边的每个图(顶点)赋值为与其相连的线(边)的最大权重,右边的每个图(顶点)赋值为0。
		2.第二步:
			1.对于左1,与左1的顶标分值相同的最大权重的边先标蓝,左1连接右1。
			2.对于左2,与左2的顶标分值相同的最大权重的边先标蓝,左2连接右3。
			3.对于左3,与左3的顶标分值相同的最大权重的边所连接的右1已经与左1配对,左3无法直接连接右1,
			  此时产生冲突。
				1.首先想到的是让左3更换匹配对象,然而根据匹配原则,
				  只有权值大于等于(左图顶标加右图顶标)0.9+0=0.9的边能满足左3连接右1的要求,否则无法换边。
				  那么于是左3无法换边。那左1能不能换边(更换匹配对象)呢?
				  对于左1来说,只有权值大于等于(左图顶标加右图顶标)0.8+0=0.8的边能满足左1连接右1的要求,
				  否则无法换边。
				2.此时根据KM算法,应对产生冲突的左右两边的图的顶点做加减操作,
				  首先令产生冲突的左边的两个图的顶点值减0.1,然后令产生冲突的右边的一个图的顶点值加0.1。
				3.此时发现左3多了一条可匹配的边,因为此时左3连接右2的匹配要求能满足权重大于等于
				  (左图顶标加右图顶标)0.8+0=0.8,所以左3与右2匹配。
			4.最后进行左4的匹配,由于左4唯一的可匹配对象右3已被左2匹配,此时发生冲突。
			  左右两边发生冲突的图进行一轮加减d的操作,再进行匹配,此时左四还是匹配右3失败。
			  当经过一共两轮的加减d的操作后发现左4的顶标降为0,左4放弃继续匹配。

	3.至此KM算法流程结束,三对目标成功匹配,甚至在左三目标预测不够准确的情况下也进行了正确匹配。
	  可见在引入了权重之后,匹配成功率大大提高。
      最后还有一点值得注意,匈牙利算法得到的最大匹配并不是唯一的,预设匹配边、或者匹配顺序不同等,
	  都可能会导致有多种最大匹配情况,所以有一种替代KM算法的想法是,
	  我们只需要用匈牙利算法找到所有的最大匹配,比较每个最大匹配的权重,
	  再选出最大权重的最优匹配即可得到更贴近真实情况的匹配结果。
	  但这种方法时间复杂度较高,会随着目标数越来越多,消耗的时间大大增加,实际使用中并不推荐。

2.KM算法

KM算法解决的是带权二分图的最优匹配问题。

还是用上面的图来举例子,这次给每条连接关系加入了权重,也就是我们算法中其他模块给出的置信度分值。

KM算法解决问题的步骤是这样的。

  • 第一步

首先对每个顶点赋值,称为顶标,将左边的顶点赋值为与其相连的边的最大权重,右边的顶点赋值为0

  • 第二步:

匹配的原则是只和权重与左边分数(顶标)相同的边进行匹配,若找不到边匹配,对此条路径的所有左边顶点的顶标减d,所有右边顶点的顶标加d。参数d我们在这里取值为0.1。

对于左1,与顶标分值相同的边先标蓝。

然后是左2,与顶标分值相同的边标

然后是左3,发现与右1已经与左1配对。首先想到让左3更换匹配对象,然而根据匹配原则,只有权值大于等于0.9+0=0.9(左顶标加右顶标)的边能满足要求。于是左3无法换边。那左1能不能换边呢?对于左1来说,只有权值大于等于0.8+0=0.8的边能满足要求,无法换边。此时根据KM算法,应对所有冲突的边的顶点做加减操作,令左边顶点值减0.1,右边顶点值加0.1。结果如下图所示。

再进行匹配操作,发现左3多了一条可匹配的边,因为此时左3对右2的匹配要求只需权重大于等于0.8+0即可,所以左3与右2匹配

最后进行左4的匹配,由于左4唯一的匹配对象右3已被左2匹配,发生冲突。进行一轮加减d操作,再匹配,左四还是匹配失败。两轮以后左4期望值降为0,放弃匹配左4。

至此KM算法流程结束,三对目标成功匹配,甚至在左三目标预测不够准确的情况下也进行了正确匹配。可见在引入了权重之后,匹配成功率大大提高。

最后还有一点值得注意,匈牙利算法得到的最大匹配并不是唯一的,预设匹配边、或者匹配顺序不同等,都可能会导致有多种最大匹配情况,所以有一种替代KM算法的想法是,我们只需要用匈牙利算法找到所有的最大匹配,比较每个最大匹配的权重,再选出最大权重的最优匹配即可得到更贴近真实情况的匹配结果。但这种方法时间复杂度较高,会随着目标数越来越多,消耗的时间大大增加,实际使用中并不推荐。


总结:

  • 匈牙利算法和KM算法是进行二分图最大匹配的算法,在目标追踪用于进行目标关联

from scipy.optimize import linear_sum_assignment
import numpy as np
# 代价矩阵
cost =np.array([[1,2,3,4],[2,4,6,8],[3,6,9,12],[4,8,12,16]])
# 匹配结果
row_ind,col_ind=linear_sum_assignment(cost)
#对应的行索引
print("行索引:\n{}".format(row_ind))
#对应行索引的最优指派的列索引
print("列索引:\n{}".format(col_ind))
#提取每个行索引的最优指派列索引所在的元素,形成数组
print("匹配度:\n{}".format(cost[row_ind,col_ind]))
# 行索引:
# [0 1 2 3]
# 列索引:
# [3 2 1 0]
# 匹配度:
# [4 6 6 4]

result=linear_sum_assignment(cost)
print(np.array(list(zip(*result))))
# [[0 3]
#  [1 2]
#  [2 1]
#  [3 0]]


"""
匈牙利算法(Hungarian Algorithm)与KM算法(Kuhn-Munkres Algorithm)
	1.匈牙利算法与KM算法:都是用来解决多目标跟踪中的数据关联问题
	2.匈牙利算法与KM算法:都是为了求解二分图的最大匹配问题
	
二分图
	1.有一种很特别的图,就做二分图,那什么是二分图呢?就是能分成两组,U,V。
	  其中,U上的点不能相互连通,只能连V中的点,同理,V中的点不能相互连通,只能连U中的点。
	  这样,就叫做二分图。
	2.可以把二分图理解为视频中连续两帧中的所有检测框,第一帧所有检测框的集合称为U,
	  第二帧所有检测框的集合称为V。同一帧的不同检测框不会为同一个目标,所以不需要互相关联,
	  相邻两帧的检测框需要相互联通,最终将相邻两帧的检测框尽量完美地两两匹配起来。
	  而求解这个问题的最优解就要用到匈牙利算法或者KM算法。
	  
匈牙利算法
	1.匈牙利算法是一种在多项式时间内求解任务分配问题的组合优化算法。
	2.我们以目标跟踪的方法介绍匈牙利算法,以下图为例,假设左边的四张图是我们在第N帧检测到的目标(U),
	  右边四张图是我们在第N+1帧检测到的目标(V)。
	  红线连起来的图,是我们的算法认为是同一人的可能性较大的目标。
	  由于算法并不是绝对理想的,因此并不一定要保证每张图都有一对一的匹配,
	  出现一对二甚至一对多的情况,再甚至多对多的情况都时有发生。
	  这时我们怎么获得最终的一对一跟踪结果呢?我们来看匈牙利算法是怎么做的。  
	3.匈牙利算法
		1.第一步:
			首先给左1进行匹配,发现左1与其相连的第一个目标右1还未匹配,将其配对,连上一条蓝线。  
		2.第二步:
			接着匹配左2,发现左2与其相连的第一个目标右2还未匹配,将其配对,连上一条蓝线。
		3.第三步:
			1.接下来匹配左3,发现左3与其相连的第一个目标(最优先的目标)右1已经匹配给左1了,怎么办呢?
			  那么我们给之前右1匹配的对象左1分配给另外一个对象,即把左1和右1的匹配关系取消掉,
			  黄色线表示这左1和右1的匹配关系被临时拆掉。
			2.可以与左1匹配的第二个目标是右2,但右2此时也已经有了其匹配对象左2,怎么办呢?
			  我们再给之前右2的匹配对象左2分配给另一个对象(注意这个步骤和上面是一样的,这是一个递归的过程),
			  即把左2和右2的匹配关系取消掉,黄色线表示这左2和右2的匹配关系被临时拆掉。
			3.此时发现左2还能匹配与其相连的第二个目标右3,发现左1还能匹配与其相连的第二个目标右2,
			  最终左2匹配右3,左1匹配右2,左3匹配右1。
		4.第四步:
			最后是左4,很遗憾,按照第三步的节奏我们没法给左4腾出来一个匹配对象,只能放弃对左4的匹配,
			匈牙利算法流程至此结束。蓝线就是我们最后的匹配结果。至此我们找到了这个二分图的一个最大匹配。
			最终的结果是我们匹配出了三对目标,由于候选的匹配目标中包含了许多错误的匹配红线(边),
			所以匹配准确率并不高。可见匈牙利算法对红线连接的准确率要求很高,
			也就是要求我们运动模型、外观模型等部件必须进行较为精准的预测,或者预设较高的阈值,
			只将置信度较高的线(边)才送入匈牙利算法进行匹配,这样才能得到较好的结果。	
			
实现匈牙利算法
	1.API:scipy.optimize.linear_sum_assignment(cost_matrix)
		其中 const_matrix 表示代价矩阵。
		比如第一帧有a,b,c,d四个目标,第二帧图像有p,q,r,s四个目标,其相似度矩阵如下所示.
	2.例子:	
		from scipy.optimize import linear_sum_assignment
		import numpy as np
		# 代价矩阵
		cost =np.array([[1,2,3,4],[2,4,6,8],[3,6,9,12],[4,8,12,16]])
		# 匹配结果
		row_ind, =linear_sum_assignment(cost)
		#对应的行索引
		print("行索引:\n{}".format(row_ind))
		#对应行索引的最优指派的列索引
		print("列索引:\n{}".format(col_ind))
		#提取每个行索引的最优指派列索引所在的元素,形成数组
		print("匹配度:\n{}".format(cost[row_ind,col_ind]))	
		打印结果:
			行索引:
			[0 1 2 3]
			列索引:
			[3 2 1 0]
			匹配度:
			[4 6 6 4]		
	
	3.结论:
		匈牙利算法的流程,有一个很明显的问题,按这个思路找到的最大匹配往往不是我们心中的最优。
		匈牙利算法将每个匹配对象的地位视为相同,在这个前提下求解最大匹配。
		这个和所研究的多目标跟踪问题有些不合,因为每个匹配对象不可能是同等地位的,
		总有一个真实目标是我们要找的最佳匹配,而这个真实目标应该拥有更高的权重,
		在此基础上匹配的结果才能更贴近真实情况。
		KM算法就能比较好地解决这个问题。

KM算法
	KM算法解决的是带权二分图的最优匹配问题。
	还是用上面的图来举例子,这次给每条连接关系加入了权重,权重也就是我们算法中其他模块给出的置信度分值。

KM算法解决带权二分图的最优匹配问题的步骤:
	1.左右两边的图匹配的原则是:
		左右两边的图只和"权重与左边图的分数(顶标)相同的"边进行匹配,
		若左边图根据与其分数(顶标)相同的最大权重的线(边)所连接到的右图已经被分配了某个左图的话,
		那么产生冲突,解决的方式是对产生冲突的左边的两个图的顶标减d,
		然后令产生冲突的右边的一个图的顶点值加d。参数d我们在这里取值为0.1。
		
	2.实现具体步骤:
		1.第一步
			首先对左右两边的每个图(顶点)进行赋值,该值分数称为顶标。
			将左边的每个图(顶点)赋值为与其相连的线(边)的最大权重,右边的每个图(顶点)赋值为0。
		2.第二步:
			1.对于左1,与左1的顶标分值相同的最大权重的边先标蓝,左1连接右1。
			2.对于左2,与左2的顶标分值相同的最大权重的边先标蓝,左2连接右3。
			3.对于左3,与左3的顶标分值相同的最大权重的边所连接的右1已经与左1配对,左3无法直接连接右1,
			  此时产生冲突。
				1.首先想到的是让左3更换匹配对象,然而根据匹配原则,
				  只有权值大于等于(左图顶标加右图顶标)0.9+0=0.9的边能满足左3连接右1的要求,否则无法换边。
				  那么于是左3无法换边。那左1能不能换边(更换匹配对象)呢?
				  对于左1来说,只有权值大于等于(左图顶标加右图顶标)0.8+0=0.8的边能满足左1连接右1的要求,
				  否则无法换边。
				2.此时根据KM算法,应对产生冲突的左右两边的图的顶点做加减操作,
				  首先令产生冲突的左边的两个图的顶点值减0.1,然后令产生冲突的右边的一个图的顶点值加0.1。
				3.此时发现左3多了一条可匹配的边,因为此时左3连接右2的匹配要求能满足权重大于等于
				  (左图顶标加右图顶标)0.8+0=0.8,所以左3与右2匹配。
			4.最后进行左4的匹配,由于左4唯一的可匹配对象右3已被左2匹配,此时发生冲突。
			  左右两边发生冲突的图进行一轮加减d的操作,再进行匹配,此时左四还是匹配右3失败。
			  当经过一共两轮的加减d的操作后发现左4的顶标降为0,左4放弃继续匹配。

	3.至此KM算法流程结束,三对目标成功匹配,甚至在左三目标预测不够准确的情况下也进行了正确匹配。
	  可见在引入了权重之后,匹配成功率大大提高。
      最后还有一点值得注意,匈牙利算法得到的最大匹配并不是唯一的,预设匹配边、或者匹配顺序不同等,
	  都可能会导致有多种最大匹配情况,所以有一种替代KM算法的想法是,
	  我们只需要用匈牙利算法找到所有的最大匹配,比较每个最大匹配的权重,
	  再选出最大权重的最优匹配即可得到更贴近真实情况的匹配结果。
	  但这种方法时间复杂度较高,会随着目标数越来越多,消耗的时间大大增加,实际使用中并不推荐。
"""

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
匈牙利算法,也称为二分图最大匹配算法,是一种解决二分图最大匹配问题的经典算法。它的目标是在一个二分图中找到最大的匹配数,即找到最大的能够互相配对的节点对数。 Python是一种高级编程语言,具有简洁、易读、易学的特点,广泛应用于各个领域。在Python中,我们可以使用网络流算法库或者自己实现匈牙利算法来解决二分图最大匹配问题。 以下是匈牙利算法的基本思想和步骤: 1. 初始化一个空的匹配集合。 2. 对于每个未匹配的左侧节点,尝试将其与一个未匹配的右侧节点进行匹配。 3. 如果右侧节点未被匹配,或者已被匹配但可以通过其他路径重新匹配,那么将左侧节点与右侧节点进行匹配,并将右侧节点标记为已匹配。 4. 如果右侧节点已被匹配且无法重新匹配,那么尝试将右侧节点的当前匹配节点重新匹配到其他未匹配的左侧节点。 5. 重复步骤3和步骤4,直到无法找到更多的匹配。 在Python中,可以使用networkx库来实现匈牙利算法。以下是一个使用networkx库解决二分图最大匹配问题的示例代码: ```python import networkx as nx # 创建一个空的二分图 G = nx.Graph() # 添加左侧节点 G.add_nodes_from(['A', 'B', 'C']) # 添加右侧节点 G.add_nodes_from([1, 2, 3]) # 添加边 G.add_edges_from([('A', 1), ('A', 2), ('B', 2), ('C', 3)]) # 使用匈牙利算法求解最大匹配 matching = nx.bipartite.maximum_matching(G) # 输出最大匹配结果 print(matching) ``` 以上代码中,我们首先创建了一个空的二分图,并添加了左侧节点和右侧节点。然后,我们使用`nx.bipartite.maximum_matching`函数来求解最大匹配,并将结果存储在`matching`变量中。最后,我们输出最大匹配结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

あずにゃん

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值