【评价方案】目标检测TP,FP,以及perception recall,以及AP,mAP

news/2024/7/10 1:38:53 标签: 目标检测, 计算机视觉, 人工智能

20230116:网上好多TP,FP,都感觉有点问题,特意研究了源代码,写下理解。

第一步:需要确定计算TP的准则

一般情况,我们设定Iou_threadhold 阈值∈[0.5,0.55,0.6,0.65,0.7,0.75,0.8,0.85,0.9,0.95],这基于IoU阈值的情况下,计算当前检测结果Dt 与 真值Gt之间的IoU,大于阈值,则算是TP。小于阈值否则视为FP。TP+FP = 全部Dt数量

也可以自定义相关TP的准则,例如我们要求模型需要输出confidence,需要输出位置,速度。confidence需要>0.3,位置与真值需要小于0.1米,速度需要小于0.5m/s,才认为是TP。

参考了:what-is-map-understanding-the-statistic-of-choice-for-comparing-object-detection-models

第二步骤,基于TP数量,基于检测到的数量,基于真值数量,计算FP、FN、TN

基于以下理解,

全部的真值标注框的数量 num_gt,全部检测的框数量为num_dt

True Positive (TP): 检测存在,真值存在,真值标注框与检测框的Iou大于阈值;
False Positive (FP): 检测存在,真值不存在,真值标注框与检测框的Iou小于阈值;
所以:fp_num = num_dt - tp_num

False Negative (FN): 检测不存在,真值是存在,
所以:fn_num = num_gt - tp_num

For calculating Recall, we need the count of Negatives. Since every part of the image where we didn’t predict an object is considered a negative, measuring “True” negatives is a bit futile. So we only measure “False” Negatives ie. the objects that our model has missed out.

True Negative (TN): 检测是不存在,真值不存在。在 mAP 评价指标中不会使用到。

Negative 和Positive 是相对于检测器的Dt而言,Dt输出的是Positive 或者 Negative。
用真值去考核Dt输出的结果为True或者False。

第三步骤:计算整体的Precision 和 Recall

Precision = tp_num / num_dt
Recall = tp_num / num_gt

等价

Precision = tp_num /(tp_num +fp_num )
Recall = TP/(tp_num +fn_num )

计算 AP

AP:在某个IoU阈值下,PR 曲线下面积。
mAP:Iou_threadhold 阈值∈[0.5,0.55,0.6,0.65,0.7,0.75,0.8,0.85,0.9,0.95] 的情况下,可以分别得到AP值,mean Average Precision,即各类别 AP 的平均值。

PR曲线的绘制方法

这篇目标检测中PR曲线和mAP文章,我个人认为有点错误。

我按照源代码的步骤:
假设:目前有101张图片,共有真值 num_gt 397;IoU阈值0.5-0.95,每0.05取一个,共10个;(通过NMS后)输出的检测目标框 2944;
1、每个框的置信度 scores 的尺寸1×2944
2、计算TP的情况:首先设定self.tps 尺寸 101 ×10 ×n,101是图片数量,n是每个图片detection的检测到的框的数目,10是0.5-0.95的Iou阈值。self.tps 里面只存储False或者True。
3、对self.tps 转换到 10 ×2944

tps = torch.cat(self.tps, dim=1)

4、对 score进行排序,

  scores = torch.cat(self.scores, dim=0)
  scores, sortidx = torch.sort(scores, dim=0, descending=True)# 全部的图片的全部检测的框的得分排序

5、对TP进行排序,按照score进行排序

tps = tps[:,sortidx]

返回结果:sortidx tensor([2902, 2922, 2703,  ..., 1245, 1546, 2901])   

6、tps 的尺寸还是 10 ×2944,10行,2944列
7、对tps 的每一列的2944个,累加计算 True 的数目

		tp_sum = torch.cumsum(tps, dim=1)

        print("tp_sum",tp_sum.shape[0],tp_sum.shape[1])
        print("tp_sum0",tp_sum[0][0])
        print("tp_sum100",tp_sum[0][100])
        print("tp_sum1000",tp_sum[0][1000])
        print("tp_sum1000",tp_sum[0][-1])
返回结果:
tp_sum 10 2944
tp_sum0 tensor(1.)
tp_sum100 tensor(48.)
tp_sum1000 tensor(126.)
tp_sum1000 tensor(144.)

这里特别说明下, torch.cumsum返回维度dim中输入元素的累计和,维度保持不变,输出的第一个数据和输入一致,输出最后的数据为输入数据的全部的和.

例如
一维数据:

    x1 = torch.arange(0, 6)
    print(x1)
    y1 = torch.cumsum(x1, dim=0)  
    print(y1)
    

在这里插入图片描述
结果分析:

y1(dim=0)的结果是:第一列不变,后面的列依次在上一列基础上加上自身的数。
第1列,值0,不变,和为本身,即:0;
第2列,值1,累加前一列值0,和为:0+1=1
第3列,值2,累加前一列值1,和为:1+2=3
第4列,值3,累加前一列值3,和为:3+3=6
第5列,值4,累加前一列值6,和为:6+4=10
第6列,值5,累加前一列值10,和为:10+5=15

8、计算fp的情况, tp+fp =2944,所以,直接可以取反得到fp数目

fps = ~tps

