jbwang1997 / OBBDetection

OBBDetection is an oriented object detection library, which is based on MMdetection.
Apache License 2.0
520 stars 111 forks source link

obb fcos hrsc testing > IndexError: tuple index out of range #120

Closed geobao closed 2 years ago

geobao commented 2 years ago

I am trying to run OBB with FCOS in dataset HRSC2016. To do so I have based the config.py on an example of OBB with FCOS in dataset DOTA and removed these two parts: dict(type='LoadDOTASpecialInfo') dict(type='DOTASpecialIgnore', ignore_size=2)

I managed to execute the training with no problem. Then, when I try to run the testing, I get this error. What am I doing wrong?

Starting loading HRSC dataset information.
Finishing loading HRSC, get 2124 images, using 0.171s.
load checkpoint from local path: work_dirs/fcos_obb_r50_caffe_fpn_gn-head_4x4_1x_hrsc/latest.pth
[>>>>>>>>>>>>>>>                                   ] 137/453, 17.9 task/s, elapsed: 8s, ETA:    18s
[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>] 453/453, 17.9 task/s, elapsed: 25s, ETA:     0sTraceback (most recent call last):
  File "tools/test.py", line 153, in <module>
    main()
  File "tools/test.py", line 149, in main
    dataset.evaluate(outputs, args.eval, **kwargs)
  File "/work/OBBDetection/mmdet/datasets/obb/hrsc.py", line 126, in evaluate
    logger=logger)
  File "/work/OBBDetection/mmdet/core/evaluation/obb/obb_mean_ap.py", line 291, in eval_arb_map
    mean_ap, eval_results, dataset, area_ranges, logger=logger)
  File "/work/OBBDetection/mmdet/core/evaluation/obb/obb_mean_ap.py", line 354, in print_map_summary
    label_names[j], num_gts[i, j], results[j]['num_dets'],
IndexError: tuple index out of range

The configuration file is:

_base_ = [
    '../_base_/datasets/hrsc.py',
    '../_base_/schedules/schedule_1x.py',
    '../../_base_/default_runtime.py'
]
# model settings
model = dict(
    type='FCOSOBB',
    pretrained='open-mmlab://detectron/resnet50_caffe',
    backbone=dict(
        type='ResNet',
        depth=50,
        num_stages=4,
        out_indices=(0, 1, 2, 3),
        frozen_stages=1,
        norm_cfg=dict(type='BN', requires_grad=False),
        norm_eval=True,
        style='caffe'),
    neck=dict(
        type='FPN',
        in_channels=[256, 512, 1024, 2048],
        out_channels=256,
        start_level=1,
        add_extra_convs=True,
        extra_convs_on_inputs=False,  # use P5
        num_outs=5,
        relu_before_extra_convs=True),
    bbox_head=dict(
        type='OBBFCOSHead',
        num_classes=15,
        in_channels=256,
        stacked_convs=4,
        feat_channels=256,
        strides=[8, 16, 32, 64, 128],
        scale_theta=True,
        loss_cls=dict(
            type='FocalLoss',
            use_sigmoid=True,
            gamma=2.0,
            alpha=0.25,
            loss_weight=1.0),
        loss_bbox=dict(type='PolyIoULoss', loss_weight=1.0),
        loss_centerness=dict(
            type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0)))
# training and testing settings
train_cfg = dict(
    assigner=dict(
        type='MaxIoUAssigner',
        pos_iou_thr=0.5,
        neg_iou_thr=0.4,
        min_pos_iou=0,
        ignore_iof_thr=-1),
    allowed_border=-1,
    pos_weight=-1,
    debug=False)
test_cfg = dict(
    nms_pre=1000,
    min_bbox_size=0,
    score_thr=0.05,
    nms=dict(type='obb_nms', iou_thr=0.1),
    max_per_img=2000)
img_norm_cfg = dict(
    mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=False)
