【行人检测】miss rate versus false positives per image (FPPI) 前世今生(实战篇-上)

上文我们说到【行人检测】miss rate versus false positives per image (FPPI) 前世今生(理论篇),今天我们来跑通作者绘制FPPI图的代码以及源码解读
(第一、二、三、四都在上一篇文章中,所以这篇文章直接从五开始)


五、miss rate versus false positives per image (FPPI) 官方绘制方法

接下来我们用作者提供的数据,跑通作者绘图的代码

(很多人可能会好奇,python现在这么热门,居然不是用python画的,主要原因有两个:1. 因为原作者提供的代码就是matlab的;2. 因为我在网上没有找到一个比较靠谱的python写法,所以目前先只讨论matlab版的。如果后续看到有比较好的python版画法,我再加上吧)

1. 安装第三方工具包

按照这篇文章Caltech评估方法0 安装步骤安装

2. 下载annotations和res

annotations是数据集的ground truth,res是模型的预测

下载地址:https://drive.google.com/drive/folders/1IBlcJP8YsCaT81LwQ2YwQJac8bf1q8xF

两个都要下载
在这里插入图片描述
文件放置如图所示(res文件夹需要自己你新建):在这里插入图片描述
annotations压缩包解压到../code3.2.1/data-USA中,annotations文件内如图所示:
在这里插入图片描述
res文件里的所有压缩包分别解压到独立文件夹中,并放在../code3.2.1/data-USA/res中,res文件内如图所示:

在这里插入图片描述
如果你觉得下载annotations和res嫌麻烦的话,可以直接下载我的这个,直接运行dbEval.m就好了

下载地址:miss rate versus false positives per image(FPPI)绘制代码

3. 运行绘图代码

绘图工具的代码地址在:http://www.vision.caltech.edu/Image_Datasets/CaltechPedestrians/

在Download标题下的Matlab evaluation/labeling code (3.2.1).,解压后里面有个dbEval.m文件,这个文件就是主要用来绘制FPPI曲线的。

打开dbEval.m,将第136行的GDFL算法注释掉,不然会报错

在这里插入图片描述

dbEval.m第292行前加一句:

saveas(gcf, './results/mr-fppi.png')

并且注释掉第293~297行的代码,如下图所示

在这里插入图片描述
然后运行dbEval.m,第一遍运行的时候会有点久,成功后results文件夹下输出名叫mr-fppi.png的图片(results文件夹是自动生成的)

在这里插入图片描述
因为算法太多了,所以legend框中只显示了一部分
在这里插入图片描述
如果模型更新了,想重新检测的话,记得把原本生成的results文件夹删掉,否则的话就会一直重新读取原本的FPPI图

以上,就是跑通作者绘图的代码的过程

六、代码解读

接下来,我们把FPPI绘图原理和dbEval.m代码给对应上

1. 首先看看有哪些函数
  1. function dbEval:主函数,评估并绘制所有行人检测结果
  2. function res = evalAlgs( plotName, algs, exps, gts, dts ):在每个实验中评估每种算法
  3. function plotExps( res, plotRoc, plotAlg, plotNum, plotName, …
    samples, lims, colors, styles ):绘制所有的ROC或PR曲线
  4. function plotBbs( res, plotName, pPage, type ):给定algs/exps,绘制fp/tp/fn样本的检测框
  5. function plotBbSheet( bb, ind, bbo, varargin ):画检测框
  6. function A = loadVbb( s, v ):加载给定的annotation
  7. function gts = loadGt( exps, plotName, aspectRatio, bnds ):对于所有帧,加载所有试验的grouth truth
  8. function dts = loadDt( algs, plotName, aspectRatio ):对于所有帧,加载所有算法的检测结果