9、对 fps 的每一列的2944个,累加计算True的数目

        print("tp_sum0",fp_sum[0][0])
        print("tp_sum100",fp_sum[0][100])
        print("tp_sum1000",fp_sum[0][1000])
        print("tp_sum1000",fp_sum[0][-1])
返回结果
tp_sum0 tensor(0.) 
tp_sum100 tensor(53.)  
tp_sum1000 tensor(875.)
tp_sum1000 tensor(2800.)

10、计算precision 和 recall

        precision = tp_sum / (tp_sum+fp_sum)
        recall = tp_sum / num_gt
        print("num_gt",num_gt)
        print("precision",precision.shape[0],precision.shape[1])
返回结果
num_gt 397                                                                                                                                                                                                                                   precision 10 2944 

11、初始化PR图片

self.rec_thres = 100
PRcurve = torch.zeros(len(self.iou_thres),len(self.rec_thres))

12、在PR 中填入precision 和 recall,但是要保证图片是单调递减的

        for ti, (prec_T,rc_T) in enumerate(zip(precision, recall)):
            # 保证了单调降低
            for i in range(num_dt-1,0,-1):
                if prec_T[i] > prec_T[i-1]:
                    prec_T[i-1] = prec_T[i]
            # find the 100 recall points
            idxs = np.searchsorted(rc_T, self.rec_thres, side='left')
            # fill in the P-R curve
            for ri,pi in enumerate(idxs):
                if pi >= len(prec_T):
                    # reach the upper bound of Recall
                    break
                PRcurve[ti,ri] = prec_T[pi]

13、返回AP的结果,尺寸10×1

APs = self.PRcurve.mean(dim=1)
# 将10× 100的PR表格,压缩到10×1

14、返回最佳阈值

f1 = 2 * (precision*recall) / (precision + recall)
self.best_thres = scores[torch.argmax(f1, dim=1)]

结束
代码,可以参考我的一份gitee代码

other

(1)交并比 - Intersection Over Union (IOU)

交并比(IOU)是度量两个检测框(对于目标检测来说)的交叠程度,公式如下:
在这里插入图片描述
B_gt 代表的是目标实际的边框(Ground Truth,GT),B_p 代表的是预测的边框,通过计算这两者的 IOU,可以判断预测的检测框是否符合条件,IOU 用图片展示如下:
在这里插入图片描述


http://www.niftyadmin.cn/n/213617.html

相关文章

对ELK的理解

什么是ELK ELK是一套针对日志数据做解决方案的框架,由三款产品组成:ElasticSearch(ES)、Logstash、Kibana。 ElasticSearch负责日志的存储和检索。Logstash负责日志的收集、过滤和格式化。Kibana则负责日志的展示统计和数据可视…

回溯算法--01背包问题

目录 回溯算法--01背包问题 [算法描述] [回溯法基本思想] 法一: 法二: 代码: 运行结果 代码改进 回溯算法--01背包问题 [算法描述] 0-1背包问题是子集选取问题。一般情况下,0-1背包问题是NP完全问题。0-1背包问题的解空…

maven报错: ‘parent.relativePath‘ of POM xxx

错误信息: parent.relativePath of POM io.renren:renren-fast:3.0.0 (D:\renren-fast\pom.xml) points at com.gwh:gulimall instead of org.springframework.boot:spring-boot-starter-parent, please verify your project structure引入人人开源的后台管理系统&…

Maven项目的JDK版本不一致引发的问题

1.运行提示java: 错误: 不支持发行版本 5&#xff08;改成JDK8&#xff09; 2.运行提示java&#xff1a;-source 8 中不支持 instanceof 中的模式匹配(改成JDK17) 解决方案&#xff08;以JDK8为例&#xff09; 1.普通Maven项目 通过指定Maven插件的JDK版本解决 <build>…

cgroups是linux内核中限制、记录、隔离进程组(process groups)所使用的物理资源的机制

容器虚拟化 可以实现应用程序的隔离 直接使用物理机的操作系统可以快速响应用户请求 不占用部署时间 占用少量磁盘空间 缺点∶学习成本增加、操作控制麻烦、网络控制与主机虚拟化有所区别、服务治理难。 微服务架构师需要会多门编程语言&#xff0c;才能治理各种服务 三种…

2023年腾讯云轻量服务器和5年CVM云服务器规格性能测评

腾讯云服务器分为轻量应用服务器和云服务器CVM&#xff0c;云服务器地域大多数北京、上海、广州这种中国大陆地域&#xff0c;这是2023年腾讯云轻量服务器和5年CVM云服务器规格性能测评。 2023年腾讯云3年轻量服务器和5年CVM云服务器规格性能测评 1、目前五年时长的云服务器CV…

vue 高德地图获取鼠标点击经纬度

新建 components/amap.vue&#xff0c;封装高德地图组件&#xff1a; <template><div id"amapcontainer" style"width: 1000px; height: 720px"></div> </template><script> import AMapLoader from amap/amap-jsapi-loade…

为什么电脑无限重启,难道是我的电脑装了无限宝石?

本来以为旧电脑容易出毛病&#xff0c;可万万没想到一款新电脑也能无限重启。下面&#xff0c;驱动人生就为大家带来电脑无限重启的解决方法。 我们要明确一个问题&#xff1a;为什么电脑会无限重启呢&#xff1f;简单来说&#xff0c;有两个主要的原因。第一种情况是硬件故障…