YOLO v2目标检测详解一box生成与转换

yolo v2会将图片切割成若干个大小为32*32 的小格子,因此,将图片传入时,图片的长和宽都必须是32的倍数,如下所示:

YOLO v2目标检测详解一box生成与转换_第1张图片

后面的内容中,如果没有说明,都是指的小格子。yolo v2中的box中的数据并不是平常的xmin,ymin,xmax,ymax,而是,offset_x,offset_y,w,h,分别代表的意思是:box中心x坐标在小格子的比例,box中心y坐标在小格子的比例,宽和小格子大小的比,高和小格子大小的比,有点难懂,下面用举几个例子。

YOLO v2目标检测详解一box生成与转换_第2张图片

黑色的小格子就是上面所说的切分成的小格子,红色的框是生成的anchor或者标注的感兴趣区域,假设红色的点就是红色的框的中心,那么相对于黑色格子来说,x,y的值就是0.9,0.1,假设红色框和黑色小格子大小一样,那么对于红色框来说,红色框在yolo   v2中的数据是0.9  0.1  1  1。假设蓝色格子的中心和黑色格子的中心重合,蓝色格子的宽是黑色格子的六倍,高是三倍,则yolo v2中的数据是0.5,0.5,6,3。其他类似,不再举例。

下面就实现如何将xmin,ymin,xmax,ymax类型的类型转换成yolo v2型的数据

#接受的boxes是(N,4)类型的数据,是二位的数据类型
def boxtoyolo(boxes):
    #xmin,ymin,xmax,ymax,是N*1的数据类型
    xmin ,ymin,xmax,ymax = boxes[:,0],boxes[:,1],boxes[:,2],boxes[:,3]
    #下面解释为什么是除以64,除以32
    #(xmin + xmax+1)/2表示的是中心坐标,再除以32得到相应的比例
    x,y,w,h =(xmin + xmax+1)/64,(ymin + ymax+1)/64,(xmax - xmin+1)/32,(ymax - ymin+1)/32
    #如果是xmin=0,xmax = 31,那么得到的x只有小数,如果xmin = 32,xmax = 63,那么得到的x还有整数部分
    # 因此要减去整数部分才会得到相对应的比例
    x,y = x - x.int(),y - y.int()

    return torch.stack([x,y,w,h],dim=0).t()

下面可以进行简单测试,判断转换是否正确

if __name__ == '__main__':
    boxs = [
        [0, 0, 31, 31],
        [32, 32, 63, 63]
    ]
    print(boxtoyolo(torch.Tensor(boxs)))

 

每个小格子都会相应生成5个anchor,是yolo v2数据类型,下面继续介绍如何再将yolo v2数据类型转换成普通的xmin,ymin,xmax,ymax数据类型

#传入的数据类型是N*4,N必须等于w_n*h_n*t,t一般都是5
def yolotobox(boxes, w_n, cell_anchor_num=5):
    box_num = boxes.shape[0]
    #0,1,2,3,4,........w_n*h_n*t-1 -> 0 0 0 0 0 1 1 1 1 1 ...... w_n*h_n-1
    index_range = torch.arange(0,box_num)//cell_anchor_num
    #每一行都有w_n个小格子
    shift_x,shift_y = index_range % w_n,index_range // w_n
    #重新转化成x,y,w,h坐标
    x, y, w, h = boxes[:,0]*32 + shift_x*32,boxes[:,1]*32 + shift_y * 32,boxes[:,2]*32,boxes[:,3]*32
    #重新转换成xmin,ymin,xmax,ymax
    return torch.stack([x - w/2,y - h/2,x + w/2-1,y + h/2-1],dim=0).t()

可以通过下面的代码测试是否正确

boxs = [
        [0.5, 0.5, 1, 1],
        [0.5, 0.5, 1, 1],
        [0.5, 0.5, 1, 1],
        [0.5, 0.5, 1, 1],
        [0.5, 0.5, 1, 1],
        [0.5, 0.5, 1, 1],
        [0.5, 0.5, 1, 1],
        [0.5, 0.5, 1, 1],
    ]
    boxs = torch.Tensor(boxs)
    print(yolo2box(boxs, w_n=2, cell_anchor_num=2))

上面介绍了yolo v2的数据类型和普通的xmin,ymin,xmax,ymax数据类型,以及两者之间的转换

 下面介绍如何产生box,这里直接提供通过其他方法运行得到的结果

一般情况在YOLO v2中会以每个小格子的中心作为中心产生五个box框,下面就产生这些box

def build_anchors(k_anchors, w_n, h_n):
    anchors = []
    for anchor in k_anchors:
        anchors.append([0.5, 0.5, anchor[0], anchor[1]])
    #每个小格子都会按照这个比例产生五个box
    res = torch.Tensor(anchors*(w_n*h_n))

    # wh5 x 4
    return res

可以用下面的代码进行测试

k_anchors = [
        [0.8216540404040407, 0.8090277777777803],
        [0.5926876770538244, 0.5874645892351248],
        [1.8697289156626502, 1.8008283132530114],
        [0.4149953358208951, 0.4131296641791048],
        [1.1900058962264153, 1.1625884433962257]
    ]
    print(build_anchors(k_anchors, 2, 2))

前面介绍了box的产生,yolo v2和普通xmin,ymin,xmax,ymax,的转换,后面文章将继续介绍一些其他的操作

 

你可能感兴趣的:(pytorch,机器学习)