目標檢測中常用的IOU、NMS和mAP


介紹目標檢測中三種最常見的代碼。

1 IOU代碼

#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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM