介绍目标检测中三种最常见的代码。
#IOU代码
#box格式 (xmin,ymin,xmax,ymax)
def computeIOU(A, B):
#assert A.size()==4 and B.size()==4, "must have 4 numbers"
bxmin = max(A[0],B[0])
bymin = max(A[1],B[1])
bxmax = min(A[2],B[2])
bymax = min(A[3],B[3])
w = max(0, bxmax-bxmin + 1)
h = max(0, bymax-bymin + 1)
inter = w * h
union = (A[2]-A[0]+1)*(A[3]-A[1]+1) + (B[2]-B[0]+1)*(B[3]-B[1]+1) - inter
return inter / union
#数据测试 https://www.aiuai.cn/aifarm1127.html
A = [39, 63, 203, 112]
B = [54, 66, 198, 114]
print(computeIOU(A,B)) #0.7980093676814989
2 NMS代码
#NMS代码
#dets格式array([[xmin,ymin,xmax,ymax,score],...]),shape(n,5)
def NMS(dets, thresh):
#解析坐标值,若dets格式不同,需要注意顺序
bxmin,bymin,bxmax,bymax,scores = dets[:,0],dets[:,1],dets[:,2],dets[:,3],dets[:,4]
areas = (bxmax-bxmin+1) * (bymax-bymin+1) #shape(n,) 各个预测框的面积
order = scores.argsort()[::-1] #按得分降序排列
keep = [] #保留下来的预测框
while order.size>0:
i = order[0] #这一轮中得分最高的预测框,用该主框来抑制其他重复框
keep.append(i)
#计算主框和其余框IOU
xx = np.maximum(bxmin[i], bxmin[order[1:]])
yy = np.maximum(bymin[i], bymin[order[1:]])
XX = np.minimum(bxmax[i], bxmax[order[1:]])
YY = np.minimum(bymax[i], bymax[order[1:]])
w = np.maximum(0.0, XX-xx)
h = np.maximum(0.0, YY-yy)
inter = w * h
iou = inter / (areas[i] + areas[order[1:]] - inter)
idx = np.where(iou <= thresh)[0] #找到iou值小于阈值的索引
order = order[idx+1] #更新order。前面的order已排除主框,故相比原索引减少了1
return keep
#测试
import numpy as np
dets=[[0,0,100,100,0.9],[10,10,90,90,0.7],[50,50,120,120,0.8],[60,60,130,130,0.5]]
dets = np.array(dets)
keep = NMS(dets, 0.5)
print(keep) #[0, 2]
3 mAP
#VOC计算AP的两种方式
def voc_ap(rec, prec, use_07_metric=False):
"""
输入recall和precision,输出AP
Compute VOC AP given precision and recall.
If use_07_metric is true, uses the VOC 07 11 point method (default:False).
"""
if use_07_metric:
# 11 point metric
ap = 0.
for t in np.arange(0., 1.1, 0.1):
if np.sum(rec >= t) == 0:
p = 0
else:
p = np.max(prec[rec >= t])
ap = ap + p / 11.
else:
# correct AP calculation
# first append sentinel values at the end
mrec = np.concatenate(([0.], rec, [1.]))
mpre = np.concatenate(([0.], prec, [0.]))
print(mpre)
# compute the precision envelope
for i in range(mpre.size - 1, 0, -1):
mpre[i - 1] = np.maximum(mpre[i - 1], mpre[i])
# to calculate area under PR curve, look for points
# where X axis (recall) changes value
i = np.where(mrec[1:] != mrec[:-1])[0] #获取rec区间变化点
ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1]) #在recall轴上积分
return ap
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:目标检测中常用的IOU、NMS和mAP - Python技术站