一、主要内容:
计算重叠,这里有一个阈值就是thresh,按照下面几条原则:
1、删除交并比大于阈值的框
2、如果ab相交的交并比大于阈值0.1,请问删除哪个框
删除置信度最小的框,第五列是置信度
二、注意:
这里如何理解阈值为啥要设置成0.1,其实版面识别的阈值我一般设置为0,但是0不太合适,我一般是设置为特别小的值,比如说0.0001,为啥呢?
因为版面识别我不需要有重叠的框,所以要这样设置
def nms(dets, thresh):
# 打印输入的检测框 dets
print(dets)
'''
[[ 90 1036 528 1292 0.98149 0]
[ 542 1033 988 1167 0.97097 0]
[ 88 177 978 446 0.97066 3]
[ 544 1210 989 1292 0.95167 0]
[ 240 480 862 991 0.92897 4]
[ 549 1182 758 1200 0.88909 1]
[ 88 126 976 175 0.88162 0]
[ 87 96 151 111 0.86345 6]
[ 813 92 974 104 0.85024 6]
[ 192 998 881 1026 0.81056 0]
[ 526 1306 545 1323 0.78073 7]]
'''
"Pure Python NMS baseline"
# dets[:, 0] 是所有检测框的左上角 x 坐标
x1 = dets[:, 0] # [ 90 542 88 544 240 549 88 87 813 192 526]
print("x1: ",x1)
# dets[:, 1] 是所有检测框的左上角 y 坐标
y1 = dets[:, 1]
# dets[:, 2] 是所有检测框的右下角 x 坐标
x2 = dets[:, 2]
# dets[:, 3] 是所有检测框的右下角 y 坐标
y2 = dets[:, 3]
# dets[:, 4] 是所有检测框的置信度分数(score)
scores = dets[:, 4]
# 计算每个检测框的面积 (width * height)
areas = (y2 - y1 + 1) * (x2 - x1 + 1) #[ 1.1282e+05 60345 2.4057e+05 37018 3.1898e+05 3990 44450 1040 2106 20010 360]
print("面积:",areas)
# 按照 scores 的大小进行排序,得到从大到小的索引顺序
order = scores.argsort()[::-1] #[ 0 1 2 3 4 5 6 7 8 9 10]
print("排序:",order)
# 用于保存最终筛选出的检测框的索引
keep = []
# 当 order 中还有剩余的检测框索引时,继续处理
while order.size > 0:
# 取出当前得分最高的检测框的索引 i
i = order[0]
# 将得分最高的检测框索引加入 keep 列表中
keep.append(i) #第一次为0
# 找到 i 框与剩下的所有框的相交区域的左上角和右下角坐标
xx1 = numpy.maximum(x1[i], x1[order[1:]]) # 相交区域左上角的 x 坐标
'''
1、官方例子
a = np.array([1, 2, 3])
b = np.array([2, 1, 4])
result = np.maximum(a, b)
返回[2,2,4]
2、这里的例子:
x1[i]:88.0
x1[order[1:]]: [ 85 809 84 88]
xx1:[ 88 809 88 88]
'''
yy1 = numpy.maximum(y1[i], y1[order[1:]]) # 相交区域左上角的 y 坐标
xx2 = numpy.minimum(x2[i], x2[order[1:]]) # 相交区域右下角的 x 坐标
yy2 = numpy.minimum(y2[i], y2[order[1:]]) # 相交区域右下角的 y 坐标
# 计算相交区域的宽度 w 和高度 h,重叠部分面积为 w * h
w = numpy.maximum(0, xx2 - xx1 + 1) # 确保宽度为正,否则重叠为0
print("w:",w) # [ 169 890 885 95]
h = numpy.maximum(0, yy2 - yy1 + 1) # 确保高度为正,否则重叠为0
print("h",h) #[ 0 0 0 0]
inter = w * h # 重叠区域的面积
# 计算 IoU(Intersection over Union):相交面积 / (两检测框的总面积 - 相交面积)
ovr = inter / (areas[i] + areas[order[1:]] - inter)
print("ovr",ovr)
# 保留 IoU 小于给定阈值的检测框索引
indx = numpy.where(ovr <= thresh)[0] #交并比小于阈值thresh的都记录
print("indx:",indx)
'''
ovr = np.array([0.1, 0.5, 0.3, 0.7])
thresh = 0.4
indx = np.where(ovr <= thresh)[0]
indx是[0 2]
'''
# 更新 order 列表,移除与当前框的 IoU 超过阈值的检测框
# indx 是基于 order[1:] 的索引,因此需要加 1 来对应原始的 order
order = order[indx + 1] #indx是一个列表,表示啥,表示比如说,indx=[0,5],那就是order只保留序列0,5的数据,意识是大于这个阈值的就不会再这个循环中出现
print("order:",order)
# 打印最终保留的检测框的索引