专栏首页CV_LearnDetectron学习三:自定义数据层
原创

Detectron学习三:自定义数据层

博客:https://www.cnblogs.com/marsggbo/p/11727556.html

官方文档:https://detectron2.readthedocs.io/tutorials/datasets.html

自定义数据层需要实现的步骤:

1:注册DatasetCatalog----将自定义的数据类型转换为detectron2标准的数据格式

2:注册metadataCatalog---(可选)

3:更新配置文件Config

一、注册DatasetCatalog

参考文件/detectron2/data/datasets/pascal_voc.py

# -*- coding: utf-8 -*-
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved

from fvcore.common.file_io import PathManager
import os
import numpy as np
import xml.etree.ElementTree as ET

from detectron2.structures import BoxMode
from detectron2.data import DatasetCatalog, MetadataCatalog


__all__ = ["register_pascal_voc"]


# fmt: off
CLASS_NAMES = [
    "aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat",
    "chair", "cow", "diningtable", "dog", "horse", "motorbike", "person",
    "pottedplant", "sheep", "sofa", "train", "tvmonitor",
]   ##为xml中目标的name名称
# fmt: on


def load_voc_instances(dirname: str, split: str):
    """
    Load Pascal VOC detection annotations to Detectron2 format.

    Args:
        dirname: Contain "Annotations", "ImageSets", "JPEGImages"
        split (str): one of "train", "test", "val", "trainval"
    """
    with PathManager.open(os.path.join(dirname, "ImageSets", "Main", split + ".txt")) as f:
        fileids = np.loadtxt(f, dtype=np.str)

    dicts = []
    ######################
    xml解析(省略)
    ######################
    return dicts

def register_pascal_voc(name, dirname, split, year):
    DatasetCatalog.register(name, lambda: load_voc_instances(dirname, split))
    MetadataCatalog.get(name).set(
        thing_classes=CLASS_NAMES, dirname=dirname, year=year, split=split
    )

/detectron2/data/datasets/builtin.py中注册实现:

# ==== Predefined splits for PASCAL VOC ===========
def register_all_pascal_voc(root="datasets"):
    SPLITS = [
        ("voc_2007_trainval", "VOC2007", "trainval"),
        ("voc_2007_train", "VOC2007", "train"),
        ("voc_2007_val", "VOC2007", "val"),
        ("voc_2007_test", "VOC2007", "test"),
        ("voc_2012_trainval", "VOC2012", "trainval"),
        ("voc_2012_train", "VOC2012", "train"),
        ("voc_2012_val", "VOC2012", "val"),
    ]   ##该列表中的名称与configs中yaml中DATASETS.{TRAIN,TEST}中的名字完全一致
    
    for name, dirname, split in SPLITS:
        year = 2007 if "2007" in name else 2012
        register_pascal_voc(name, os.path.join(root, dirname), split, year)
        MetadataCatalog.get(name).evaluator_type = "pascal_voc"

步骤:

1:实现函数load_voc_instances,返回detectron2标准数据格式。

标准数据格式:datasetFormat=[dict1,dict2,dict3,....]  ##len(datasetFormat)为数据集大小,一张图像对应一个dict
dict1={
    "file_name":str, ##图像绝对路径
    "image_id":str or int,
    "annotations":[ ##list[dict]
        {
            "category_id":int,  ##类别索引,CLASS_NAMES.index(cls)的返回值,cls为类别名name
            "bbox":[float,float,float,float], ##排列顺序与下面bbox_mode有关
            "bbox_mode":int    ##XYXY_ABS:[xmin,ymin,xmax,ymax]  XYWH_ABS:[xmin,ymin,width,height]
                                ##XYXY_REL XYWH 相对与图像尺寸的坐标值,范围[0,1]
        },
        {
        },
    ]    
}

2:注册DatasetCatalog