2. 看看主函数的流程
  1. 设置实验类型exps
  2. 设置每种算法的名字及是否需要rescale height of each box、对应曲线的颜色、线性algs
  3. 设置数据集名称dataNames
  4. 参数选择:
  • 需要验证的数据集dataNames
  • 进行的实验种类exps
  • 用到的算法algs
  • 检测框的默认纵横比aspectRatio
  • 丢弃超出此像素范围的检测框bnds
  • 是否画ROC曲线或PR曲线plotRoc
  • 是否为每一个算法一张图或者每一个实验一张图plotAlg
  • 是否只显示最佳的plotNum曲线plotNum
  • 曲线下计算面积的样本范围samples
  • ROC曲线的坐标范围lims
  • 是否可视化每个算法或每个实验的样本bbsShow
  • 可视化的种类(fp/tp/fn/dt)bbsType

在这里插入图片描述
5. 接下来是一个大的for循环,在for循环中完成图片的绘制,这个for循环是真针对数据集来循环的,因为我们目前只有一个数据集,所以相当于只跑了一遍

所以上面的流程中,前面都是在设置参数,比较关键的就是for循环

3. 看看for循环内部的流程
  1. 选择拥有当前这个数据集检测结果的算法,若有则变量keep对应位置为1,否则为0
  2. 处理特定于数据库的特殊情况,我们的数据集UsaTest是不会经过这一步的
  3. 设置绘图文件的保存名称及保存地址
  4. 加载检测结果函数loadDt、加载ground truth函数loadGt、计算评估结果函数evalAlgs
  5. 绘制曲线函数plotExps
  6. 可视化检测框函数plotBbs(默认是不可视化的)

所以上面的流程中,比较关键的就是计算评估结果函数evalAlgs和函数plotExps

4. 看看评估结果函数evalAlgs内部的流程

函数的input为:

  • 保存文件的名称plotName
  • 算法种类algs
  • 试验种类exps
  • 该数据集上的ground truthgts及检测结果dts

gts是一个1*1的cell,表示评估一种实验类型。这个cell内部的维度是1*4024,表示这个数据集中有4024张图片。
dts是一个1*78的cell,表示涉及到78种算法。这个cell内部的维度是1*4024,表示这个数据集中有4024张图片。

函数的output为res,包含四列:

  • 算法名称
  • 实验名称
  • gtr:每一帧ground truth的结果,具体为[x y w h match]
  • dtr:每一帧检测的结果,具体为[x y w h score match]

gtrdtr中的match为一个匹配标志位,表示是否有检测结果dt检测到ground truthgt或是否有ground truthgt对应这个检测结果dt,用于统计后续的fp、fn、tp:

  • 对于gt: -1=ignore, 0=fn [unmatched], 1=tp [matched]
  • 对于dt: -1=ignore, 0=fp [unmatched], 1=tp [matched]

在下面的评估函数bbGt中会有具体解释。
在这里插入图片描述
我们可以看到,函数evalAlgs最主要是两个嵌套的for循环,第一个nGt的循环表示根据实验类型循环,第二个nDt的循环表示根据算法类型循环。由此得到每一种算法在每一种实验类型下的检测评估结果。

在这里插入图片描述
我们直接看最里层nDt的循环在做什么:

  1. 读取某一实验种类ground truth和某一种算法的检测结果、算法名称、实验名称
  2. 设置保存文件的名称、显示当前验证进度
  3. 根据实验种类,设置检测框的height的阈值,并且从所有检测结果中,提取出符合height阈值范围的检测框
  4. 通过函数bbGt('evalRes',gt,dt,exps(g).overlap),计算ground truth与检测结果的匹配程度,并保存到res

所以上面的流程中,比较关键的就是函数bbGt,前面的设置主要是为了各种实验类型、算法而准备的。

函数bbGt其实内部还有很多个函数,因为用的是参数'evalRes',所以实际调用的是函数[gt,dt] = evalRes( gt0, dt0, thr, mul ),所以我们来看看函数evalRes

5. 看看函数evalRes内部的流程

函数的input为:

  • ground truthgt0:维度为m*5,m为实际的行人数量,每一行为[x y w h ignore]。
  • 检测结果dt0:维度为n*5,n为输出的检测框数量,每一行为[x y w h score]
  • thr表示重合程度的阈值,因为判断一个框是否真的检测到某一行人,还需要判断ground truth和检测结果之间的IoU,所以需要用到重合程度的阈值
  • mul:每个gt是否允许匹配多个dt,默认为0不可

