1. 配置环境:
使用detectron2配置的环境,所以也是复制之前电脑上用过detectron2的环境
conda create -n mask2former --clone PatchDCT
conda activate mask2former
然后在requirement里面下载需要的包
另外在mask2former中还需要make一下:
2. 数据集配置
利用之前配置好的coco数据集,但由于maskFormer/mask2Former使用的数据集是包含实例分割和语义分割,还需要在datasets/prepare_ade20k_sem_seg.py输出符合代码运行的数据集格式。
环境里面还需要导入包:
pip install git+https://github.com/cocodataset/panopticapi.git
在trin_net.py加入:(这个在之前创建自己的coco数据集也有提到)
# 自己的数据集
from detectron2.data import DatasetCatalog
from detectron2.data.datasets.coco import load_coco_json
os.environ['CUDA_LAUNCH_BLOCKING'] = '1'
# 声明类别,尽量保持 #需修改成为自己的类别名称
# CLASS_NAMES = ["_background_", "person", "bicycle", "car", "UAV"] # 没有背景就不标注背景
CLASS_NAMES = ["person", "bicycle", "car", "UAV"]
# 数据集类别元数据
DATASET_CATEGORIES = [
{"name": "person", "id": 0, "isthing": 1, "color": [219, 142, 185]},
{"name": "bicycle", "id": 1, "isthing": 1, "color": [119, 11, 32]},
{"name": "car", "id": 2, "isthing": 1, "color": [0, 0, 142]},
{"name": "UAV", "id": 3, "isthing": 1, "color": [119, 11, 32]},
]
# 数据集路径 此路径需修改为自己的路径
DATASET_ROOT = r'G:/coco_4classes'
ANN_ROOT = os.path.join(DATASET_ROOT, 'annotations')
TRAIN_PATH = os.path.join(DATASET_ROOT, 'train2017')
VAL_PATH = os.path.join(DATASET_ROOT, 'val2017')
TRAIN_JSON = os.path.join(ANN_ROOT, 'instances_train2017.json')
# VAL_JSON = os.path.join(ANN_ROOT, 'val.json')
VAL_JSON = os.path.join(ANN_ROOT, 'instances_val2017.json')
# print(TRAIN_PATH)
# 声明数据集的子集 coco_my_train 修改为自己的数据集名字
PREDEFINED_SPLITS_DATASET = {
"coco_my_train": (TRAIN_PATH, TRAIN_JSON),
"coco_my_val": (VAL_PATH, VAL_JSON),
}
# 注册数据集
def register_dataset():
"""
purpose: register all splits of dataset with PREDEFINED_SPLITS_DATASET
"""
for key, (image_root, json_file) in PREDEFINED_SPLITS_DATASET.items():
register_dataset_instances(name=key,
metadate=get_dataset_instances_meta(),
json_file=json_file,
image_root=image_root)
def get_dataset_instances_meta():
"""
purpose: get metadata of dataset from DATASET_CATEGORIES
return: dict[metadata]
"""
thing_ids = [k["id"] for k in DATASET_CATEGORIES if k["isthing"] == 1]
thing_colors = [k["color"] for k in DATASET_CATEGORIES if k["isthing"] == 1]
# assert len(thing_ids) == 2, len(thing_ids)
thing_dataset_id_to_contiguous_id = {k: i for i, k in enumerate(thing_ids)}
thing_classes = [k["name"] for k in DATASET_CATEGORIES if k["isthing"] == 1]
ret = {
"thing_dataset_id_to_contiguous_id": thing_dataset_id_to_contiguous_id,
"thing_classes": thing_classes,
"thing_colors": thing_colors,
}
return ret
# # 注册数据集实例,加载数据集中的对象实例
def register_dataset_instances(name, metadate, json_file, image_root):
"""
purpose: register dataset to DatasetCatalog,
register metadata to MetadataCatalog and set attribute
"""
DatasetCatalog.register(name, lambda: load_coco_json(json_file, image_root, name))
MetadataCatalog.get(name).set(json_file=json_file,
image_root=image_root,
evaluator_type="coco",
**metadate)
# 注册数据集和元数据
def plain_register_dataset():
# 训练集
DatasetCatalog.register("coco_my_train", lambda: load_coco_json(TRAIN_JSON, TRAIN_PATH))
MetadataCatalog.get("coco_my_train").set(thing_classes=CLASS_NAMES, # 可以选择开启,但是不能显示中文,这里需要注意,中文的话最好关闭
evaluator_type='coco', # 指定评估方式
json_file=TRAIN_JSON,
image_root=TRAIN_PATH)
# DatasetCatalog.register("coco_my_val", lambda: load_coco_json(VAL_JSON, VAL_PATH, "coco_2017_val"))
# 验证/测试集
DatasetCatalog.register("coco_my_val", lambda: load_coco_json(VAL_JSON, VAL_PATH))
MetadataCatalog.get("coco_my_val").set(thing_classes=CLASS_NAMES, # 可以选择开启,但是不能显示中文,这里需要注意,中文的话最好关闭
evaluator_type='coco', # 指定评估方式
json_file=VAL_JSON,
image_root=VAL_PATH)
再在def setup 里面修改配置参数即可
注意别忘记在main函数加入:
plain_register_dataset() # 新加的数据集代码
3. 出现问题:
1. Attribute 'ignore_label' does not exist in the metadata of dataset 'coco_my_train'
网上的原因是说detectron2版本低于0.4.0,但是我的版本是0.6.0,所以就直接在注册自己的数据集里面加入了这个参数:
# 注册数据集和元数据
def plain_register_dataset():
# 训练集
DatasetCatalog.register("coco_my_train", lambda: load_coco_json(TRAIN_JSON, TRAIN_PATH))
MetadataCatalog.get("coco_my_train").set(thing_classes=CLASS_NAMES, # 可以选择开启,但是不能显示中文,这里需要注意,中文的话最好关闭
evaluator_type='coco', # 指定评估方式
ignore_label=255, # 缺少这个标签,加上
json_file=TRAIN_JSON,
image_root=TRAIN_PATH)
# DatasetCatalog.register("coco_my_val", lambda: load_coco_json(VAL_JSON, VAL_PATH, "coco_2017_val"))
# 验证/测试集
DatasetCatalog.register("coco_my_val", lambda: load_coco_json(VAL_JSON, VAL_PATH))
MetadataCatalog.get("coco_my_val").set(thing_classes=CLASS_NAMES, # 可以选择开启,但是不能显示中文,这里需要注意,中文的话最好关闭
evaluator_type='coco', # 指定评估方式
ignore_label=255, # 缺少这个标签,加上
json_file=VAL_JSON,
image_root=VAL_PATH)
2. ValueError: matrix contains invalid numeric entries
经查阅有两种解决方式
(1).降低学习率lr
(2).在_lsap.py文件中加上
if np.any(np.isneginf(cost_matrix) | np.isnan(cost_matrix)):
raise ValueError("matrix contains invalid numeric entries")
我先尝试了第一个办法,把学习率降低到了0.0001。
3. Attribute 'thing_dataset_id_to_contiguous_id' does not exist in the metadata of dataset 'coco_my_train'.
但是我在get_dataset_instances_meta()定义了这个关于metadata的函数,是定义了thing_dataset_id_to_contiguous_id'
def get_dataset_instances_meta():
"""
purpose: get metadata of dataset from DATASET_CATEGORIES
return: dict[metadata]
"""
thing_ids = [k["id"] for k in DATASET_CATEGORIES if k["isthing"] == 1]
thing_colors = [k["color"] for k in DATASET_CATEGORIES if k["isthing"] == 1]
# assert len(thing_ids) == 2, len(thing_ids)
thing_dataset_id_to_contiguous_id = {k: i for i, k in enumerate(thing_ids)}
thing_classes = [k["name"] for k in DATASET_CATEGORIES if k["isthing"] == 1]
ret = {
"thing_dataset_id_to_contiguous_id": thing_dataset_id_to_contiguous_id,
"thing_classes": thing_classes,
"thing_colors": thing_colors,
}
return ret
利用新的代码注册数据集,直接在train_net里面加入class Register 注册自己的数据集:
# 注册自己的数据集
import cv2
from detectron2.data import DatasetCatalog
from detectron2.data.datasets.coco import load_coco_json
from detectron2.utils.visualizer import Visualizer
class Register:
"""用于注册自己的数据集"""
# 声明类别,尽量保持 #需修改成为自己的类别名称
# CLASS_NAMES = ["_background_", "person", "bicycle", "car", "UAV"] # 没有背景就不标注背景
CLASS_NAMES = ["person", "bicycle", "car", "UAV"]
# ROOT = r'G:/coco_4classes' # 图片所在目录
def __init__(self):
self.CLASS_NAMES = Register.CLASS_NAMES
# 数据集路径,此路径需修改为自己的路径
DATASET_ROOT = r'G:/coco_4classes'
self.ANN_ROOT = os.path.join(DATASET_ROOT, 'annotations')
# self.ANN_ROOT = "/home/user/yourdir/detectron2/datasets/coco/annotations"
self.TRAIN_PATH = os.path.join(DATASET_ROOT, 'train2017')
self.VAL_PATH = os.path.join(DATASET_ROOT, 'val2017')
self.TRAIN_JSON = os.path.join(self.ANN_ROOT, 'instances_train2017.json')
self.VAL_JSON = os.path.join(self.ANN_ROOT, 'instances_val2017.json')
# 声明数据集的子集,coco_my_train 修改为自己的数据集名字
self.PREDEFINED_SPLITS_DATASET = {
"coco_my_train": (self.TRAIN_PATH, self.TRAIN_JSON),
"coco_my_val": (self.VAL_PATH, self.VAL_JSON),
}
# 注册数据集
def register_dataset(self):
"""
purpose: register all splits of datasets with PREDEFINED_SPLITS_DATASET
注册数据集(这一步就是将自定义数据集注册进Detectron2)
"""
for key, (image_root, json_file) in self.PREDEFINED_SPLITS_DATASET.items():
self.register_dataset_instances(name=key,
json_file=json_file,
image_root=image_root)
@staticmethod
def register_dataset_instances(name, json_file, image_root):
"""
purpose: register datasets to DatasetCatalog,
register metadata to MetadataCatalog and set attribute
注册数据集实例,加载数据集中的对象实例
"""
DatasetCatalog.register(name, lambda: load_coco_json(json_file, image_root, name))
MetadataCatalog.get(name).set(json_file=json_file,
image_root=image_root,
evaluator_type="coco")
def plain_register_dataset(self):
"""注册数据集和元数据"""
# 训练集
DatasetCatalog.register("coco_my_train", lambda: load_coco_json(self.TRAIN_JSON, self.TRAIN_PATH))
MetadataCatalog.get("coco_my_train").set(thing_classes=self.CLASS_NAMES, # 可以选择开启,但是不能显示中文,这里需要注意,中文的话最好关闭
evaluator_type='coco', # 指定评估方式
json_file=self.TRAIN_JSON,
image_root=self.TRAIN_PATH)
# DatasetCatalog.register("coco_my_val", lambda: load_coco_json(VAL_JSON, VAL_PATH, "coco_2017_val"))
# 验证/测试集
DatasetCatalog.register("coco_my_val", lambda: load_coco_json(self.VAL_JSON, self.VAL_PATH))
MetadataCatalog.get("coco_my_val").set(thing_classes=self.CLASS_NAMES, # 可以选择开启,但是不能显示中文,这里需要注意,中文的话最好关闭
evaluator_type='coco', # 指定评估方式
json_file=self.VAL_JSON,
image_root=self.VAL_PATH)
def checkout_dataset_annotation(self, name="coco_my_val"):
"""
查看数据集标注,可视化检查数据集标注是否正确,
这个也可以自己写脚本判断,其实就是判断标注框是否超越图像边界
可选择使用此方法
"""
# dataset_dicts = load_coco_json(TRAIN_JSON, TRAIN_PATH, name)
dataset_dicts = load_coco_json(self.TRAIN_JSON, self.TRAIN_PATH)
print(len(dataset_dicts))
for i, d in enumerate(dataset_dicts, 0):
# print(d)
img = cv2.imread(d["file_name"])
visualizer = Visualizer(img[:, :, ::-1], metadata=MetadataCatalog.get(name), scale=1.5)
vis = visualizer.draw_dataset_dict(d)
# cv2.imshow('show', vis.get_image()[:, :, ::-1])
cv2.imwrite('out/' + str(i) + '.jpg', vis.get_image()[:, :, ::-1])
# cv2.waitKey(0)
if i == 200:
break
注意在def main(args)加入这个:
def main(args):
cfg = setup(args)
# 记得加入这个
Register().register_dataset() # register my dataset
运行即可。