首页 > 编程语言 >一文带你搞懂匈牙利算法

一文带你搞懂匈牙利算法

时间:2024-03-29 21:36:44浏览次数:31  
标签:二分 匹配 一文 增广 匈牙利 路径 算法 搞懂

一文带你搞懂匈牙利算法

image

附赠自动驾驶学习资料和量产经验:链接

什么是匈牙利算法

最近在研究一个比较有意思的应用—车辆追踪算法。传统的车辆追踪算法是基于检测器检出车辆,之后使用卡尔曼滤波和匈牙利算法来进行位置预测与数据级联的。关于卡尔曼滤波,我之前已经写过一篇文章进行了详细的介绍;最近则是在研究匈牙利算法是如何工作的。这里简单的记录一下相关原理。

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

在车辆追踪中,匈牙利算法(Hungarian Algorithm)与KM算法(Kuhn-Munkres Algorithm)都是用来解决多目标跟踪中的数据关联问题,而数据关联问题,亦可转化为求解二分图的最大匹配问题。二分图的最大匹配问题听起来很绕口,这里如何理解呢?换句话说,就是求解任务分配问题,也叫指派问题,即n项任务,对应分配给n个人去做,应该由哪个人来完成哪项任务,能够使完成效率最高。

这里举一个例子

image

从图上可以看到,不同的车和人,之间的距离是不一样的。那么如果正确的把对应的车和对应的人匹配起来呢?这时候就需要用到匈牙利算法。

一个关于匈牙利算法的例子

这里我们使用一个例子来说明如何使用匈牙利算法

假设你有4个检测框(简写为det),对应于四个相应的追踪轨迹(简写为tracking), 给定相应之间的距离(稍后会讲到怎么算这个距离),那么如何匹配检测框与对应的追踪轨迹呢?

image

我们可以采用这样几个步骤来进行匹配

  1. 按照行,减去本行最小值

  2. 按照列,减去本列最小值

  3. 尝试以最少数量的线条划掉所有零;如果这个数量大于等于矩阵的行列数,那么跳到第五步

  4. 在剩下的矩阵中,减去最小值;如果有零被交叉,那么把这个最小值加上去,然后重复第三步

  5. 从只有一个零的行开始一一对应,对应完则整个行列删除

image

image

详细的执行步骤可以看一下这里的两张图,有比较清晰的描述。

最终结果: det_A->D det_B->A det_C->B det_D->C, 这里 -> 代表 “匹配”的意思。

额外要注意的是,这里我们求解的矩阵是N * N的,如果对应矩阵是 M * N的话,需要给少的维度补齐,补的值是当前矩阵中的最大值即可。

匈牙利算法原理与实现

接下来,我们简单聊一下匈牙利算法的原理和实现。

匈牙利算法一般是在二分图(Bipartite graph)这样的数据结构上实现的。这种图的名字可以看到,会把图中元素一分为二,其中顶点分为两两不相交的集合,并且同属于一个集合内的点两两不相连。

image

那么如何基于二分图(也叫二部图)判断匹配呢?这里我们说两条边匹配,即为存在两条边e1,e2,有e1,e2的顶点不相交,即为成功匹配。反之,如果相交了,代表的情况就是同一个人完成两个任务,这不符合匹配的要求,具体例子可以看下图。

image

这里,我们有边 e1 连接 点1和点5, e6连接 点4和点7,且各点之间不相交;红色边表示成功的匹配,被称为匹配边,匹配边所连接的点被称为匹配点。同样可以定义非匹配边和非匹配点(也就是顶点相交)

接下来,我们再给出最大匹配的定义:如果给定的二分图里面,有若干边不相交(形成若干匹配),且匹配数量达到这个二分图里所有可能匹配的最大值,那么我们认为这个二分图对应的匹配达到最大匹配(Maximum Matching)。图中 {e2,e3,e5,e7} 即为其中一组最大匹配。

image

此外有关于二分图(也属于图的定义),还有两个常常提到的定义,这里简单做一下介绍。

交错路径:图匹配结果中,如果相邻两条边性质不同,也就是出现匹配边->非匹配边->匹配边 相互交错的情况,那么我们说存在交错路径。假设 {e2, e7}相互匹配,我们有 {e1,e2,e6,e7}为交错路径。

