AutoMM Detection - Quick Start on a Tiny COCO Format Dataset

Open In Colab Open In SageMaker Studio Lab

In this section, our goal is to fast finetune a pretrained model on a small dataset in COCO format, and evaluate on its test set. Both training and test sets are in COCO format. See Convert Data to COCO Format for how to convert other datasets to COCO format.

Setting up the imports

To start, let’s import MultiModalPredictor:

Make sure mmcv and mmdet are installed:

from autogluon.multimodal import MultiModalPredictor

And also import some other packages that will be used in this tutorial:

import os
import time

from autogluon.core.utils.loaders import load_zip

Downloading Data

We have the sample dataset ready in the cloud. Let’s download it:

zip_file = "https://automl-mm-bench.s3.amazonaws.com/object_detection_dataset/tiny_motorbike_coco.zip"
download_dir = "./tiny_motorbike_coco"

load_zip.unzip(zip_file, unzip_dir=download_dir)
data_dir = os.path.join(download_dir, "tiny_motorbike")
train_path = os.path.join(data_dir, "Annotations", "trainval_cocoformat.json")
test_path = os.path.join(data_dir, "Annotations", "test_cocoformat.json")
Downloading ./tiny_motorbike_coco/file.zip from https://automl-mm-bench.s3.amazonaws.com/object_detection_dataset/tiny_motorbike_coco.zip...
100%|██████████| 21.8M/21.8M [00:00<00:00, 87.8MiB/s]

While using COCO format dataset, the input is the json annotation file of the dataset split. In this example, trainval_cocoformat.json is the annotation file of the train-and-validate split, and test_cocoformat.json is the annotation file of the test split.

Creating the MultiModalPredictor

We select the "medium_quality" presets, which uses a YOLOX-large model pretrained on COCO dataset. This preset is fast to finetune or inference, and easy to deploy. We also provide presets "high_quality" with a DINO-Resnet50 model and "best quality" with a DINO-SwinL model, with much higher performance but also slower and with higher GPU memory usage.

presets = "medium_quality"

We create the MultiModalPredictor with selected presets. We need to specify the problem_type to "object_detection", and also provide a sample_data_path for the predictor to infer the catgories of the dataset. Here we provide the train_path, and it also works using any other split of this dataset. And we also provide a path to save the predictor. It will be saved to a automatically generated directory with timestamp under AutogluonModels if path is not specified.

# Init predictor
import uuid

model_path = f"./tmp/{uuid.uuid4().hex}-quick_start_tutorial_temp_save"

predictor = MultiModalPredictor(
    problem_type="object_detection",
    sample_data_path=train_path,
    presets=presets,
    path=model_path,
)

Finetuning the Model

Learning rate, number of epochs, and batch_size are included in the presets, and thus no need to specify. Note that we use a two-stage learning rate option during finetuning by default, and the model head will have 100x learning rate. Using a two-stage learning rate with high learning rate only on head layers makes the model converge faster during finetuning. It usually gives better performance as well, especially on small datasets with hundreds or thousands of images. We also compute the time of the fit process here for better understanding the speed. We run it on a g4.2xlarge EC2 machine on AWS, and part of the command outputs are shown below:

start = time.time()
predictor.fit(train_path)  # Fit
train_end = time.time()
loading annotations into memory...
Done (t=0.00s)
creating index...
index created!
Downloading yolox_l_8x8_300e_coco_20211126_140236-d3bd2b23.pth from https://download.openmmlab.com/mmdetection/v2.0/yolox/yolox_l_8x8_300e_coco/yolox_l_8x8_300e_coco_20211126_140236-d3bd2b23.pth...
Loads checkpoint by local backend from path: yolox_l_8x8_300e_coco_20211126_140236-d3bd2b23.pth
The model and loaded state dict do not match exactly

