Efficientdet源码详解

1.参数配置 

      最重要的参数配置如下 

-p:配置文件,需要在project文件夹下新建配置文件
 -c:efficientdet的版本,efficientdet B0-B7
 -n:windows为0,linix根据自己的需求修改
 --batch_size:batch大小
 '--data_path:数据集路径
 -p data --batch_size 16

其中,在运行时,需要在project文件夹下新建配置文件,并指定在-p下。其中,mean/std/anchors_scales/anchors_ratios一般不用修改。

Efficientdet源码详解_第1张图片

2.dataloader数据读取

数据读取部分做得比较简单,没有使用过多的数据增强策略

数据读取部分如下:

  • 从json中取出图片名称,并读取图片,并归一化至0-1之间
  • 取出对应的标签,并将x,y,w,h转为x1,y1,x2,y2
  • 数据增强,仅仅进行标准化、平移、翻转等操作,最后,将图像resize到指定大小
class CocoDataset(Dataset):
    def __init__(self, root_dir, set='train2017', transform=None):

        self.root_dir = root_dir
        self.set_name = set
        self.transform = transform
        # 若是自己创建的coco数据,可以在此指定名称
        self.coco = COCO(os.path.join(self.root_dir, 'annotations', 'instances_' + self.set_name + '.json'))
        self.image_ids = self.coco.getImgIds()

        self.load_classes()

    def load_classes(self):

        # load class names (name -> label)
        categories = self.coco.loadCats(self.coco.getCatIds())
        categories.sort(key=lambda x: x['id'])

        self.classes = {}
        for c in categories:
            self.classes[c['name']] = len(self.classes)

        # also load the reverse (label -> name)
        self.labels = {}
        for key, value in self.classes.items():
            self.labels[value] = key

    def __len__(self):
        return len(self.image_ids)

    def __getitem__(self, idx):
        # 从json中取出图片名称,并读取图片,并归一化至0-1之间
        img = self.load_image(idx)
        # 取出对应的标签,并将x,y,w,h转为x1,y1,x2,y2
        annot = self.load_annotations(idx)
        sample = {'img': img, 'annot': annot}
        if self.transform:
            # 数据增强,仅仅进行标准化、平移、翻转等操作,最后,将图像resize到指定大小
            sample = self.transform(sample)
        return sample

    def load_image(self, image_index):
        image_info = self.coco.loadImgs(self.image_ids[image_index])[0]
        path = os.path.join(self.root_dir, self.set_name, image_info['file_name'])
        img = cv2.imread(path)
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

        return img.astype(np.float32) / 255.

    def load_annotations(self, image_index):
        # get ground truth annotations
        annotations_ids = self.coco.getAnnIds(imgIds=self.image_ids[image_index], iscrowd=False)
        annotations = np.zeros((0, 5))

        # some images appear to miss annotations
        if len(annotations_ids) == 0:
            return annotations

        # parse annotations
        coco_annotations = self.coco.loadAnns(annotations_ids)
        for idx, a in enumerate(coco_annotations):

            # some annotations have basically no width / height, skip them
            if a['bbox'][2] < 1 or a['bbox'][3] < 1:
                continue

            annotation = np.zeros((1, 5))
            annotation[0, :4] = a['bbox']
            annotation[0, 4] = a['category_id'] - 1
            annotations = np.append(annotations, annotation, axis=0)

        # transform from [x, y, w, h] to [x1, y1, x2, y2]
        annotations[:, 2] = annotations[:, 0] + annotations[:, 2]
        annotations[:, 3] = annotations[:, 1] + annotations[:, 3]

        return annotations

3.backbone

backbone采用efficientnet,详见博客:Efficientnet网络详解及构建_樱花的浪漫的博客-CSDN博客_efficientnet网络 \

需要注意的是,深度可分离卷积在pytorch的实现上,通过指定groups参数实现。

Efficientdet源码详解_第2张图片

 4.BiFPN

         首先,FPN实现了高维特征和低维特征的融合,PANet通过自上而下和自上而下的路径实现了更高程度的特征融合。但是,BiFPN做了两个方面的改进:(1)PANet进行特征融合时,是通过Concat的,一般高层和低层的特征贡献程度相同,BiFPN在特征融合时,通过一组可学习的归一化权重参数调整各层贡献程度。(2)BiFPN堆叠多层实现更高维度的特征融合。

Efficientdet源码详解_第3张图片

         在源码的实现上,单个BiFPN有两个核心,

  • 第一个是可学习参数的设定。首先,为各层生成一组可学习的权重参数,经过relu激活函数保证权重参数为正。对于权重参数的归一化,论文作者认为softmax归一化太慢,因此采用最简单的归一化:
  •  第二个是特征融合,对于特征融合,由于训练了一组权重参数,因此采用add比concat更适宜。在从上到下的路径时,特征融合由三部分组成,如上图(d)所示

最后,对提取的特征分别做分类和回归。

你可能感兴趣的:(目标检测,python,深度学习,人工智能,计算机视觉)