train_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(type='LoadOBBAnnotations', with_bbox=True,
         with_label=True, obb_as_mask=True),
    dict(type='Resize', img_scale=(1024, 1024), keep_ratio=True),
    dict(type='OBBRandomFlip', h_flip_ratio=0.5, v_flip_ratio=0.5),
    dict(type='Normalize', **img_norm_cfg),
    dict(type='RandomOBBRotate', rotate_after_flip=True,
         angles=(0, 0), vert_rate=0.5, vert_cls=['roundabout', 'storage-tank']),
    dict(type='Pad', size_divisor=32),
    #dict(type='DOTASpecialIgnore', ignore_size=2),
    dict(type='FliterEmpty'),
    dict(type='Mask2OBB', obb_type='obb'),
    dict(type='OBBDefaultFormatBundle'),
    dict(type='OBBCollect', keys=['img', 'gt_bboxes', 'gt_obboxes', 'gt_labels'])
]
test_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(
        type='MultiScaleFlipRotateAug',
        img_scale=[(1024, 1024)],
        h_flip=False,
        v_flip=False,
        rotate=False,
        transforms=[
            dict(type='Resize', keep_ratio=True),
            dict(type='OBBRandomFlip'),
            dict(type='Normalize', **img_norm_cfg),
            dict(type='RandomOBBRotate', rotate_after_flip=True),
            dict(type='Pad', size_divisor=32),
            dict(type='ImageToTensor', keys=['img']),
            dict(type='OBBCollect', keys=['img']),
        ])
]
data = dict(
    samples_per_gpu=2,
    workers_per_gpu=4,
    train=dict(pipeline=train_pipeline),
    val=dict(pipeline=test_pipeline),
    test=dict(pipeline=test_pipeline))
# optimizer
optimizer = dict(
    lr=0.0025, paramwise_cfg=dict(bias_lr_mult=2., bias_decay_mult=0.))
optimizer_config = dict(
    _delete_=True, grad_clip=dict(max_norm=35, norm_type=2))
# learning policy
lr_config = dict(
    policy='step',
    warmup='constant',
    warmup_iters=500,
    warmup_ratio=1.0 / 3,
    step=[8, 11])
total_epochs = 36
jbwang1997 commented 2 years ago

the num_classes in bbox_head should be 1 when using hrsc dataset.

geobao commented 2 years ago

This was it, thanks! I re-trained the model with the new config. The testing gives me this output:

+-------+------+-------+--------+--------+
| class | gts  | dets  | recall | ap     |
+-------+------+-------+--------+--------+
| ship  | 1188 | 44519 | 0.0000 | 0.0000 |
+-------+------+-------+--------+--------+
| mAP   |      |       |        | 0.0000 |
+-------+------+-------+--------+--------+

I used 36 epochs. I will try with more epochs, but I am not convinced it is that because the scores are not low but exactly 0.0000. I will let you know the result with more epochs

jbwang1997 commented 2 years ago

lr_config = dict( policy='step', warmup='constant', warmup_iters=500, warmup_ratio=1.0 / 3, step=[8, 11]) total_epochs = 36

It seems you only extend the total epochs to 36. The first and second steps to decay the lr should also be extended. 8 -> 24 11 -> 33

geobao commented 2 years ago

thanks, I will try that and let you know how it goes

geobao commented 2 years ago

This was the result. It makes more sense now. Thanks!

+-------+------+------+--------+--------+
| class | gts  | dets | recall | ap     |
+-------+------+------+--------+--------+
| ship  | 1188 | 9589 | 0.7727 | 0.6331 |
+-------+------+------+--------+--------+
| mAP   |      |      |        | 0.6331 |
+-------+------+------+--------+--------+
geobao commented 2 years ago

I would like to ask you. Is this implementation of FCOS the rotated version as in:

FCOSR: A Simple Anchor-free Rotated Detector for Aerial Object Detection https://arxiv.org/pdf/2111.10780.pdf

or is it rather the original FCOS for generic purpose (rotated or horizontal labeled objects).

Thanks

geobao commented 2 years ago

Answering my last question: No, it is not FCOSR. This is the original FCOS with the loss "PolyIoULoss" for obb