size mismatch for bbox_head.multi_level_conv_cls.0.weight: copying a param with shape torch.Size([80, 256, 1, 1]) from checkpoint, the shape in current model is torch.Size([10, 256, 1, 1]).
size mismatch for bbox_head.multi_level_conv_cls.0.bias: copying a param with shape torch.Size([80]) from checkpoint, the shape in current model is torch.Size([10]).
size mismatch for bbox_head.multi_level_conv_cls.1.weight: copying a param with shape torch.Size([80, 256, 1, 1]) from checkpoint, the shape in current model is torch.Size([10, 256, 1, 1]).
size mismatch for bbox_head.multi_level_conv_cls.1.bias: copying a param with shape torch.Size([80]) from checkpoint, the shape in current model is torch.Size([10]).
size mismatch for bbox_head.multi_level_conv_cls.2.weight: copying a param with shape torch.Size([80, 256, 1, 1]) from checkpoint, the shape in current model is torch.Size([10, 256, 1, 1]).
size mismatch for bbox_head.multi_level_conv_cls.2.bias: copying a param with shape torch.Size([80]) from checkpoint, the shape in current model is torch.Size([10]).
=================== System Info ===================
AutoGluon Version:  1.1.1b20240716
Python Version:     3.10.13
Operating System:   Linux
Platform Machine:   x86_64
Platform Version:   #1 SMP Fri May 17 18:07:48 UTC 2024
CPU Count:          8
Pytorch Version:    2.3.1+cu121
CUDA Version:       12.1
Memory Avail:       28.67 GB / 30.95 GB (92.7%)
Disk Space Avail:   WARNING, an exception (FileNotFoundError) occurred while attempting to get available disk space. Consider opening a GitHub Issue.
===================================================
Using default root folder: ./tiny_motorbike_coco/tiny_motorbike/Annotations/... Specify `root=...` if you feel it is wrong...

AutoMM starts to create your model. ✨✨✨

To track the learning progress, you can open a terminal and launch Tensorboard:
    ```shell
    # Assume you have installed tensorboard
    tensorboard --logdir /home/ci/autogluon/docs/tutorials/multimodal/object_detection/quick_start/tmp/448f4193da6b40bcb3aee3f621cad3af-quick_start_tutorial_temp_save
    ```

Seed set to 0
GPU Count: 1
GPU Count to be Used: 1
GPU 0 Name: Tesla T4
GPU 0 Memory: 0.42GB/15.0GB (Used/Total)

Using 16bit Automatic Mixed Precision (AMP)
GPU available: True (cuda), used: True
TPU available: False, using: 0 TPU cores
HPU available: False, using: 0 HPUs
`Trainer(val_check_interval=1.0)` was configured so validation will run at the end of the training epoch..
LOCAL_RANK: 0 - CUDA_VISIBLE_DEVICES: [0]

  | Name              | Type                             | Params | Mode 
-------------------------------------------------------------------------------
0 | model             | MMDetAutoModelForObjectDetection | 54.2 M | train
1 | validation_metric | MeanAveragePrecision             | 0      | train
-------------------------------------------------------------------------------
54.2 M    Trainable params
0         Non-trainable params
54.2 M    Total params
216.620   Total estimated model params size (MB)
/home/ci/opt/venv/lib/python3.10/site-packages/torch/functional.py:512: UserWarning: torch.meshgrid: in an upcoming release, it will be required to pass the indexing argument. (Triggered internally at ../aten/src/ATen/native/TensorShape.cpp:3587.)
  return _VF.meshgrid(tensors, **kwargs)  # type: ignore[attr-defined]
