- Here,
AMODrefers to our large-scale synthetic dataset, Aerial Military Object Detection (RGB-T, Multi-view)! - Categories of AMOD: Armored, Artillery, Helicopter, LCU, MLRS, Plane, RADAR, SAM, Self-propelled Artillery, Support, Tank, TEL.
- The dataset structure is as follows:
|ββ π train
|ββ π train_imgs
|ββ π 0000 // scenario number
|ββ πΌοΈ EO_0000_0.png // image at look angle 0 for scenario "0000"
|ββ πΌοΈ EO_0000_10.png
...
|ββ πΌοΈ EO_0000_50.png
|ββ ...
|ββ π train_labels
|ββ π ANNOTATION-EO_0000_0.csv // annotation file for "EO_0000_0.png"
|ββ π ANNOTATION-EO_0000_10.csv
...
|ββ π test
|ββ π test_imgs
|ββ π test_labels
|ββ π train.txt // scenario number list for train split
|ββ π val.txt // scenario number list for validation split
|ββ π test.txt // scenario number list for test split
- Training & test code for AMOD!
Note
Please note that our deep learning code is developed and tested on Linux. Windows is not officially supported.
Install Docker? (Ubuntu)
-
(Optional) Itβs best to remove any previously installed versions of Docker before starting.
sudo apt-get remove docker docker-engine docker.io containerd runc
-
(Step 0-A) Add Dockerβs official GPG key and set up the repository.
sudo apt-get update sudo apt-get install -y ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
-
(Step 0-B) Install Docker Engine.
sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
-
(Step 0-B-Optional) Verify Installation: If you see the message Hello from Docker!, Docker has been installed successfully.
sudo docker run hello-world
-
(Step 0-C) Set up the NVIDIA Container Toolkit repository and install the NVIDIA Container Toolkit.
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \ && curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \ sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \ sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list sudo apt-get update sudo apt-get install -y nvidia-container-toolkit sudo systemctl restart docker
-
(Step 0-C-Optional) Verify Installation: If you see the message from NVIDIA-SMI, everything is fine!
sudo docker run --rm --gpus all nvidia/cuda:11.8.0-base-ubuntu22.04 nvidia-smi
-
(Optional) Use Docker without sudo βοΈNote: Be sure to restart your terminal session or reboot your system after executing the command so that the changes are applied.
sudo usermod -aG docker $USER
-
Step 1. To get started, pull our Docker image.
docker pull uniquechan/my-amod-app:v1
If you want to build the Docker image by yourself?
-
Execute the command below in the
AMODdirectory.docker build -t my-amod-app:v1 .
To test the Docker image, please execute the command below.
-
If you encounter the message including CUDA 11.7.1, it means you are ready to play with AMOD.
docker run -it --rm --gpus all -v $(pwd):/workspace my-amod-app:v1
-
-
Step 2. Enjoy our code with Docker! We highly recommend that you use
-v(volume mount) to connect your local environment with the Docker container. The below is an example:docker run -it --rm --gpus all \ -v $(pwd):/workspace \ -v $("YOUR_DATASET_FOLDER"):/dataset \ my-amod-app:v1
-
Step 1. Create a conda environment with Python 3.8 and activate it.
conda create --name amodexpkit python=3.8 -y conda activate amodexpkit
-
Step 2. Install PyTorch with TorchVision following official instructions. The below is an example. We do not recommend PyTorch 2.x for our code.
pip install torch==1.10.2+cu113 torchvision==0.11.3+cu113 -f https://download.pytorch.org/whl/torch_stable.html
-
Step 3. Install
MMDetection (v2.28.2)(v2.28.2 is the latest version suited to MMRotate of 2024).# β οΈ No need to clone MMDet (e.g. "git clone -b 2.x https://github.com/open-mmlab/mmdetection; rm -rf mmdetection/.git"). Already cloned! pip install -U openmim==0.3.9 mim install mmcv-full==1.7.2 pip install -v -e mmdetection/ -
Step 4. Install
MMRotate (v0.3.4)(v0.3.4 is the latest version of 2024).# β οΈ No need to clone MMRot (e.g. "git clone https://github.com/open-mmlab/mmrotate; rm -rf mmrotate/.git"). Already cloned! pip install -v -e mmrotate/To verify whether MMRotate is installed correctly, you may try the following things:
- Download config and checkpoint files.
mim download mmrotate --config oriented_rcnn_r50_fpn_1x_dota_le90 --dest . - Verify the inference demo.
python mmrotate/demo/image_demo.py \ mmrotate/demo/demo.jpg oriented_rcnn_r50_fpn_1x_dota_le90.py \ oriented_rcnn_r50_fpn_1x_dota_le90-6d2b2ce0.pth --out-file result.jpg
- If result.jpg is generated correctly, it means that the environment is set up properly.
- Download config and checkpoint files.
-
Step 5. Install
Tensorboardfor visualizing learning curves.pip install tensorboard==2.9.1 # If AttributeError: module 'setuptools._distutils' has no attribute 'version' -> pip install setuptools==59.5.0
You can use the following commands to infer a dataset.
# Single-gpu
python mmrotate/tools/test.py ${CONFIG_FILE} ${CHECKPOINT_FILE} [optional arguments]
# Multi-gpu
./mmrotate/tools/dist_test.sh ${CONFIG_FILE} ${CHECKPOINT_FILE} ${GPU_NUM} [optional arguments]Examples:
-
Test OrientedRCNN with Swin-S pretrained on AMOD
- Run the following command to get AP50, AP75 of test split of AMOD:
python mmrotate/tools/test.py my_config/orientedrcnn_swinS_fpn_angle0,10,20,30,40,50_30epochs_le90_amod.py \ [path/to/pretrained_weights/*.pth] --eval mAP --eval-options iou_thr=0.5,0.75 -
If you want to change the data root path through Python arguments?
DATA_ROOT="data/AMOD_MOCK/" python mmrotate/tools/test.py my_config/orientedrcnn_swinS_fpn_angle0,10,20,30,40,50_30epochs_le90_amod.py \ [path/to/pretrained_weights/*.pth] --cfg-options data.test.data_root="$DATA_ROOT" --eval mAP \ --eval-options iou_thr=0.5,0.75
-
If you want to get a confusion matrix?
- You have to save the prediction results as a
.pklfile using--outintest.py.
DATA_ROOT="data/AMOD_MOCK/" python mmrotate/tools/test.py my_config/orientedrcnn_swinS_fpn_angle0,10,20,30,40,50_30epochs_le90_amod.py \ [path/to/pretrained_weights/*.pth] --cfg-options data.test.data_root="$DATA_ROOT" --eval mAP \ --eval-options iou_thr=0.5 --out "./test.pkl"
- Then, run the following code:
DATA_ROOT="data/AMOD_MOCK/" mkdir ./confusion_matrix_results python mmrotate/tools/analysis_tools/confusion_matrix.py \ my_config/orientedrcnn_swinS_fpn_angle0,10,20,30,40,50_30epochs_le90_amod.py \ ./test.pkl \ ./confusion_matrix_results --color-theme 'viridis' --show \ --tp-iou-thr 0.5 \ --cfg-options data.test.data_root="$DATA_ROOT"
- You have to save the prediction results as a
You can use the following commands to train a model from the dataset.
# Single-gpu
python mmrotate/tools/train.py ${CONFIG_FILE} [optional arguments]
# Multi-gpu
./mmrotate/tools/dist_train.sh ${CONFIG_FILE} ${GPU_NUM} [optional arguments]Optional arguments are:
--no-validate(not recommended): No validation (evaluation) during the training.--work-dir ${WORK_DIR}: Override the working directory specified in the config file.--resume-from ${CHECKPOINT_FILE}: Resume from a previous checkpoint file.- Difference between resume-from and load-from: resume-from loads both the model weights and optimizer status, and the epoch is also inherited from the specified checkpoint. It is usually used for resuming the training process that is interrupted accidentally. load-from only loads the model weights and the training epoch starts from 0. It is usually used for finetuning.
Launch multiple jobs on a single machine: If you launch multiple jobs on a single machine, e.g., 2 jobs of 4-GPU training on a machine with 8 GPUs, you need to specify different ports (29500 by default) for each job to avoid communication conflict.
CUDA_VISIBLE_DEVICES=0,1,2,3 PORT=29500 ./mmrotate/tools/dist_train.sh ${CONFIG_FILE} 4 [optional arguments]
CUDA_VISIBLE_DEVICES=4,5,6,7 PORT=29501 ./mmrotate/tools/dist_train.sh ${CONFIG_FILE} 4 [optional arguments]Examples:
-
Train OrientedRCNN with Swin-S on train set of AMOD.
-
Tip1: Please read carefully both
PreferredandBadexamples! (π¨) -
Tip2: You may use
--cfg-optionsto instantly and temporally modify the config file. (Do not over-use)! -
Preferred example (π):
- If you want to train three models with look angles [0,10], [10,20], [50] respectively, on AMOD for 1 epoch with batch size 1?
- Solution:
-
- Copy the file
orientedrcnn_swinS_fpn_angle0,10,20,30,40,50_30epochs_le90_amod.pylocated in the my_config directory three times.
- Copy the file
-
- Rename each file as follows:
orientedrcnn_swinS_fpn_angle0,10_1epoch_le90_amod.pyorientedrcnn_swinS_fpn_angle10,20_1epoch_le90_amod.pyorientedrcnn_swinS_fpn_angle50_1epoch_le90_amod.py
-
- Properly modify variables
angles(line 3) andrunner.max_epochs(line 19) in each file.
- Properly modify variables
-
- Finally, run the below shell code:
-
DATA_ROOT="/media/yechani9/T7\Shield/AMOD_V1_FINAL_OPTICAL/" # AMOD DATA ROOT PATH!!! python mmrotate/tools/train.py my_config/orientedrcnn_swinS_fpn_angle0,10_1epoch_le90_amod.py \ --cfg-options data.train.data_root="$DATA_ROOT" data.val.data_root="$DATA_ROOT" \ data.samples_per_gpu=1 python mmrotate/tools/train.py my_config/orientedrcnn_swinS_fpn_angle10,20_1epoch_le90_amod.py \ --cfg-options data.train.data_root="$DATA_ROOT" data.val.data_root="$DATA_ROOT" \ data.samples_per_gpu=1 python mmrotate/tools/train.py my_config/orientedrcnn_swinS_fpn_angle50_1epoch_le90_amod.py \ --cfg-options data.train.data_root="$DATA_ROOT" data.val.data_root="$DATA_ROOT" \ data.samples_per_gpu=1
- Tip: You can remove
DATA_ROOTand--cfg-options ...in the above shell code if you also properly modify variablesdata_root(in line 4) anddata.samples_per_gpu(in line 79) in each config file.
-
Another example:
- If you want to train three models with look angles [0,10], [10,20], [50] respectively, on AMOD for 1 epoch? The below is a bad example!
DATA_ROOT="/media/yechani9/T7\Shield/AMOD_V1_FINAL_OPTICAL/" ANGLES="0,10" python mmrotate/tools/train.py my_config/orientedrcnn_swinS_fpn_angle0,10,20,30,40,50_30epochs_le90_amod.py \ --cfg-options data.train.data_root="$DATA_ROOT" data.val.data_root="$DATA_ROOT" \ data.train.angles="$ANGLES" data.val.angles="$ANGLES" \ runner.max_epochs=1 data.samples_per_gpu=1 # ... almost same shell code be here for look angles [10,20] # ... almost same shell code be here for look angle [50]
-
Reason: Using
--cfg-optionsdynamically with the same config file while keeping the same working directory can lead to serious issues, such as experiment results being overwritten and difficulties in tracking which modifications were applied to each experiment. This becomes especially problematic when modifying crucial parameters likeANGLES, as it makes it nearly impossible to trace back the exact configurations that led to specific results. -
Solution: You have to separate
--work-dir(working directories) per each experiment.
DATA_ROOT="/media/yechani9/T7\Shield/AMOD_V1_FINAL_OPTICAL/" ANGLES="0,10" python mmrotate/tools/train.py my_config/orientedrcnn_swinS_fpn_angle0,10,20,30,40,50_30epochs_le90_amod.py \ --cfg-options data.train.data_root="$DATA_ROOT" data.val.data_root="$DATA_ROOT" \ data.train.angles="$ANGLES" data.val.angles="$ANGLES" \ runner.max_epochs=1 data.samples_per_gpu=1 --work-dir work_dirs/orientedrcnn_swinS_fpn$ANGLES # ... almost same shell code be here for look angles [10,20] # ... almost same shell code be here for look angle [50]
or use more advanced shell script (with
foriteration) like:DATA_ROOT="/media/yechani9/T7\Shield/AMOD_V1_FINAL_OPTICAL/" for ANGLES in 0,10 10,20 50; do python mmrotate/tools/train.py my_config/orientedrcnn_swinS_fpn_angle0,10,20,30,40,50_30epochs_le90_amod.py \ --cfg-options data.train.data_root="$DATA_ROOT" data.val.data_root="$DATA_ROOT" \ data.train.angles="$ANGLES" data.val.angles="$ANGLES" \ runner.max_epochs=1 data.samples_per_gpu=1 --work-dir work_dirs/orientedrcnn_swinS_fpn$ANGLES done
Still, we recommend following the previous good example!
-