[x y w h]分别为左上角的x坐标、左上角的y坐标、框的宽度、框的高度。

ignore表示这个ground truth是否需要忽略,若为1,则评估的性能的时候忽略这个ground truth。为什么要有ignore呢,因为在论文中作者分别评估了不同类型的行人,例如评估near scale的行人时,不满足near scale的行人就需要忽略掉,ignore设置为1
在这里插入图片描述

函数的output为:

  • gt:维度为m*5,m为实际的行人数量。对于gt,第五列: -1=ignore, 0=fn [unmatched], 1=tp [matched]
  • dt:维度为n*5,n为输出的检测框数量。对于dt,第五列: -1=ignore, 0=fp [unmatched], 1=tp [matched]

因为对于每一张图片来说,计算gtdt匹配程度的方式是一样的,而由于我们输进这个函数数据格式是一个元胞、每个元胞表示一张图片的结果,所以作者通过递归的写法,把每一张图片的信息分别取出来去算gtdt匹配程度(感觉这段代码作者是在秀操作啊)

在这里插入图片描述

针对每一张图片,计算gtdt匹配程度的流程为:

  1. 检测框按照置信度降序排列
  2. 计算所有ground truth与所有检测框之间的IoU
  3. 对于每一个的检测框,遍历每个ground truth
    1. 判断这个ground truth是否已经被匹配了,若是则遍历下一个ground truth;若否则继续往下
    2. 判断这个检测结果是否已经找到最佳匹配,若是则为下一个检测框找匹配;若否则继续往下
    3. 判断IoU是否满足IoU阈值条件,若不满足,则遍历下一个ground truth;若是则继续往下
    4. 将最佳匹配的ground truth与检测框标记为1,即“已匹配”

通过上面的流程,我们就可以找到所有的tp、fn、fp了,因为求tp、fn、fp的过程本质就是在计数:

  • gt中匹配成功的,就是成功检测出来的行人,即tp
  • gt中没有匹配成功的,就是漏掉的行人,即fn
  • dt中没有匹配成功的,就是明明没有行人却认为有行人,即fp
6. 看看函数`plotExps``内部的流程

函数的input为:

  • res评估的结果
  • 画图种类的参数:plotRocplotAlgplotNumplotName
  • 综合评估的参数samples
  • 图形的参数limscolorsstyles

第一步,对于每一种实验、每一种算法,计算其ROC需要用到的x点、y点、综合评分score

[xs{g,d},ys{g,d},~,score] = ... bbGt('compRoc',res(g,d).gtr,res(g,d).dtr,plotRoc,samples);
在这里插入图片描述

此时返回的xs表示x轴FPPI、ys表示TPR。我们知道在FPPI曲线中,y轴其实是miss rate,那怎么办呢,也很简单,作者通过ys{g,d}=1-ys{g,d}将TPR变成了miss rate。

TPR就是recall!miss rate = 1 - reacall = 1 - TPR!!!忘了的朋友请回到上一篇文章的《四、由ROC曲线得到FPPI曲线》再复习下【行人检测】miss rate versus false positives per image (FPPI) 前世今生(理论篇)

综合评分score指理论篇中提到的量化评价指标,是9个参考点处的miss rate。

例如在代码中,9个参考点的选取方式为samples = 10.^(-2:.25:0),即范围从 1 0 − 2 10^{-2} 102 1 0 0 10^{0} 100之间,均匀地取9个fppi值
在这里插入图片描述
然后再找到这9个fppi值对应的miss rate值
在这里插入图片描述
然后通过score=exp(mean(log(score)))变成一个值,即log-average miss rate

第二步,根据plotName,提取前N个分数最高的算法相关数据

第三步,绘制图形,并调整为图片的细节,例如坐标轴、字体大

以上,就是FPPI绘图代码的解读。


在下一篇文章中【行人检测】miss rate versus false positives per image (FPPI) 前世今生(实战篇-下),我们将介绍如何通过使用自己的数据,绘制FPPI图

猜你喜欢

转载自blog.csdn.net/weixin_38705903/article/details/109684244