Epoch 2, global step 15: 'val_map' reached 0.33796 (best 0.33796), saving model to '/home/ci/autogluon/docs/tutorials/multimodal/object_detection/quick_start/tmp/448f4193da6b40bcb3aee3f621cad3af-quick_start_tutorial_temp_save/epoch=2-step=15.ckpt' as top 1
Epoch 5, global step 30: 'val_map' was not in top 1
Epoch 8, global step 45: 'val_map' reached 0.38069 (best 0.38069), saving model to '/home/ci/autogluon/docs/tutorials/multimodal/object_detection/quick_start/tmp/448f4193da6b40bcb3aee3f621cad3af-quick_start_tutorial_temp_save/epoch=8-step=45.ckpt' as top 1
Epoch 11, global step 60: 'val_map' reached 0.41595 (best 0.41595), saving model to '/home/ci/autogluon/docs/tutorials/multimodal/object_detection/quick_start/tmp/448f4193da6b40bcb3aee3f621cad3af-quick_start_tutorial_temp_save/epoch=11-step=60.ckpt' as top 1
Epoch 14, global step 75: 'val_map' reached 0.45463 (best 0.45463), saving model to '/home/ci/autogluon/docs/tutorials/multimodal/object_detection/quick_start/tmp/448f4193da6b40bcb3aee3f621cad3af-quick_start_tutorial_temp_save/epoch=14-step=75.ckpt' as top 1
Epoch 17, global step 90: 'val_map' was not in top 1
Epoch 20, global step 105: 'val_map' was not in top 1
Epoch 23, global step 120: 'val_map' reached 0.46099 (best 0.46099), saving model to '/home/ci/autogluon/docs/tutorials/multimodal/object_detection/quick_start/tmp/448f4193da6b40bcb3aee3f621cad3af-quick_start_tutorial_temp_save/epoch=23-step=120.ckpt' as top 1
Epoch 26, global step 135: 'val_map' reached 0.47348 (best 0.47348), saving model to '/home/ci/autogluon/docs/tutorials/multimodal/object_detection/quick_start/tmp/448f4193da6b40bcb3aee3f621cad3af-quick_start_tutorial_temp_save/epoch=26-step=135.ckpt' as top 1
Epoch 29, global step 150: 'val_map' was not in top 1
Epoch 32, global step 165: 'val_map' was not in top 1
Epoch 35, global step 180: 'val_map' was not in top 1
Epoch 38, global step 195: 'val_map' was not in top 1
Epoch 41, global step 210: 'val_map' was not in top 1
AutoMM has created your model. 🎉🎉🎉

To load the model, use the code below:
    ```python
    from autogluon.multimodal import MultiModalPredictor
    predictor = MultiModalPredictor.load("/home/ci/autogluon/docs/tutorials/multimodal/object_detection/quick_start/tmp/448f4193da6b40bcb3aee3f621cad3af-quick_start_tutorial_temp_save")
    ```

