box_iou交并比及assign_anchor_to_bbox个人理解

接上篇文章,李沐沐神的《动手学深度学习》中的show_bboxes还是比较好理解的,于是来看这两个方法
以下内容建议对照源代码理解

def box_iou

首先我们来设置boxes1和boxes2的初始值

boxes1 = torch.tensor([[1,2,5,6],[2,1,4,6],[-1,2,7,6],
                      [1,2,5,8]])
boxes2 = torch.tensor([[0,3,5,7],[1,2,3,7],[0,4,5,7],
                      [0,5,5,7]])

设置了第一组的四个锚框的左横,下纵,右横,上纵坐标(详情上一篇文章)和第二组的四个锚框坐标

boxes1[:,2],boxes1[:,0]
'''结果'''
(tensor([5, 4, 7, 5]), tensor([ 1,  2, -1,  1]))
boxes1[:,3],boxes1[:,1]
'''结果'''
(tensor([6, 6, 6, 8]), tensor([2, 1, 2, 2]))

很显然这两个语句将这一组锚框的右横、左横和上纵、下纵坐标表示了出来,而右横坐标-左横坐标便得出了这一个锚框的长,上纵坐标-下纵坐标便得出了这个锚框的宽,相乘便是这个锚框的面积
下面的方法便是求一组锚框的面积

(boxes1[:,2]-boxes1[:,0])*(boxes1[:,3]-boxes1[:,1])
'''结果'''
tensor([16, 10, 32, 24])

与上面求得的各个坐标相对应
于是便有了这个方法

box_area = lambda boxes: ((boxes[:, 2] - boxes[:, 0]) *
                              (boxes[:, 3] - boxes[:, 1]))

下面的语句中包含
inter_upperlefts = torch.max(boxes1[:, None, :2], boxes2[:, :2])
inter_lowerrights = torch.min(boxes1[:, None, 2:], boxes2[:, 2:])
而其中的torch.max(boxes1[:, None, :2], boxes2[:, :2])与 torch.min(boxes1[:, None, 2:], boxes2[:, 2:])实在让人费解,到底为什么要在boxes中增加一个None呢?
让我们带着上面假设的boxes1和boxes2继续向下看
首先我们要知道带None和不带None有什么区别

torch.max(boxes1[:,:2],boxes2[:,:2])
'''结果'''
tensor([[1, 3],
        [2, 2],
        [0, 4],
        [1, 5]])

给boxes1中四个锚框取名为A1,A2,A3,A4,boxes2中四个锚框取名为B1,B2,B3,B4,能够看出这是将A1B1做比较,A2B2、A3B3、A4B4分别做比较

torch.max(boxes1[:,None,:2],boxes2[:,:2])
'''结果'''
tensor([[[1, 3],
         [1, 2],
         [1, 4],
         [1, 5]],

        [[2, 3],
         [2, 2],
         [2, 4],
         [2, 5]],

        [[0, 3],
         [1, 2],
         [0, 4],
         [0, 5]],

        [[1, 3],
         [1, 2],
         [1, 4],
         [1, 5]]])

答案是将A1与所有B做比较,A2与所有B作比较…
接着来看min部分的代码

torch.min(boxes1[:, 2:], boxes2[:, 2:])
'''结果'''
tensor([[5, 6],
        [3, 6],
        [5, 6],
        [5, 7]])
torch.min(boxes1[:, None, 2:], boxes2[:, 2:])
'''结果'''
tensor([[[5, 6],
         [3, 6],
         [5, 6],
         [5, 6]],

        [[4, 6],
         [3, 6],
         [4, 6],
         [4, 6]],

        [[5, 6],
         [3, 6],
         [5, 6],
         [5, 6]],

        [[5, 7],
         [3, 7],
         [5, 7],
         [5, 7]]])

同样也是答案是将A1与所有B做比较,A2与所有B作比较…,这样就知道了加None的作用
box_iou交并比及assign_anchor_to_bbox个人理解_第1张图片
像这张图,相交部分的下横坐标与左纵坐标取两个锚框的max值
相交部分的上横坐标与右纵坐标取两个锚框的min值

inters = (inter_lowerrights - inter_upperlefts).clamp(min=0)
inters
'''结果'''
tensor([[[4, 3],
         [2, 4],
         [4, 2],
         [4, 1]],

        [[2, 3],
         [1, 4],
         [2, 2],
         [2, 1]],

        [[5, 3],
         [2, 4],
         [5, 2],
         [5, 1]],

        [[4, 4],
         [2, 5],
         [4, 3],
         [4, 2]]])

将这两组答案相减,便得到了所有锚框交接的长和宽,clamp(min=0)意思是将小于0的长和宽变为0,因为长和宽都不为0

将长和宽相乘便是相交锚框的面积

inter_areas = inters[:, :, 0] * inters[:, :, 1]
inter_areas
'''结果'''
tensor([[12,  8,  8,  4],
        [ 6,  4,  4,  2],
        [15,  8, 10,  5],
        [16, 10, 12,  8]])

再算出原始锚框的面积

areas1 = box_area(boxes1)
areas2 = box_area(boxes2)

相交部分的所有面积(同样有None,人们也叫这个机制为广播机制)

union_areas = areas1[:, None] + areas2 - inter_areas
union_areas
'''结果'''
tensor([[24, 18, 23, 22],
        [24, 16, 21, 18],
        [37, 34, 37, 37],
        [28, 24, 27, 26]])

相除便得到了io比

inter_areas / union_areas
''''''
tensor([[0.5000, 0.4444, 0.3478, 0.1818],
        [0.2500, 0.2500, 0.1905, 0.1111],
        [0.4054, 0.2353, 0.2703, 0.1351],
        [0.5714, 0.4167, 0.4444, 0.3077]])

assign_anchor_to_bbox方法

设置初始值
生成锚框的数量和真实锚框的数量
io比

num_anchors, num_gt_boxes = 4, 4
jaccard=torch.tensor([[0.5000, 0.4444, 0.3478, 0.1818],
        [0.2500, 0.2500, 0.1905, 0.1111],
        [0.4054, 0.2353, 0.2703, 0.1351],
        [0.5714, 0.4167, 0.4444, 0.3077]])
max_ious, indices = torch.max(jaccard, dim=1)
max_ious, indices
'''结果'''
(tensor([0.5000, 0.2500, 0.4054, 0.5714]), tensor([0, 0, 0, 0]))

dim=0即在横方向比较,max_ious储存了所有行最大的io比,indices储存了最大io比的位置,这里很巧都是第一个最大
设置最小的io比,即小于这个的io比不做考虑

iou_threshold = 0.3
anc_i = torch.nonzero(max_ious >= iou_threshold).reshape(-1)
torch.nonzero(max_ious >= iou_threshold).reshape(-1)
'''结果'''
tensor([0, 2, 3])

只有序号为0,2,3的位置算作有效io比
而下一段代码

box_j = indices[max_ious >= iou_threshold]
box_j
'''结果'''
tensor([0, 0, 0])

表示了有效io比的行里最大的io比,与上面的anc_i对应


后面的就比较好理解了
剩下的多看看视频理解老师的思路就可以了

你可能感兴趣的:(动手学深度学习,目标检测,深度学习,锚框,李沐)