增广路径:如果一条路径的首尾是非匹配点,路径中除此之外(如果有)其他的点均是匹配点,那么这条路径就是一条增广路径(Agumenting path)。也就是说,从一个非匹配点出发,走交错路径到另一个非匹配点(保证了两边的边为非匹配边)。这里假设{e1, e6}相互匹配,我们有 {e7,e6,e2,e1,e3}为增广路径。

从增广路径的定义可以看到,增广路径的首尾是非匹配点。因此,增广路径的第一条和最后一条边,必然是非匹配边;由交错路径的定义可知,增广路径从非匹配边开始,匹配边和非匹配边依次交替,最后由非匹配边结束。这样一来,增广路径中非匹配边的数目总比匹配边大 1。考虑置换增广路径中的匹配边和非匹配边,由于增广路径的首尾是非匹配点,其余则是匹配点,这样的置换不会影响原匹配中其他的匹配边和匹配点,因而不会破坏匹配;而增广路径的置换,可使匹配的边数加1,得到比原有匹配更大的匹配。

由于二分图的最大匹配必然存在(比如,上限是包含所有顶点的完全匹配),所以,在任意匹配的基础上,如果有办法不断地搜寻出增广路径,直到最终我们找不到新的增广路径为止。具体来说,每次找到增广路径,就尝试进行替换,使得匹配边数+1。最后就有可能得到二分图的一个最大匹配。这也是匈牙利算法的设计思路。

这里我们再举一个例子来进一步理解这个问题。

image

这里假设1-4是任务, 5-8是对应要干活的人,我们对应的可以这么分配任务:5->2, 6->3, 7->4

这样子做之后,只有8无法分到任务,这个时候并没有实现最佳匹配。因此,我们进一步的考虑交错路径 1->7; 7->4; 4->8中间是匹配边,其余是非匹配边,而且非匹配=匹配边+1。这时我们尝试交换匹配边与非匹配边,则有1->7, 4->8匹配, 这就找到了最大匹配。

匈牙利算法代码示例

这里提供一个使用python已有库计算匈牙利算法的代码片段,输入数据和“一个关于匈牙利算法的例子”一节中的输入数据一样,我们把这个输入数据叫做 cost_matrix。

