目录
一些基础知识整理,仅为自己查看方便,侵删。
1、NMS
非极大值抑制(Non-maximum suppression,NMS)是一种去除非极大值的算法,也就是不是局部最大值的那些值都滚蛋,其基本操作流程如下:
给出一张图片和上面许多物体检测的候选框,但是这些框很可能有互相重叠的部分,我们要做的就是只保留最优的框。假设有N个框,每个框的置信度为Si, 1<=i<=N。
0、构建一个存放待处理候选框的集合H,初始化为包含全部N个框;构建一个存放最优框的集合M,初始化为空集。
1、将所有集合 H 中的框进行排序,选出置信度最高的一个框 m,从集合 H 移到集合 M;
2、遍历集合 H 中的框,分别与框 m 计算交并比(Interection-over-union,IoU),如果高于某个阈值(一般为0~0.5),则认为此框与 m 重叠,将此框从集合 H 中去除。
3、回到第1步进行迭代,直到集合 H 为空。集合 M 中的框为我们所需。
需要优化的参数:
IoU 的阈值是一个可优化的参数,一般范围为0~0.5,可以使用交叉验证来选择最优的参数。
第一轮选出H中置信度最高的框0.98,遍历其他框,将0.75,0.83两个框去除;
第二轮选出H中置信度最高的框0.81,遍历其他,去除0.67框。
soft nms
与nms的区别是:
NMS将IoU大于阈值的box得分全置为0:
Soft-nms将IoU大于阈值的box得分进行衰减,最后删除得分小于设定分数阈值的box:
线性衰减:
高斯加权:
import numpy as np
def NMS(dets, thresh):
#x1、y1、x2、y2、以及score赋值
# (x1、y1)(x2、y2)为box的左上和右下角标
x1 = dets[:, 0]
y1 = dets[:, 1]
x2 = dets[:, 2]
y2 = dets[:, 3]
scores = dets[:, 4]
#每一个候选框的面积
areas = (x2 - x1 + 1) * (y2 - y1 + 1)
#order是按照score降序排序的,得到的是排序的本来的索引,不是排完序的原数组
order = scores.argsort()[::-1]
# ::-1表示逆序
temp = []
while order.size > 0:
i = order[0]
temp.append(i)
#计算当前概率最大矩形框与其他矩形框的相交框的坐标
# 由于numpy的broadcast机制,得到的是向量
xx1 = np.maximum(x1[i], x1[order[1:]])
yy1 = np.maximum(y1[i], y1[order[1:]])
xx2 = np.minimum(x2[i], x2[order[1:]])
yy2 = np.minimum(y2[i], y2[order[1:]])
#计算相交框的面积,注意矩形框不相交时w或h算出来会是负数,需要用0代替
w = np.maximum(0.0, xx2 - xx1 + 1)
h = np.maximum(0.0, yy2 - yy1 + 1)
inter = w * h
#计算重叠度IoU
ovr = inter / (areas[i] + areas[order[1:]] - inter)
#找到重叠度不高于阈值的矩形框索引
inds = np.where(ovr <= thresh)[0]
#将order序列更新,由于前面得到的矩形框索引要比矩形框在原order序列中的索引小1,所以要把这个1加回来
order = order[inds + 1]
return temp
if __name__ == "__main__":
dets = np.array([[310, 30, 420, 5, 0.6],
[20, 20, 240, 210, 1],
[70, 50, 260, 220, 0.8],
[400, 280, 560, 360, 0.7]])
# 设置阈值
thresh = 0.4
keep_dets = NMS(dets, thresh)
# 打印留下的框的索引
print(keep_dets)
# 打印留下的框的信息
print(dets[keep_dets])
https://blog.youkuaiyun.com/lanchunhui/article/details/71216463,https://blog.youkuaiyun.com/HappyRocking/article/details/79970627,https://blog.youkuaiyun.com/leviopku/article/details/80886386
2、评价指标
交并比IOU是指候选框与原标记框之间交集与并集的比值。
I O U = ( A ∩ B ) / ( A ∪ B ) IOU=(A∩B)/(A∪B) IOU=(A∩B)/(A∪B)
def compute_iou(rec1, rec2):
"""
computing IoU
:param rec1: (y0, x0, y1, x1), which reflects
(top, left, bottom, right)
:param rec2: (y0, x0, y1, x1)
:return: scala value of IoU
"""
# computing area of each rectangles
S_rec1 = (rec1[2] - rec1[0]) * (rec1[3] - rec1[1])
S_rec2 = (rec2[2] - rec2[0]) * (rec2[3] - rec2[1])
# computing the sum_area
sum_area = S_rec1 + S_rec2
# find the each edge of intersect rectangle 找到相交矩形的边
left_line = max(rec1[1], rec2[1])
right_line = min(rec1[3], rec2[3])
top_line = max(rec1[0], rec2[0])
bottom_line = min(rec1[2], rec2[2])
# judge if there is an intersect
if left_line >= right_line or top_line >= bottom_line:
return 0
else:
intersect = (right_line - left_line) * (bottom_line - top_line)
return (intersect / (sum_area - intersect))*1.0
if __name__=='__main__':
rect1 = (661, 27, 679, 47)
# (top, left, bottom, right)
rect2 = (662, 27, 682, 47)
iou = compute_iou(rect1, rect2)
print