前言
最近在看实例分割与伪装目标检测相关的项目,看了几天solo和solov2的模型,在GitHub上搜索了之后想要复现solo-master,发现repository已经移动了,下载一直失败,而且现在很多目标检测和实例分割的代码都在mmdetection项目中集成了,看了mmdetection一周多,从配置环境开始有很多问题,这里就不一一赘述了,网上开源的配置教程有很多,官方的中文教程很多人不推荐,觉得说不清楚,但是我觉得自制数据集和转换为coco格式的数据集部分还是说的很清楚的,这里贴上链接:
https://mmdetection.readthedocs.io/zh-cn/stable/overview.html
本文主要讲一下怎么把自制的伪装目标检测数据集放入mmdetection的solo模型进行检测。
首先在这篇链接中给出了COD10K和NC4K数据集的coco数据集的json格式,将COD10K,分3040张图片做训练集,2026张图片做验证集,NC4K中4121张图片做测试集。
怎么把数据集转换为json格式我还没有了解全面,先用这两个数据集进行复现
https://github.com/PJLallen/OSFormer
这个开源模型中给出了数据集的json下载链接,由于是伪装目标检测数据集,所以没有物体类别,只需要把伪装的物体区分开就可以,所以在这里数据集设置类别为1,名称为’foreground’
1.修改
首先修改mmdet/datasets/coco.py文件,修改CocoDataset类,(还有一种方法是自建类,然后导入,我也尝试了这种方法,但是出现了registry的问题,花了很久没有解决,于是还用这种更改coco声明格式的方法)
class CocoDataset(BaseDetDataset):
"""Dataset for COCO."""
METAINFO = {
'classes':
('foregrouond'), #自定义的数据集的所有类别名称,这里我的只有一种foreground
# palette is a list of color tuples, which is used for visualization.
'palette':
[(220, 20, 60)] #不同实例类别的颜色,与类别数量一致即可
}
COCOAPI = COCO
# ann_id is unique in coco dataset.
ANN_ID_UNIQUE = True
比较重要的,我之前就是没有设置另一个文件的信息,所以一直不对:
修改mmdet/evaluation/functional/class_names.py,找到coco_classes函数的声明:
def coco_classes() -> list:
"""Class names of COCO."""
return [
'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train',
'truck', 'boat', 'traffic_light', 'fire_hydrant', 'stop_sign',
'parking_meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep',
'cow', 'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella',
'handbag', 'tie', 'suitcase', 'frisbee', 'skis', 'snowboard',
'sports_ball', 'kite', 'baseball_bat', 'baseball_glove', 'skateboard',
'surfboard', 'tennis_racket', 'bottle', 'wine_glass', 'cup', 'fork',
'knife', 'spoon', 'bowl', 'banana', 'apple', 'sandwich', 'orange',
'broccoli', 'carrot', 'hot_dog', 'pizza', 'donut', 'cake', 'chair',
'couch', 'potted_plant', 'bed', 'dining_table', 'toilet', 'tv',
'laptop', 'mouse', 'remote', 'keyboard', 'cell_phone', 'microwave',
'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase',
'scissors', 'teddy_bear', 'hair_drier', 'toothbrush'
]
修改为:
def coco_classes() -> list:
"""Class names of COCO."""
return [
'foreground'
]
到此为止coco部分已经改好了,其他就是自己的配置部分,我用的是configs/solo/decoupled-solo_r50_fpn_1x_coco.py,基于solo_r50_fpn_1x_coco.py,先看decoupled-solo_r50_fpn_1x_coco.py,再看solo_r50_fpn_1x_coco.py,
decoupled-solo_r50_fpn_1x_coco.py
_base_ = './solo_r50_fpn_1x_coco.py'
# model settings
model = dict(
mask_head=dict(
type='DecoupledSOLOHead',
num_classes=1, #这里的类别总数要修改
in_channels=256,
stacked_convs=7,
feat_channels=256,
strides=[8, 8, 16, 32, 32],
scale_ranges=((1, 96), (48, 192), (96, 384), (192, 768), (384, 2048)),
pos_scale=0.2,
num_grids=[40, 36, 24, 16, 12],
cls_down_index=0,
loss_mask=dict(
type='DiceLoss', use_sigmoid=True, activate=False,
loss_weight=3.0),
loss_cls=dict(
type='FocalLoss',
use_sigmoid=True,
gamma=2.0,
alpha=0.25,
loss_weight=1.0),
norm_cfg=dict(type='GN', num_groups=32, requires_grad=True)))
solo_r50_fpn_1x_coco.py
_base_ = [
'../_base_/datasets/coco_instance.py',
'../_base_/schedules/schedule_1x.py', '../_base_/default_runtime.py'
]
# model settings
model = dict(
type='SOLO',
data_preprocessor=dict(
type='DetDataPreprocessor',
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
bgr_to_rgb=True,
pad_mask=True,
pad_size_divisor=32),
backbone=dict(
type='ResNet',
depth=50,
num_stages=4,
out_indices=(0, 1, 2, 3),
frozen_stages=1,
init_cfg=dict(type='Pretrained', checkpoint='torchvision://resnet50'),
style='pytorch'),
neck=dict(
type='FPN',
in_channels=[256, 512, 1024, 2048],
out_channels=256,
start_level=0,
num_outs=5),
mask_head=dict(
type='SOLOHead',
num_classes=1, #这里的分割类别总数要更改,改为1
in_channels=256,
stacked_convs=7,
feat_channels=256,
strides=[8, 8, 16, 32, 32],
scale_ranges=((1, 96), (48, 192), (96, 384), (192, 768), (384, 2048)),
pos_scale=0.2,
num_grids=[40, 36, 24, 16, 12],
cls_down_index=0,
loss_mask=dict(type='DiceLoss', use_sigmoid=True, loss_weight=3.0),
loss_cls=dict(
type='FocalLoss',
use_sigmoid=True,
gamma=2.0,
alpha=0.25,
loss_weight=1.0),
norm_cfg=dict(type='GN', num_groups=32, requires_grad=True)),
# model training and testing settings
test_cfg=dict(
nms_pre=500,
score_thr=0.1,
mask_thr=0.5,
filter_thr=0.05,
kernel='gaussian', # gaussian/linear
sigma=2.0,
max_per_img=100))
# optimizer
optim_wrapper = dict(optimizer=dict(lr=0.01))
val_evaluator = dict(metric='segm')
test_evaluator = val_evaluator
这个比较全,是各个模块参数的设置,后面会讲解。
主要看coco_instance.py
# dataset settings
dataset_type = 'CocoDataset' #自己所用数据集名称
data_root = '/root/autodl-tmp/mmdetection/data/coco/' #数据集在项目中的位置
# Example to use different file client
# Method 1: simply set the data root and let the file I/O module
# automatically infer from prefix (not support LMDB and Memcache yet)
# data_root = 's3://openmmlab/datasets/detection/coco/'
# Method 2: Use `backend_args`, `file_client_args` in versions before 3.0.0rc6
# backend_args = dict(
# backend='petrel',
# path_mapping=dict({
# './data/': 's3://openmmlab/datasets/detection/',
# 'data/': 's3://openmmlab/datasets/detection/'
# }))
backend_args = None
train_pipeline = [
dict(type='LoadImageFromFile', backend_args=backend_args),
dict(type='LoadAnnotations', with_bbox=True, with_mask=True),
dict(type='Resize', scale=(1333, 800), keep_ratio=True), #有帖子说这里的scale也可以改,我没有改
dict(type='RandomFlip', prob=0.5),
dict(type='PackDetInputs')
]
test_pipeline = [
dict(type='LoadImageFromFile', backend_args=backend_args),
dict(type='Resize', scale=(1333, 800), keep_ratio=True),
# If you don't have a gt annotation, delete the pipeline
dict(type='LoadAnnotations', with_bbox=True, with_mask=True),
dict(
type='PackDetInputs',
meta_keys=('img_id', 'img_path', 'ori_shape', 'img_shape',
'scale_factor'))
]
train_dataloader = dict(
batch_size=2,
num_workers=2,
persistent_workers=True,
sampler=dict(type='DefaultSampler', shuffle=True),
batch_sampler=dict(type='AspectRatioBatchSampler'),
dataset=dict(
type=dataset_type,
data_root=data_root,
ann_file='annotations/train.json', #训练数据集的json文件位置
data_prefix=dict(img='train'),
filter_cfg=dict(filter_empty_gt=True, min_size=32),
pipeline=train_pipeline,
backend_args=backend_args))
val_dataloader = dict(
batch_size=1,
num_workers=2,
persistent_workers=True,
drop_last=False,
sampler=dict(type='DefaultSampler', shuffle=False),
dataset=dict(
type=dataset_type,
data_root=data_root,
ann_file='annotations/val.json', #验证数据集的json文件位置
data_prefix=dict(img='val/'),
test_mode=True,
pipeline=test_pipeline,
backend_args=backend_args))
test_dataloader = val_dataloader
val_evaluator = dict(
type='CocoMetric',
ann_file=data_root + 'annotations/val.json',
metric=['bbox', 'segm'],
format_only=False,
backend_args=backend_args)
test_evaluator = val_evaluator
2.train
注意!!!修改之后要重新编译!!!!!!
划重点!!1.4因为租的服务器不好用换了一个,更新代码之后又忘记重新编译!!!
运行代码:
python setup.py install
我租的是单GPU,训练模型时在terminal运行命令:
python tools/train.py configs/decoupled-solo_r50_fpn_1x_coco.py
即可,如果选择多GPU,运行时命令选择:
python tools/dist_train.py XXXX
(什么时候可以显卡自由呜呜)