【Pytorch深度学习50篇】·······第五篇:【YOLO】【2】-----数据标签的准备【2】

看过上一篇的同学们应该都知道,今天我们要进入make_labels这个关键的函数了

值得一提的是,今天上午来上班的时候,发现自己的电脑歇菜了,这外星人也不经用啊,我担心的是我的里面的代码和数据集怎么办,可急死我了。我怀疑是昨天卸载了360,这个流氓软件肯定动我系统文件了。强行360背锅。

没办法,捣鼓一上午也打不开,然后选择制作一个u盘启动盘,然后把关键的一些数据拷贝到U盘里,然后选择恢复出厂设置,不过,这个恢复出厂设置是真的⑨啊

144H remaining···············································,当场休克啊。

2.2 make_labels函数的详解

好了回到正题上来,我们先上make_labels函数的代码

def make_labels(resize_img_size, ANCHORS_GROUP, CLASS_NUM, boxes, ANCHORS_GROUP_AREA):
    """
    :param resize_img_size: resize之后的图片的高宽
    :param ANCHORS_GROUP: 9个anchor的宽高
    :param CLASS_NUM: 类别总数
    :param boxes: 目标的坐标位置
    :param ANCHORS_GROUP_AREA: anchor的面积
    :return: 一个featuremap
    """
    labels = {}
    for feature_size, anchors in ANCHORS_GROUP.items():
        labels[feature_size] = torch.zeros(
            [int(resize_img_size[0] / feature_size), int(resize_img_size[1] / feature_size), 3, 5 + CLASS_NUM])

        for box in boxes:
            cls, xmin, ymin, xmax, ymax = box
            cx = (xmin + xmax) / 2
            cy = (ymin + ymax) / 2
            w = xmax - xmin
            h = ymax - ymin
            cx_offset, cx_index = math.modf(cx / feature_size)
            cy_offset, cy_index = math.modf(cy / feature_size)

            for i, anchor in enumerate(anchors):
                anchor_area = ANCHORS_GROUP_AREA[feature_size][i]
                p_w, p_h = w / anchor[0], h / anchor[1]
                conf = IOU(gt_box=[xmin, ymin, xmax, ymax],
                           anchor=[cx - (anchor[0] / 2), cy - (anchor[1] / 2), cx + (anchor[0] / 2),
                                   cy + (anchor[1] / 2)])
                labels[feature_size][int(cy_index), int(cx_index), i] = torch.tensor(
                    [conf, cx_offset, cy_offset, torch.log(p_w), torch.log(p_h), *one_hot(CLASS_NUM, int(cls))]
                )
    return labels

打眼一瞅,妈呀,3个for循环,别怕,咱们一个一个来说。

参数我就不一一介绍了,代码里我写过注释的。

第一个for循环

for feature_size, anchors in ANCHORS_GROUP.items():
        labels[feature_size] = torch.zeros(
            [int(resize_img_size[0] / feature_size), int(resize_img_size[1] / feature_size), 3, 5 + CLASS_NUM])

featurefe_size是32,16,8就是下采样的倍数,anchors对应的就是当前这个featuremap下的3个anchor的宽高,然后我们创建一了全零的tensor,它的维度是【下采样featurefe_size后的高,下采样featurefe_size后的宽,3,5+类别总数】,比如一个图片的宽高是640*640,你下采样32倍后,此时这个label的维度就是 【20,20,3,5+类别总数】,括号里面的3表示3个anchor,5表示【conf,cx_offset,cy_offset,p_w,p_h】,讲到这里你就应该知道,我上一篇提问题的答案了吧。至于conf,cx_offset,cy_offset,p_w,p_h是什么,看下面。

第二个for循环

for box in boxes:
        cls, xmin, ymin, xmax, ymax = box
        cx = (xmin + xmax) / 2
        cy = (ymin + ymax) / 2
        w = xmax - xmin
        h = ymax - ymin
        cx_offset, cx_index = math.modf(cx / feature_size)
        cy_offset, cy_index = math.modf(cy / feature_size)

 这是不是回答了上面的5个里面的2个参数,cx_offset就是目标中心点的x坐标,cy_offset就是目标中心的y坐标,w就是目标的宽,h就是目标的高,然后你会看到我们又用了math.modf这个函数,它的作用就是分开小数和整数部分,一会还很有用的东西就是cx_index和cy_index是什么,我们第三个for循环来讲

第三个for循环

for i, anchor in enumerate(anchors):
                anchor_area = ANCHORS_GROUP_AREA[feature_size][i]
                p_w, p_h = w / anchor[0], h / anchor[1]
                conf = IOU(gt_box=[xmin, ymin, xmax, ymax],
                           anchor=[cx - (anchor[0] / 2), cy - (anchor[1] / 2), cx + (anchor[0] / 2),
                                   cy + (anchor[1] / 2)])
                labels[feature_size][int(cy_index), int(cx_index), i] = torch.tensor(
                    [conf, cx_offset, cy_offset, torch.log(p_w), torch.log(p_h), *one_hot(CLASS_NUM, int(cls))]

我们可以看到,我们用w和h除以了anchor的w,h,得到了p_w,p_h这个两个变量,这个两个变量也是5中的两个参数,那么为什么要除以anchor的w,h呢?这就是小马哥牛x的地方,大家慢慢体会。conf就是anchor和目标矩形框的IOU,至于什么是IOU,IOU就是两个矩形的交集/并集,最后我们就可以以往刚刚创建的全零的label里面填值了,填在哪里呢?就填在cx_index和cy_index处。我知道,这么讲下来还是有点抽象。于是我准备给大家画一个图来模拟一下。

这只是一个下采样8倍的featuremap的对应其中一个anchor计算过程。图画的不好,先这样,到时候让小罗帮我出一个精修的图。

这个部分是我觉得YOLO最难理解的部分了,不过理顺了,你就大彻大悟了。

由此可见你我理解起来都这么费劲的话,小马哥当时是多么强大啊,能想到这些真的是无敌的存在啊。再次致敬。

ok,数据准备的部分我们就到这里了,下一期我们就可以开始训练了

我要去搞我的那台歇菜的电脑了。

至此,敬礼,salute!!!!

差点忘了咩咩狗,上图

 

猜你喜欢

转载自blog.csdn.net/guligedong/article/details/121490686