• 基础学习1_目标检测的评估标准


    主要参考:
    书籍《深度学习之PyTorch物体检测实战》

    IoU ( Intersection of Union)

    在这里插入图片描述
    对于具体的某个物体来讲,我们可以从预测框与真实框的贴合程度来判
    断检测的质量,通常使用IoU来量化贴合程度。
    在这里插入图片描述

    IoU的计算方式如上图所示,使用两个边框的交集与并集的比值,就可以得到IoU,公式如式(1-1)所示。显而易见,IoU的取值区间是[0,1],IoU值越大,表明两个框重合越好。

    伪代码:

    # 需要根据自己的代码进行修改
    def iou(boxA, boxB): 
    	# 计算重合部分的上、下、左、右4个边的值,注意最大最小函数的使用
    	left_max = max(boxA[0], boxB[0]) 
    	top_max = max(boxA[1], boxB[1]) 
    	right_min = min(boxA[2], boxB[2]) 
    	bottom_min = min(boxA[3], boxB[3]) 
    	# 计算重合部分的面积 
    	inter =max(0(right_min-left_max))* max(0(bottom_min-top_max) 
    	Sa = (boxA[2]-boxA[0])*(boxA[3]-boxA[1]) 
    	Sb = (boxB[2]-boxB[0])*(boxB[3]-boxB[1]) 
    	# 计算所有区域的面积并计算iou,如果是Python 2,则要增加浮点化操作 
    	union = Sa+Sb-inter 
    	iou = inter/union 
    	return iou
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    对于IoU而言,通常会选取一个阈值,如0.5,来确定预测框是 正确的还是错误的
    IoU>0.5 ————有效的检测
    IoU<=0.5 ————无效的匹配

    如下图中有两个杯子的标签,模型产生 了两个预测框。在这里插入图片描述
    由于图像中存在背景与物体两种标签,预测框也分为正确与错误,因此在评测时会产生以下4种样本。

    • TP(True Positive)正确检测框 预测框正确地与标签框匹配了,
      两者间的IoU大于0.5。
    • FP(False Positive)误检框 将背景预测成了物体,框与图中所有标签的IoU都不会超过0.5。
    • FN(False Negative)漏检框 本来需要模型检测出的物体,模型 没有检测出。
    • TN(True Negative):正确背景 本身是背景,模型也没有检测出来,通常不需要考虑

    mAP(mean Average Precision)

    mAP用来评价一 个模型的好坏,这里的AP指的是一个类别的检测精度,mAP则是多个类别的平均精度。

    准备知识:

    每个样本(图片)的预测值与标签值

    • 预测值(Dets):物体类别、边框位置的4个预测值、该物体的得分(置信度)。
    • 标签值(GTs) :物体类别、边框位置的4个真值。

    在这里插入图片描述

     1. 首先将所有的预测框按照得分从高到低进行排序(因为得分越高的边框其对于真实物体的概率往往越大)
    
     2. 然后从高到低遍历预测框
    	对于遍历中的每一个预测框,计算其(预测框 Dets)与该图中同一类别的所有真实框(标签框GTs)的IoU
    	并选取拥有最大IoU的GT作为当前预测框的匹配对象。
    		如果该IoU小于阈值,则将当前的预测框标记为误检框FP
    		如果该IoU大于阈值,还要看对应的标签框GT是否被访问过。
    			如果已经被访问过(即前面已经有得分更高的预测框与该标签框对应了),即使现在的IoU大于阈值,也会被标记为FP。
    			如果没有被访问过,则将当前预测框Det标记为正确检测框TP,并将该GT标记为访问过,以防止后面还有预测框与其对应。
     3. 在遍历完所有的预测框后,我们会得到每一个预测框的属性,即TP或FP。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    召回率(Recall,R)
    即当前一共检测出的标签框与所有标签框的比值
    在这里插入图片描述

    准确率(Precision,P)
    即当前遍历过的预测框中,属于正确预测边框的比值
    在这里插入图片描述

    F1分数(F1 Score)

    通常是统计学中用来衡量二分类模型精确度的一种指标。它同时兼顾了分类模型的准确率和召回率。
    F1分数可以看作是模型精确率和召回率的一种调和平均(可以理解为P和R的调和平均数),它的最大值是1,最小值是0。

    1/F1=1/2*(1/P+1/R)
    在这里插入图片描述

    P-R曲线
    遍历到每一个预测框时,都可以生成一个对应的P与R,这两个值可以组成一个点(R,P),将所有的点绘制成曲线,即形成了P-R曲线
    在这里插入图片描述
    然而,即使有了P-R曲线,评价模型仍然不直观,如果直接取曲线上的点,在哪里选取都不合适,因为召回率高的时候准确率会很低,准确率高的时候往往召回率很低。

    AP(Average Precision)

    在这里插入图片描述
    AP代表了曲线的面积,综合考量了不同召回率下的准确率,不会对P与R有任何偏好。每个类别的AP是相互独立的,将每个类别的AP进行平均,即可得到mAP

    严格意义上讲,还需要对曲线进行一定的修正,再进行AP计算。除了求面积的方式,还可 以使用11个不同召回率对应的准确率求平均的方式求AP。

    伪代码:

    假设当前经过标签数据与预测数据的加载,我们得到了下面两个变量:

    • det_boxes:包含全部图像中所有类别的预测框,其中一个边框包含了[left,top,right,bottom,score,NameofImage]。
    • gt_boxes:包含了全部图像中所有类别的标签,其中一个标签的内容为[left,top,right,bottom,0]。
      需要注意的是,最后一位0代表该标签有没有被匹配过,如果匹配过则会置为1,其他预测框再去匹配则为误检框。
    for c in classes: 
    	# 通过类别作为关键字,得到每个类别的预测、标签及总标签数
    	dects = det_boxes[c] 
    	gt_class = gt_boxes[c] 
    	npos = num_pos[c] 
    	# 利用得分作为关键字,对预测框按照得分从高到低排序
    	dects = sorted(dects, key=lambda conf: conf[5], reverse=True) 
    	# 设置两个与预测边框长度相同的列表,标记是True Positive还是False Positive 
    	TP = np.zeros(len(dects)) 
    	FP = np.zeros(len(dects)) 
    	# 对某一个类别的预测框进行遍历 
    	for d in range(len(dects)): 
    		# 将IoU默认置为最低 
    		iouMax = sys.float_info.min 
    		# 遍历与预测框同一图像中的同一类别的标签,计算IoU 
    		if dects[d][-1] in gt_class: 
    			for j in range(len(gt_class[dects[d][-1]])): 
    				iou = Evaluator.iou(dects[d][:4], gt_class[dects[d][-1]][j][:4]) 
    				if iou > iouMax: 
    				iouMax = iou 
    				jmax = j	# 记录与预测有最大IoU的标签 
    			# 如果最大IoU大于阈值,并且没有被匹配过,则赋予TP 
    			if iouMax >= cfg['iouThreshold']: 
    				if gt_class[dects[d][-1]][jmax][4] == 0: 
    					TP[d] = 1 
    					gt_class[dects[d][-1]][jmax][4] = 1	# 标记为匹配过 
    				# 如果被匹配过,赋予FP 
    				else:
    					FP[d] = 1 
    			# 如果最大IoU没有超过阈值,赋予FP 
    			else: 
    				FP[d] = 1 
    		# 如果对应图像中没有该类别的标签,赋予FP 
    		else: 
    			FP[d] = 1 
    	# 利用NumPy的cumsum()函数,计算累计的FP与TP 
    	acc_FP = np.cumsum(FP) 
    	acc_TP = np.cumsum(TP) 
    	rec = acc_TP / npos 	# 得到每个点的Recall 
    	prec = np.divide(acc_TP, (acc_FP + acc_TP)) 	# 得到每个点的Precision
    	# 利用Recall与Precision进一步计算得到AP 
    	[ap, mpre, mrec, ii] = Evaluator.CalculateAveragePrecision(rec, prec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
  • 相关阅读:
    课堂教学效率低?这个方案很适合
    PE结构学习(4)_节的操作
    分享一个JS对象隐式转换的问题
    力扣133题:只出现一次的数字
    Web应用安全测试-权限篡改
    pytorch代码实现之分布偏移卷积DSConv
    中断操作:AbortController学习笔记
    JS数据结构与算法-队列结构
    SQL常用语句大全
    GBASE 8A v953报错集锦49--ftp 报错 500 OOPS: cannot change
  • 原文地址:https://blog.csdn.net/zxm_jimin/article/details/126403673