def register_pascal_voc(name, dirname, split, year):
    DatasetCatalog.register(name, lambda: load_voc_instances(dirname, split))
 
 #################################
 类DatasetCatalog中register函数的定义
 @staticmethod
 def register(name,func):
        """
        Args:
            name (str): the name that identifies a dataset, e.g. "coco_2014_train".
            func (callable): a callable which takes no arguments and returns a list of dicts.
        """
  #############################
  此处使用了lambda表达式
  作用:借助lambda给回调函数传参,做了一个“函数打包”的操作,它把函数和它的参数列表打包在一起,得到一个新的函数,
  实际传入到register的并不是原来的load_voc_instances,而是打包得到的新函数。至于这个新函数叫做什么名字,对于
  我们来说是无所谓的(匿名函数),反正也只用这一次,下次还要用的话,lambda会再一次重新打包,得到新的匿名函数。

二、注册metadataCatalog -----没太明白具体是做什么用的,后续若有新的理解在进行补充

参考博客https://www.cnblogs.com/marsggbo/p/11727556.html

MetadataCatalog的作用是记录数据集的一些特征,这样我们就可以很方便的在整个代码中获取数据集的特征信息。在注册DatasetCatalog后,我们可以按如下栗子对MetadataCatalog进行注册并定义我们后面可能会用到的属性特征:

from detectron2.data import MetadataCatalog
MetadataCatalog.get("my_dataset").thing_classes = ["person", "dog"]

# 也可以这样
MetadataCatalog.get("my_dataset").set("thing_classes",["person", "dog"])

注意:如果你的数据集名字未注册过,MetadataCatalog.get会自动进行注册,然后会自动设置你所设定的属性值。

其实MetadataCatalog还有其他的特征属性可以设置,如stuff_classes,stuff_colors等等。你可能会好奇thing_classesstuff_classes有什么区别,区别如下:

  • 抽象解释:thing_classes用于指定instance-level任务,stuff_classes用于semantic segmentation任务。
  • 具体解释:像椅子,书这种可数的东西,就可以理解成thing,所以用于instance-level;而雪、天空这种不可数的就理解成stuff,所以用于semantic segmentation。参考On Seeing Stuff: The Perception of Materials by Humans and Machines

最后,get_detection_dataset_dicts会返回一个包含若干个dict的list,之所以是list是因为参数dataset_names也是一个list,这样我们就可以制定多个names来同时对数据进行读取。

三、修改配置文件 在对应加载的配置文件如/configs/PascalVOC-Detection/faster_rcnn_R_50_FPN.yaml中修改MODEL.NUM_CLASSES参数

DATASETS.{TRAIN,TEST}参数

。。。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Linux gdb+valgrind调试

    产生了 core 文件,我们该如何使用该 Core 文件进行调试呢?Linux 中可以使用 GDB 来调试 core 文件,步骤如下:

    CV_Learner
  • Detectron2学习二:目录结构、超参数配置、Trainer类

    参考链接:https://www.cnblogs.com/marsggbo/p/11677086.html

    CV_Learner
  • Detectron2学习四:build_train_loader流程

    DefaultTrainer类中函数build_train_loader(cfg)的实现流程

    CV_Learner
  • JavaScript 之 this

    在 JavaScript 中,this 的值是动态的,即一个函数中在不同的情况下被调用,this 的值可能是不同的。

    Joel
  • python metaclass ..

    关于Python2.x中metaclass这一黑科技,我原以为我是懂的,只有当被打脸的时候,我才认识到自己too young too simple someti...

    用户5760343
  • 2014年OA产品实施满意度:成行业最大短板 OA厂商需加强

    移动信息化研究中心认为,实施服务是当前的一个“短板”,企业客户对于实施服务的整体评价一般。 实施服务满意度评价主要包括了“项目顾问的管控能力、进场顾问的专业能力...

    人称T客
  • shell学习一变量的定义 原

    用符号$加上变量名如 $name 或${name},{}括号是为了确定变理边界,推荐使用

    用户2603479
  • Feign源码分析之FeignClientFactoryBean

         springcloud-openfeign-core-2.1.1.release.

    克虏伯
  • sql 语言

    sql 语言 DDL DDL 全称 Data Definition Language,即数据定义语言。 DATABASE 创建数据库 CREATE DATABA...

    静默虚空
  • Django -自定义命令

    IT故事会

扫码关注云+社区

领取腾讯云代金券