import numpy as np
from scipy.optimize import linear_sum_assignment
cost_matrix = assignment.values.copy()
print("cost matrix is: ")
print(cost_matrix)
matches = linear_sum_assignment(cost_matrix)
print("find available matches: {}”.format(matches))

匈牙利算法中如何计算权重(距离)

现在我们尝试把匈牙利算法应用的车辆追踪任务上,这里主要介绍数据关联相关的内容。

使用匈牙利算法,最为重要的是去了解当前追踪问题对应的cost matrix,也就是损失矩阵。那么如果对损失矩阵进行计算呢?这里我们介绍三种常见的方法:

* 基于欧氏距离进行匹配;给定两帧中目标框的中心点,直接计算其中心点的欧式距离,需要迭代MXN次。如果目标形态发生变化,或目标间有重叠,那么效果相应的会受很大影响。

* 计算车辆之间的IOU值并进行计算,取最大值为合理匹配。然而匈牙利算法的目标是最小化损失,而IOU是越大越好,所以两者不相符合。解决方法是,找到待求解矩阵中的最大值,依次减去全部元素,然后继续求解即可

* 使用外观相似度进行判断。可以加入了外观信息,借用了ReID领域模型来提取特征,使用生成的特征来判断相似度。这样子的做法减少了ID switch。

实际进行损失计算,会同时考虑2和3,加权进行计算以获取最终匹配结果。

小结

匈牙利算法是一种二分图匹配算法,常用于二分图的最大匹配。数据追踪任务中,可以使用匈牙利算法进行数据关联,在物体匀速场景下配合卡尔曼滤波,会起到很好的作用。限于匈牙利算法本身是求二分图下最大结果,与数据级联要求的最小损失有冲突,实际使用是会额外追加限制或进行条件转化,使得匈牙利算法可以用于车辆追踪场景下的最优结果匹配。

匈牙利算法并不需要我们手写代码。在了解如何计算损失并可以生成损失矩阵的情况下,可以套用scipy或scikit-learn已有库来直接求解,相对来说还是比较方便的。

标签:二分,匹配,一文,增广,匈牙利,路径,算法,搞懂
From: https://www.cnblogs.com/autodriver/p/18104648

相关文章

  • 数学建模智能算法
    模拟退火算法%生成初始解,求目标函数f(x)=x1^2+x2^2+8在x1^2-x2>0;-x1-x2^2+2=0约束下的最小值问题sol_new2=1;%(1)解空间(初始解)sol_new1=2-sol_new2^2;sol_current1=sol_new1;sol_best1=sol_new1;sol_current2=sol_new2;sol_best2=sol_new2;E_c......
  • 一文搞懂Python的数据结构-列表
    大道至简:任何技术都来源于生活,每一个技术点都是为了解决生活场景中的某个问题1/Python列表基础1.1什么是列表?从生活场景说起,购物清单=列表当我们去购物时,我们通常会准备一个购物清单,其中列出了我们需要购买的物品。这个购物清单就是一个列表的实际应用。你可......
  • 遗传算法(matlab)
    %求下列函数的最大值%%f(x)=10*sin(5x)+7*cos(4x)x∈[0,10]%%将x的值用一个10位的二值形式表示为二值问题,一个10位的二值数提供的分辨率是每为(10-0)/(2^10-1)≈0.01。%%将变量域[0,10]离散化为二值域[0,1023],x=0+10*b/1023,其中b是[0,1023]中的一个......
  • 一文带你搞懂RTK定位
    一文带你搞懂RTK定位附赠自动驾驶学习资料和量产经验:链接说到定位,相信大家一定不会觉得陌生。如今我们所处的信息时代,人人都有手机。每天,我们都会用到与地图和导航有关的APP。这些APP,就是基于定位技术的。说到定位技术呢,大家又肯定会想到GPS、北斗这些名词。是的,这些都属于全......
  • 代码随想录算法训练营第6天 | 哈希表
    哈希表理论基础用法:一般哈希表都是用来快速判断一个元素是否出现集合里,哈希法牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找eg:例如要查询一个名字是否在这所学校里,要枚举的话时间复杂度是O(n),但如果使用哈希表的话,只需要O(1)就可......
  • 硬件算法协同优化-嵌入式深度学习3
    嵌入式深度学习-硬件与算法协同优化本系列博客主要以BertMoons《EmbeddedDeepLearning》翻译而成GoetschalckxK,MoonsB,LauwereinsS,AndraudM,VerhelstM(2018)Optimizedhierarchicalcascadedprocessing.IEEEJEmergingSelTopCircuitsSyst.https://doi.o......
  • 代码随想录算法训练营第六十天 | 84.柱状图中最大的矩形
      84.柱状图中最大的矩形 已解答困难 相关标签相关企业 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为1。求在该柱状图中,能够勾勒出来的矩形的最大面积。 示例1:输入:heights=[2,1,5,6,2,3]输出:10......
  • 机器人姿态估计-IMU、互补滤波算法应用+C代码实现
    机器人姿态估计-IMU、互补滤波算法应用附赠自动驾驶学习资料和量产经验:链接机器人的姿态测量对于许多应用至关重要,如导航、运动控制等。在这篇文章中,我们将介绍如何利用MPU6050传感器以及互补滤波和卡尔曼滤波算法来实现自平衡车的姿态测量。我们将从原理出发,逐步介绍互补滤波......
  • 代码随想录算法训练营第二十四天(回溯1)|77. 组合(JAVA)
    文章目录回溯理论基础概念类型回溯模板77.组合解题思路源码回溯理论基础概念回溯是递归的副产品,本质上是一种穷举回溯解决的问题可以抽象为一种树形结构类型回溯主要用来解决以下问题组合问题:N个数里面按一定规则找出k个数的集合切割问题:一个字符串按一定......
  • 代码随想录算法训练营第二十三天(二叉树9)|669. 修剪二叉搜索树、108. 将有序数组转换为
    文章目录669.修剪二叉搜索树解题思路源码108.将有序数组转换为二叉搜索树解题思路源码538.把二叉搜索树转换为累加树解题思路源码669.修剪二叉搜索树给你二叉搜索树的根节点root,同时给定最小边界low和最大边界high。通过修剪二叉搜索树,使得所有节点的值......