cudnn_benchmark = True ## True for accelerating the training speed
crop_size = 511 # Crop size around a bounding box
exemplar_size = 127 # Exemplar size
search_size = 255 # Search size
# model settings
model = dict(
type='SiamRPN', # the type of single object tracker
backbone=dict( # The config of backbone
type='SOTResNet', # The type of the backbone
depth=50, # The depth of backbone, usually it is 50 for ResNet backbones.
out_indices=(1, 2, 3), # The index of output feature maps produced in each stage
frozen_stages=4, # The weights in the first 1 stage are fronzen
strides=(1, 2, 1, 1), # The stride of conv in each stage
dilations=(1, 1, 2, 4), # The dilation of conv in each stage
norm_eval=True, # Whether to freeze the statistics in BN
init_cfg=dict(
type='Pretrained',
checkpoint= # noqa: E251
'https://download.openmmlab.com/mmtracking/pretrained_weights/sot_resnet50.model' # noqa: E501
)), # The pretrained weights of backbone
neck=dict(
type='ChannelMapper', # The neck is ChannelMapper.
in_channels=[512, 1024, 2048], # The input channels, this is consistent with the output channels of backbone
out_channels=256, # The output channels of each level of the pyramid feature map
kernel_size=1, # kernel size of convs in ChannelMapper
norm_cfg=dict(type='BN'), # The config of normalization layers.
act_cfg=None), # The config of activation layers.
head=dict(
type='SiameseRPNHead', # The type of head.
anchor_generator=dict( # The config of anchor generator
type='SiameseRPNAnchorGenerator', # anchor generator for SiameseRPN++
strides=[8],
# The strides of the anchor generator. This is consistent with the FPN feature strides. The strides will be taken as base_sizes if base_sizes is not set.
ratios=[0.33, 0.5, 1, 2, 3], # The ratio between height and width.
scales=[8]),
# Basic scale of the anchor, the area of the anchor in one position of a feature map will be scale * base_sizes
in_channels=[256, 256, 256], # The input channels, this is consistent with the output channels of neck
weighted_sum=True,
# If True, use learnable weights to weightedly sum the output of multi heads in siamese rpn , otherwise, use averaging.
bbox_coder=dict( # Config of box coder to encode and decode the boxes during training and testing
type='DeltaXYWHBBoxCoder',
# Type of box coder. 'DeltaXYWHBBoxCoder' is applied for most of methods. Refer to https://github.com/open-mmlab/mmdetection/blob/master/mmdet/core/bbox/coder/delta_xywh_bbox_coder.py#L9 for more details.
target_means=[0., 0., 0., 0.], # The target means used to encode and decode boxes
target_stds=[1., 1., 1., 1.]), # The standard variance used to encode and decode boxes
loss_cls=dict( # Config of loss function for the classification branch
type='CrossEntropyLoss', # Type of loss for classification branch, we also support FocalLoss etc.
reduction='sum',
loss_weight=1.0), # Loss weight of the classification branch.
loss_bbox=dict( # Config of loss function for the regression branch.
type='L1Loss',
# Type of loss, we also support many IoU Losses and smooth L1-loss, etc. Refer to https://github.com/open-mmlab/mmdetection/blob/master/mmdet/models/losses/smooth_l1_loss.py#L56 for implementation.
reduction='sum',
loss_weight=1.2)), # Loss weight of the regression branch.
train_cfg=dict( # Config of training hyperparameters for rpn and rcnn
rpn=dict( # Training config of rpn
assigner=dict( # Config of assigner
type='MaxIoUAssigner',
# Type of assigner, MaxIoUAssigner is used for many common detectors. Refer to https://github.com/open-mmlab/mmdetection/blob/master/mmdet/core/bbox/assigners/max_iou_assigner.py#L10 for more details.
pos_iou_thr=0.6, # IoU >= threshold 0.6 will be taken as positive samples
neg_iou_thr=0.3, # IoU < threshold 0.3 will be taken as negative samples
min_pos_iou=0.6, # The minimal IoU threshold to take boxes as positive samples
match_low_quality=False),
# Whether to match the boxes under low quality (see API doc for more details).
sampler=dict( # Config of positive/negative sampler
type='RandomSampler',
# Type of sampler, PseudoSampler and other samplers are also supported. Refer to https://github.com/open-mmlab/mmdetection/blob/master/mmdet/core/bbox/samplers/random_sampler.py#L8 for implementation details.
num=64, # Number of samples when the examplar image and search image are positive pair.
pos_fraction=0.25,
# The ratio of positive samples in the total samples when the examplar image and search image are positive pair.
add_gt_as_proposals=False), # Whether add GT as proposals after sampling.
num_neg=16, # Number of negative samples when the examplar image and search image are negative pair.
exemplar_size=exemplar_size,
search_size=search_size)),
test_cfg=dict(
exemplar_size=exemplar_size,
search_size=search_size,
context_amount=0.5, # the amount of context
center_size=7, # the size of cropping the center feature maps of examplar image
rpn=dict(penalty_k=0.05, window_influence=0.42, lr=0.38))) # used to smooth the predicted tracking box.
data_root = 'data/' # Dataset type, this will be used to define the dataset
train_pipeline = [
dict(
type='PairSampling', # sampling method in training
frame_range=5, # the sampling range of search frames in the same video for template frame
pos_prob=0.8, # the probility of sampling positive sample pairs
filter_template_img=False), # whether to exclude template frame when sampling search frame
dict(type='LoadMultiImagesFromFile', # First pipeline to load multi images from files path
to_float32=True), # convert the image to np.float32
dict(type='SeqLoadAnnotations', # Second pipeline to load annotations for multi images
with_bbox=True), # Whether to use bounding box, True for detection
dict(
type='SeqCropLikeSiamFC', # crop images like SiamFC does.
context_amount=0.5, # the amount of context
exemplar_size=exemplar_size,
crop_size=crop_size),
dict(
type='SeqShiftScaleAug', # shift and rescale images
target_size=[exemplar_size, search_size], # the target size of each image
shift=[4, 64], # the max shift offset for each image
scale=[0.05, 0.18]), # the max rescale offset for each image
dict(type='SeqColorAug', # color augmentation
prob=[1.0, 1.0]), # the probability color augmentaion for each image
dict(type='SeqBlurAug', # blur augmentation
prob=[0.0, 0.2]), # the probability color augmentaion for each image
dict(type='VideoCollect', keys=['img', 'gt_bboxes', 'is_positive_pairs']),
# Pipeline that decides which keys in the data should be passed to the video detector
dict(type='ConcatVideoReferences'), # Pipeline that concats references images
dict(type='SeqDefaultFormatBundle', # Default format bundle to gather data in the pipeline
ref_prefix='search') # The prefix key for reference images.
]
test_pipeline = [
dict(type='LoadImageFromFile', to_float32=True), # First pipeline to load images from file path
dict(type='LoadAnnotations', with_bbox=True), # Second pipeline to load annotations for image
dict(
type='MultiScaleFlipAug', # An encapsulation that encapsulates the testing augmentations
scale_factor=1, # the scale factor to resize the input image
flip=False, # Whether to flip images during testing
transforms=[
dict(type='VideoCollect', keys=['img', 'gt_bboxes']),
# Collect pipeline that collect necessary keys for testing.
dict(type='ImageToTensor', keys=['img']) # convert image to tensor
])
]
# dataset settings
data = dict(
samples_per_gpu=28, # Batch size of a single GPU
workers_per_gpu=8, # Worker to pre-fetch data for each single GPU
persistent_workers=True, # Setting of persistent workers
samples_per_epoch=600000, # The number of training samples per epoch
train=dict(
type='RandomSampleConcatDataset', # Sampling the comcatenated datasets ramdomly
dataset_sampling_weights=[0.25, 0.2, 0.55], # The sampling weights of concatenated dataset
dataset_cfgs=[
dict(
type='SOTImageNetVIDDataset', # Type of dataset
ann_file=data_root +
'ILSVRC/annotations/imagenet_vid_train.json', # Path of annotation file
img_prefix=data_root + 'ILSVRC/Data/VID', # Prefix of image path
pipeline=train_pipeline, # pipeline, this is passed by the train_pipeline created before.
split='train', # Split of dataset
test_mode=False), # Whether test mode
dict(
type='SOTCocoDataset', # Type of dataset
ann_file=data_root +
'coco/annotations/instances_train2017.json', # Path of annotation file
img_prefix=data_root + 'coco/train2017', # Prefix of image path
pipeline=train_pipeline, # pipeline, this is passed by the train_pipeline created before.
split='train', # Split of dataset
test_mode=False), # Whether test mode
dict(
type='SOTCocoDataset', # Type of dataset
ann_file=data_root +
'ILSVRC/annotations/imagenet_det_30plus1cls.json', # Path of annotation file
img_prefix=data_root + 'ILSVRC/Data/DET', # Prefix of image path
pipeline=train_pipeline, # pipeline, this is passed by the train_pipeline created before.
split='train', # Split of dataset
test_mode=False) # Whether test mode
]),
val=dict( # Validation dataset config
type='LaSOTDataset',
ann_file=data_root + 'lasot/annotations/lasot_test_infos.txt', # Path of dataset information file
img_prefix=data_root + 'lasot/LaSOTBenchmark', # Prefix of image path
pipeline=test_pipeline, # Pipeline is passed by test_pipeline created before
split='test', # split of dataset
test_mode=True, # whether test mode
only_eval_visible=True), # whether to only evaluate the method on frames where the object is visible in LaSOT
test=dict( # Test dataset config, modify the ann_file for test-dev/test submission
type='LaSOTDataset',
ann_file=data_root + 'lasot/annotations/lasot_test_infos.txt', # Path of dataset information file
img_prefix=data_root + 'lasot/LaSOTBenchmark', # Prefix of image path
pipeline=test_pipeline, # Pipeline is passed by test_pipeline created before
split='test', # Split of dataset
test_mode=True, # Whether test mode
only_eval_visible=True)) # whether to only evaluate the method on frames where the object is visible in LaSOT
# optimizer
optimizer = dict(
# Config used to build optimizer, support all the optimizers in PyTorch whose arguments are also the same as those in PyTorch
type='SGD',
lr=0.005,
momentum=0.9,
weight_decay=0.0001,
paramwise_cfg=dict(
custom_keys=dict(backbone=dict(lr_mult=0.1, decay_mult=1.0))))
optimizer_config = dict(
# Config used to build the optimizer hook, refer to https://github.com/open-mmlab/mmcv/blob/master/mmcv/runner/hooks/optimizer.py#L8 for implementation details.
type='SiameseRPNOptimizerHook',
backbone_start_train_epoch=10,
backbone_train_layers=['layer2', 'layer3', 'layer4'],
grad_clip=dict(max_norm=10.0, norm_type=2))
# learning policy
lr_config = dict( # Learning rate scheduler config used to register LrUpdater hook
policy='SiameseRPN',
lr_configs=[
dict(type='step', start_lr_factor=0.2, end_lr_factor=1.0, end_epoch=5),
dict(type='log', start_lr_factor=1.0, end_lr_factor=0.1, end_epoch=20),
])
# checkpoint saving
checkpoint_config = dict(
interval=1) # Config to set the checkpoint hook, Refer to https://github.com/open-mmlab/mmcv/blob/master/mmcv/runner/hooks/checkpoint.py for implementation.
evaluation = dict(
metric=['track'],
interval=1,
start=10,
rule='greater',
save_best='success') # The config to build the evaluation hook
# yapf:disable
log_config = dict( # Config to register logger hook
interval=50, # Interval to print the log
hooks=[
dict(type='TextLoggerHook', by_epoch=False),
dict(type='TensorboardLoggerHook', by_epoch=False),
dict(type='WandbLoggerHook', by_epoch=False,
# The Wandb logger is also supported, It requires `wandb` to be installed.
init_kwargs={'entity': "OpenMMLab", # The entity used to log on Wandb
'project': "MMTracking", # Project name in WandB
'config': cfg_dict}), # Check https://docs.wandb.ai/ref/python/init for more init arguments.
]) # ClearMLLoggerHook, DvcliveLoggerHook, MlflowLoggerHook, NeptuneLoggerHook, PaviLoggerHook, SegmindLoggerHook are also supported based on MMCV implementation.
# yapf:enable
# runtime settings
total_epochs = 20 # Total epochs to train the model
dist_params = dict(backend='nccl') # Parameters to setup distributed training, the port is set to 29500 by default
log_level = 'INFO' # The level of logging.
work_dir = './work_dirs/xxx' # Directory to save the model checkpoints and logs for the current experiments.
load_from = None # load models as a pre-trained model from a given path. This will not resume training.
resume_from = None # Resume checkpoints from a given path, the training will be resumed from the epoch when the checkpoint's is saved.
workflow = [('train',
1)] # Workflow for runner. [('train', 1)] means there is only one workflow and the workflow named 'train' is executed once. The workflow trains the model by 7 epochs according to the total_epochs.