IoU
矩形框的IoU
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) , which reflects ( top, left, bottom, right)
return : scale value of IoU
"" "
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 interest rectangle
in_h = min ( rec1[ 2 ] , rec2[ 2 ] ) - max ( rec1[ 0 ] , rec2[ 0 ] )
in_w = min ( rec1[ 3 ] , rec2[ 3 ] ) - max ( rec1[ 1 ] , rec2[ 1 ] )
# judge if interact
inter = 0 if in_h< 0 or in_w< 0 else in_h* in_w
return intersect / ( sum_area - intersect)
旋转目标的IoU
from shapely. geometry import Polygon
def intersection ( g, p) :
g= np. asarray ( g)
p= np. asarray ( p)
g = Polygon ( g[ : 8 ] . reshape ( ( 4 , 2 ) ) )
p = Polygon ( p[ : 8 ] . reshape ( ( 4 , 2 ) ) )
if not g. is_valid or not p. is_valid:
return 0
inter = Polygon ( g) . intersection ( Polygon ( p) ) . area
union = g. area + p. area - inter
if union == 0 :
return 0
else :
return inter/ union
语义分割的IoU
NMS
矩形框NMS
def nms_cpu ( dets, thresh) :
dets = dets. numpy ( )
x1 = dets[ : , 0 ] # 取出所有的边界框左上角点的x坐标放入x1
y1 = dets[ : , 1 ]
x2 = dets[ : , 2 ]
y2 = dets[ : , 3 ]
scores = dets[ : , 4 ]
areas = ( x2 - x1 + 1 ) * ( y2 - y1 + 1 ) # 计算所有边界框的面积
# numpy 的argsort ( ) 函数:返回数组值从小到大的索引值,
# 再加上[ :: - 1 ] 返回数组值从大到小的索引值,
# 也可以order = np. argsort ( - score)
order = scores. argsort ( ) [ :: - 1 ] #分数从大到小排列的索引值
# 每次选出scores中最大的那个边界框
keep = [ ]
while order. size > 0 :
i = order[ 0 ]
keep. append ( i) # 保留该类剩余box中得分最高的索引
xx1 = np. maximum ( x1[ i] , x1[ order[ 1 : ] ] ) #获取得分最高的边界框与其他所有框的的重叠区域的左上角x坐标
yy1 = np. maximum ( y1[ i] , y1[ order[ 1 : ] ] ) #标量和numpy取最值,结果是一个numpy
xx2 = np. minimum ( x2[ i] , x2[ order[ 1 : ] ] ) #此处是minimun,不是maximum。求得分最高的边界框与其他所有框的的重叠区域的右下角x坐标
yy2 = np. minimum ( y2[ i] , y2[ order[ 1 : ] ] )
# 计算重叠的面积, 不重叠时面积为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)
# 保留iou小于等于阈值的边界框,其它则被过滤了
# numpy . where ( ) 有两种用法:
# 1. np. where ( condition, x, y) : 满足条件( condition) ,输出x,不满足输出y。
# 2. np. where ( condition) : 输出满足条件( 即非0 ) 元素的坐标( 等价于numpy. nonzero)
inds = np. where ( ovr <= thresh) [ 0 ] #重叠面积小表示要保留
# 因为ovr数组的长度比order数组少一个, 所以这里要将所有下标后移一位,
# 获得下一个目标区域的得分最高的一个的索引
order = order[ inds + 1 ]
return torch. IntTensor ( keep)
soft_NMS
def soft_nms ( boxes, sigma= 0.5 , threshold1= 0.7 , threshold2= 0.1 , method= 1 ) :
'' '
paper: Improving Object Detection With One Line of Code
'' '
N = boxes. shape[ 0 ]
pos = 0
maxscore = 0
maxpos = 0
for i in range ( N) :
# 用冒泡排序法找到分数最高的预测框,并将该预测框放在第i个位置
maxscore = boxes[ i, 4 ]
maxpos = i
# 先用一些中间变量存储第i个预测框
tx1 = boxes[ i, 0 ]
ty1 = boxes[ i, 1 ]
tx2 = boxes[ i, 2 ]
ty2 = boxes[ i, 3 ]
ts = boxes[ i, 4 ]
pos = i + 1
# 得到评分最高的box
while pos < N:
if maxscore < boxes[ pos, 4 ] :
maxscore = boxes[ pos, 4 ]
maxpos = pos
pos = pos + 1
# 交换第i个box和评分最高的box, 将评分最高的box放到第i个位置
boxes[ i, 0 ] = boxes[ maxpos, 0 ]
boxes[ i, 1 ] = boxes[ maxpos, 1 ]
boxes[ i, 2 ] = boxes[ maxpos, 2 ]
boxes[ i, 3 ] = boxes[ maxpos, 3 ]
boxes[ i, 4 ] = boxes[ maxpos, 4 ]
# 将原先第i个预测框放在分数最高的位置
boxes[ maxpos, 0 ] = tx1
boxes[ maxpos, 1 ] = ty1
boxes[ maxpos, 2 ] = tx2
boxes[ maxpos, 3 ] = ty2
boxes[ maxpos, 4 ] = ts
# 程序到此实现了:寻找第i至第N个预测框中分数最高的框,并将其与第i个预测框互换位置。
# 预测框M,前缀"t" 表示target
tx1 = boxes[ i, 0 ]
ty1 = boxes[ i, 1 ]
tx2 = boxes[ i, 2 ]
ty2 = boxes[ i, 3 ]
ts = boxes[ i, 4 ]
# 下面针对M进行NMS迭代过程,
# 需要注意的是,如果soft- NMS将score削弱至某阈值threshold以下,则将其删除掉
# 在程序中体现为,将要删除的框放在了最后,并使 N = N- 1
pos = i + 1
# soft NMS迭代
while pos < N:
x1 = boxes[ pos, 0 ]
y1 = boxes[ pos, 1 ]
x2 = boxes[ pos, 2 ]
y2 = boxes[ pos, 3 ]
s = boxes[ pos, 4 ]
area = ( x2 - x1 + 1 ) * ( y2 - y1 + 1 )
iw = ( min ( tx2, x2) - max ( tx1, x1) + 1 )
if iw > 0 :
ih = ( min ( ty2, y2) - max ( ty1, y1) + 1 )
if ih > 0 :
uinon = float ( ( tx2 - tx1 + 1 ) *
( ty2 - ty1 + 1 ) + area - iw * ih)
iou = iw * ih / uinon # 计算iou
if method == 1 : # 线性更新分数
if iou > threshold1:
weight = 1 - iou
else :
weight = 1
elif method == 2 : # 高斯权重
weight = np. exp ( - ( iou * iou) / sigma)
else : # 传统 NMS
if iou > threshold1:
weight = 0
else :
weight = 1
boxes[ pos, 4 ] = weight * boxes[ pos, 4 ] # 根据和最高分数box的iou来更新分数
# 如果box分数太低,舍弃( 把他放到最后,同时N- 1 )
if boxes[ pos, 4 ] < threshold2:
boxes[ pos, 0 ] = boxes[ N - 1 , 0 ]
boxes[ pos, 1 ] = boxes[ N - 1 , 1 ]
boxes[ pos, 2 ] = boxes[ N - 1 , 2 ]
boxes[ pos, 3 ] = boxes[ N - 1 , 3 ]
boxes[ pos, 4 ] = boxes[ N - 1 , 4 ]
N = N - 1 # 注意这里N改变
pos = pos - 1
pos = pos + 1
keep = [ i for i in range ( N) ]
return keep