If you are not satisfied with the model, try to increase the training time, 
adjust the hyperparameters (https://auto.gluon.ai/stable/tutorials/multimodal/advanced_topics/customization.html),
or post issues on GitHub (https://github.com/autogluon/autogluon/issues).

Notice that at the end of each progress bar, if the checkpoint at current stage is saved, it prints the model’s save path. In this example, it’s ./quick_start_tutorial_temp_save.

Print out the time and we can see that it’s fast!

print("This finetuning takes %.2f seconds." % (train_end - start))
This finetuning takes 451.85 seconds.

Evaluation

To evaluate the model we just trained, run following code.

And the evaluation results are shown in command line output. The first line is mAP in COCO standard, and the second line is mAP in VOC standard (or mAP50). For more details about these metrics, see COCO’s evaluation guideline. Note that for presenting a fast finetuning we use presets “medium_quality”, you could get better result on this dataset by simply using “high_quality” or “best_quality” presets, or customize your own model and hyperparameter settings: Customization, and some other examples at Fast Fine-tune Coco or High Performance Fine-tune Coco.

predictor.evaluate(test_path)
eval_end = time.time()
loading annotations into memory...
Done (t=0.00s)
creating index...
index created!
saving file at /home/ci/autogluon/docs/tutorials/multimodal/object_detection/quick_start/AutogluonModels/ag-20240716_225201/object_detection_result_cache.json
loading annotations into memory...
Done (t=0.00s)
creating index...
index created!
Loading and preparing results...
DONE (t=0.00s)
creating index...
index created!
Running per image evaluation...
Evaluate annotation type *bbox*
DONE (t=0.09s).
Accumulating evaluation results...
DONE (t=0.04s).
 Average Precision  (AP) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.364
 Average Precision  (AP) @[ IoU=0.50      | area=   all | maxDets=100 ] = 0.525
 Average Precision  (AP) @[ IoU=0.75      | area=   all | maxDets=100 ] = 0.392
 Average Precision  (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.222
 Average Precision  (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.446
 Average Precision  (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.755
 Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=  1 ] = 0.249
 Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets= 10 ] = 0.413
 Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.420
 Average Recall     (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.364
 Average Recall     (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.484
 Average Recall     (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.799
Using default root folder: ./tiny_motorbike_coco/tiny_motorbike/Annotations/... Specify `root=...` if you feel it is wrong...
A new predictor save path is created. This is to prevent you to overwrite previous predictor saved here. You could check current save path at predictor._save_path. If you still want to use this path, set resume=True
No path specified. Models will be saved in: "AutogluonModels/ag-20240716_225201"

Print out the evaluation time:

print("The evaluation takes %.2f seconds." % (eval_end - train_end))
The evaluation takes 1.83 seconds.

We can load a new predictor with previous save_path, and we can also reset the number of GPUs to use if not all the devices are available:

# Load and reset num_gpus
new_predictor = MultiModalPredictor.load(model_path)
new_predictor.set_num_gpus(1)
Load pretrained checkpoint: /home/ci/autogluon/docs/tutorials/multimodal/object_detection/quick_start/tmp/448f4193da6b40bcb3aee3f621cad3af-quick_start_tutorial_temp_save/model.ckpt

Evaluating the new predictor gives us exactly the same result:

# Evaluate new predictor
new_predictor.evaluate(test_path)
loading annotations into memory...
Done (t=0.00s)
creating index...
index created!
saving file at /home/ci/autogluon/docs/tutorials/multimodal/object_detection/quick_start/AutogluonModels/ag-20240716_225205/object_detection_result_cache.json
loading annotations into memory...
Done (t=0.00s)
creating index...
index created!
Loading and preparing results...
DONE (t=0.00s)
creating index...
index created!
Running per image evaluation...
Evaluate annotation type *bbox*
DONE (t=0.09s).
Accumulating evaluation results...
DONE (t=0.04s).
 Average Precision  (AP) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.364
 Average Precision  (AP) @[ IoU=0.50      | area=   all | maxDets=100 ] = 0.525
 Average Precision  (AP) @[ IoU=0.75      | area=   all | maxDets=100 ] = 0.392
 Average Precision  (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.222
 Average Precision  (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.446
 Average Precision  (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.755
 Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=  1 ] = 0.249
 Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets= 10 ] = 0.413
 Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.420
 Average Recall     (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.364
 Average Recall     (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.484
 Average Recall     (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.799
Using default root folder: ./tiny_motorbike_coco/tiny_motorbike/Annotations/... Specify `root=...` if you feel it is wrong...
A new predictor save path is created. This is to prevent you to overwrite previous predictor saved here. You could check current save path at predictor._save_path. If you still want to use this path, set resume=True
No path specified. Models will be saved in: "AutogluonModels/ag-20240716_225205"
{'map': 0.3641261275188341,
 'mean_average_precision': 0.3641261275188341,
 'map_50': 0.5249143462047373,
 'map_75': 0.39209779597082756,
 'map_small': 0.2221366354228851,
 'map_medium': 0.4459716681084122,
 'map_large': 0.7547044943494515,
 'mar_1': 0.24885365280714114,
 'mar_10': 0.4130082217524078,
 'mar_100': 0.420041813483674,
 'mar_small': 0.36375,
 'mar_medium': 0.48365079365079366,
 'mar_large': 0.7991632928475033}

For how to set the hyperparameters and finetune the model with higher performance, see AutoMM Detection - High Performance Finetune on COCO Format Dataset.

Inference

Now that we have gone through the model setup, finetuning, and evaluation, this section details the inference. Specifically, we layout the steps for using the model to make predictions and visualize the results.

To run inference on the entire test set, perform:

pred = predictor.predict(test_path)
print(pred)
loading annotations into memory...
Done (t=0.00s)
creating index...
index created!
                                                image  \
0   ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
1   ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
2   ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
3   ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
4   ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
5   ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
6   ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
7   ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
8   ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
9   ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
10  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
11  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
12  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
13  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
14  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
15  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
16  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
17  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
18  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
19  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
20  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
21  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
22  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
23  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
24  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
25  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
26  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
27  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
28  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
29  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
30  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
31  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
32  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
33  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
34  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
35  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
36  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
37  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
38  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
39  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
40  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
41  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
42  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
43  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
44  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
45  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
46  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
47  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
48  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   
49  ./tiny_motorbike_coco/tiny_motorbike/Annotatio...   

                                               bboxes  
0   [{'class': 'bicycle', 'class_id': 0, 'bbox': [...  
1   [{'class': 'person', 'class_id': 8, 'bbox': [1...  
2   [{'class': 'person', 'class_id': 8, 'bbox': [1...  
3   [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
4   [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
5   [{'class': 'person', 'class_id': 8, 'bbox': [2...  
6   [{'class': 'person', 'class_id': 8, 'bbox': [7...  
7   [{'class': 'pottedplant', 'class_id': 9, 'bbox...  
8   [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
9   [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
10  [{'class': 'person', 'class_id': 8, 'bbox': [8...  
11  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
12  [{'class': 'person', 'class_id': 8, 'bbox': [1...  
13  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
14  [{'class': 'person', 'class_id': 8, 'bbox': [2...  
15  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
16  [{'class': 'person', 'class_id': 8, 'bbox': [2...  
17  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
18  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
19  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
20  [{'class': 'person', 'class_id': 8, 'bbox': [0...  
21  [{'class': 'person', 'class_id': 8, 'bbox': [4...  
22  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
23  [{'class': 'person', 'class_id': 8, 'bbox': [4...  
24  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
25  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
26  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
27  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
28  [{'class': 'person', 'class_id': 8, 'bbox': [1...  
29  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
30  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
31  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
32  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
33  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
34  [{'class': 'person', 'class_id': 8, 'bbox': [-...  
35  [{'class': 'car', 'class_id': 3, 'bbox': [378....  
36  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
37  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
38  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
39  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
40  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
41  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
42  [{'class': 'person', 'class_id': 8, 'bbox': [1...  
43  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
44  [{'class': 'person', 'class_id': 8, 'bbox': [2...  
45  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
46  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
47  [{'class': 'person', 'class_id': 8, 'bbox': [1...  
48  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
49  [{'class': 'motorbike', 'class_id': 7, 'bbox':...  
Using default root folder: ./tiny_motorbike_coco/tiny_motorbike/Annotations/... Specify `root=...` if you feel it is wrong...

The output pred is a pandas DataFrame that has two columns, image and bboxes.

In image, each row contains the image path

In bboxes, each row is a list of dictionaries, each one representing a bounding box: {"class": <predicted_class_name>, "bbox": [x1, y1, x2, y2], "score": <confidence_score>}

Note that, by default, the predictor.predict does not save the detection results into a file.

To run inference and save results, run the following:

pred = predictor.predict(test_path, save_results=True)
loading annotations into memory...
Done (t=0.00s)
creating index...
index created!
Using default root folder: ./tiny_motorbike_coco/tiny_motorbike/Annotations/... Specify `root=...` if you feel it is wrong...
A new predictor save path is created. This is to prevent you to overwrite previous predictor saved here. You could check current save path at predictor._save_path. If you still want to use this path, set resume=True
No path specified. Models will be saved in: "AutogluonModels/ag-20240716_225208"
Saved detection results to /home/ci/autogluon/docs/tutorials/multimodal/object_detection/quick_start/AutogluonModels/ag-20240716_225208/result.txt

Here, we save pred into a .txt file, which exactly follows the same layout as in pred. You can use a predictor initialized in any way (i.e. finetuned predictor, predictor with pretrained model, etc.).

Visualizing Results

To run visualizations, ensure that you have opencv installed. If you haven’t already, install opencv by running

!pip install opencv-python
Requirement already satisfied: opencv-python in /home/ci/opt/venv/lib/python3.10/site-packages (4.10.0.84)
Requirement already satisfied: numpy>=1.21.2 in /home/ci/opt/venv/lib/python3.10/site-packages (from opencv-python) (1.26.4)

To visualize the detection bounding boxes, run the following:

from autogluon.multimodal.utils import ObjectDetectionVisualizer

conf_threshold = 0.4  # Specify a confidence threshold to filter out unwanted boxes
image_result = pred.iloc[30]

img_path = image_result.image  # Select an image to visualize

visualizer = ObjectDetectionVisualizer(img_path)  # Initialize the Visualizer
out = visualizer.draw_instance_predictions(image_result, conf_threshold=conf_threshold)  # Draw detections
visualized = out.get_image()  # Get the visualized image

from PIL import Image
from IPython.display import display
img = Image.fromarray(visualized, 'RGB')
display(img)
../../../../_images/609674d3cf19f00ec001fbb3bfb337fbe8ae03eab928da8c1f71f3279188bd9d.png

Testing on Your Own Data

You can also predict on your own images with various input format. The follow is an example:

Download the example image:

from autogluon.multimodal import download
image_url = "https://raw.githubusercontent.com/dmlc/web-data/master/gluoncv/detection/street_small.jpg"
test_image = download(image_url)
Downloading street_small.jpg from https://raw.githubusercontent.com/dmlc/web-data/master/gluoncv/detection/street_small.jpg...
                                           

Run inference on data in a json file of COCO format (See Convert Data to COCO Format for more details about COCO format). Note that since the root is by default the parent folder of the annotation file, here we put the annotation file in a folder:

import json

# create a input file for demo
data = {"images": [{"id": 0, "width": -1, "height": -1, "file_name": test_image}], "categories": []}
os.mkdir("input_data_for_demo")
input_file = "input_data_for_demo/demo_annotation.json"
with open(input_file, "w+") as f:
    json.dump(data, f)

pred_test_image = predictor.predict(input_file)
print(pred_test_image)
loading annotations into memory...
Done (t=0.00s)
creating index...
index created!
                                     image  \
0  input_data_for_demo/../street_small.jpg   

                                              bboxes  
0  [{'class': 'person', 'class_id': 8, 'bbox': [2...  
Using default root folder: input_data_for_demo/... Specify `root=...` if you feel it is wrong...

Run inference on data in a list of image file names:

pred_test_image = predictor.predict([test_image])
print(pred_test_image)
              image                                             bboxes
0  street_small.jpg  [{'class': 'person', 'class_id': 8, 'bbox': [2...

Other Examples

You may go to AutoMM Examples to explore other examples about AutoMM.

Customization

To learn how to customize AutoMM, please refer to Customize AutoMM.

Citation

@article{DBLP:journals/corr/abs-2107-08430,
  author    = {Zheng Ge and
               Songtao Liu and
               Feng Wang and
               Zeming Li and
               Jian Sun},
  title     = {{YOLOX:} Exceeding {YOLO} Series in 2021},
  journal   = {CoRR},
  volume    = {abs/2107.08430},
  year      = {2021},
  url       = {https://arxiv.org/abs/2107.08430},
  eprinttype = {arXiv},
  eprint    = {2107.08430},
  timestamp = {Tue, 05 Apr 2022 14:09:44 +0200},
  biburl    = {https://dblp.org/rec/journals/corr/abs-2107-08430.bib},
  bibsource = {dblp computer science bibliography, https://dblp.org},
}