├── LICENSE ├── NOTICE ├── README.md ├── data └── .gitignore ├── exp └── .gitignore ├── experiments ├── ctdet_coco_dla_1x.sh ├── ctdet_coco_dla_2x.sh ├── ctdet_coco_hg.sh ├── ctdet_coco_resdcn101.sh ├── ctdet_coco_resdcn18.sh ├── ctdet_pascal_dla_384.sh ├── ctdet_pascal_dla_512.sh ├── ctdet_pascal_resdcn101_384.sh ├── ctdet_pascal_resdcn101_512.sh ├── ctdet_pascal_resdcn18_384.sh ├── ctdet_pascal_resdcn18_512.sh ├── ddd_3dop.sh ├── ddd_sub.sh ├── exdet_coco_dla.sh ├── exdet_coco_hg.sh ├── multi_pose_dla_1x.sh ├── multi_pose_dla_3x.sh ├── multi_pose_hg_1x.sh └── multi_pose_hg_3x.sh ├── images ├── 16004479832_a748d55f21_k.jpg ├── 17790319373_bd19b24cfc_k.jpg ├── 18124840932_e42b3e377c_k.jpg ├── 19064748793_bb942deea1_k.jpg ├── 24274813513_0cfd2ce6d0_k.jpg ├── 33823288584_1d21cf0a26_k.jpg ├── 33887522274_eebd074106_k.jpg ├── 34501842524_3c858b3080_k.jpg └── NOTICE ├── models └── .gitignore ├── ncnn ├── CMakeLists.txt ├── README.md ├── __pycache__ │ └── mobilenetv2.cpython-36.pyc ├── bspline.txt ├── build │ ├── CMakeCache.txt │ ├── CMakeFiles │ │ ├── 3.10.2 │ │ │ ├── CMakeCCompiler.cmake │ │ │ ├── CMakeCXXCompiler.cmake │ │ │ ├── CMakeDetermineCompilerABI_C.bin │ │ │ ├── CMakeDetermineCompilerABI_CXX.bin │ │ │ ├── CMakeSystem.cmake │ │ │ ├── CompilerIdC │ │ │ │ ├── CMakeCCompilerId.c │ │ │ │ └── a.out │ │ │ └── CompilerIdCXX │ │ │ │ ├── CMakeCXXCompilerId.cpp │ │ │ │ └── a.out │ │ ├── CMakeDirectoryInformation.cmake │ │ ├── CMakeOutput.log │ │ ├── Makefile.cmake │ │ ├── Makefile2 │ │ ├── TargetDirectories.txt │ │ ├── cmake.check_cache │ │ ├── demo.dir │ │ │ ├── CXX.includecache │ │ │ ├── DependInfo.cmake │ │ │ ├── build.make │ │ │ ├── cmake_clean.cmake │ │ │ ├── cpp │ │ │ │ └── ncnn_centernet.cpp.o │ │ │ ├── demo.cpp.o │ │ │ ├── depend.internal │ │ │ ├── depend.make │ │ │ ├── flags.make │ │ │ ├── link.txt │ │ │ └── progress.make │ │ ├── feature_tests.bin │ │ ├── feature_tests.c │ │ ├── feature_tests.cxx │ │ └── progress.marks │ ├── Makefile │ ├── cmake_install.cmake │ └── demo ├── cpp │ ├── ncnn_centernet.cpp │ └── ncnn_centernet.h ├── demo.cpp ├── dog.jpg ├── faceimg │ ├── 1.jpg │ ├── 2.jpg │ ├── 3.jpg │ ├── 4.jpg │ └── 5.jpg ├── include │ ├── allocator.h │ ├── benchmark.h │ ├── blob.h │ ├── command.h │ ├── cpu.h │ ├── gpu.h │ ├── layer.h │ ├── layer_type.h │ ├── layer_type_enum.h │ ├── mat.h │ ├── modelbin.h │ ├── net.h │ ├── opencv.h │ ├── option.h │ ├── paramdict.h │ ├── pipeline.h │ └── platform.h ├── lib │ └── libncnn.a ├── mobilenetv2.py ├── model.py ├── models │ ├── bus_face │ │ ├── centernet_mbv2.bin │ │ ├── centernet_mbv2.param │ │ ├── res18.bin │ │ └── res18.param │ └── voc │ │ ├── centernet_mbv2.bin │ │ └── centernet_mbv2.param ├── plane.jpg ├── plate │ ├── centernet_mbv2.bin │ ├── centernet_mbv2.onnx │ ├── centernet_mbv2.param │ └── model_best.pth ├── result.jpg └── voc.txt ├── readme ├── DATA.md ├── DEVELOP.md ├── GETTING_STARTED.md ├── INSTALL.md ├── MODEL_ZOO.md ├── det1.png ├── det2.png ├── fig2.png ├── pose1.png ├── pose2.png └── pose3.png ├── requirements.txt └── src ├── __pycache__ └── _init_paths.cpython-36.pyc ├── _init_paths.py ├── _init_paths.pyc ├── demo.py ├── lib ├── __pycache__ │ ├── logger.cpython-36.pyc │ └── opts.cpython-36.pyc ├── datasets │ ├── __pycache__ │ │ └── dataset_factory.cpython-36.pyc │ ├── dataset │ │ ├── __pycache__ │ │ │ ├── coco.cpython-36.pyc │ │ │ ├── coco_hp.cpython-36.pyc │ │ │ ├── face.cpython-36.pyc │ │ │ ├── kitti.cpython-36.pyc │ │ │ └── pascal.cpython-36.pyc │ │ ├── coco.py │ │ ├── coco_hp.py │ │ ├── face.py │ │ ├── kitti.py │ │ └── pascal.py │ ├── dataset_factory.py │ └── sample │ │ ├── __pycache__ │ │ ├── ctdet.cpython-36.pyc │ │ ├── ddd.cpython-36.pyc │ │ ├── exdet.cpython-36.pyc │ │ └── multi_pose.cpython-36.pyc │ │ ├── ctdet.py │ │ ├── ddd.py │ │ ├── exdet.py │ │ └── multi_pose.py ├── detectors │ ├── __pycache__ │ │ ├── base_detector.cpython-36.pyc │ │ ├── ctdet.cpython-36.pyc │ │ ├── ddd.cpython-36.pyc │ │ ├── detector_factory.cpython-36.pyc │ │ ├── exdet.cpython-36.pyc │ │ └── multi_pose.cpython-36.pyc │ ├── base_detector.py │ ├── ctdet.py │ ├── ddd.py │ ├── detector_factory.py │ ├── exdet.py │ └── multi_pose.py ├── external │ ├── .gitignore │ ├── Makefile │ ├── __init__.py │ ├── __pycache__ │ │ └── __init__.cpython-36.pyc │ ├── nms.pyx │ └── setup.py ├── logger.py ├── models │ ├── __pycache__ │ │ ├── data_parallel.cpython-36.pyc │ │ ├── decode.cpython-36.pyc │ │ ├── losses.cpython-36.pyc │ │ ├── model.cpython-36.pyc │ │ ├── scatter_gather.cpython-36.pyc │ │ └── utils.cpython-36.pyc │ ├── data_parallel.py │ ├── decode.py │ ├── losses.py │ ├── model.py │ ├── networks │ │ ├── __pycache__ │ │ │ ├── dlav0.cpython-36.pyc │ │ │ ├── large_hourglass.cpython-36.pyc │ │ │ ├── mobilenetv2.cpython-36.pyc │ │ │ ├── msra_resnet.cpython-36.pyc │ │ │ ├── pose_dla_dcn.cpython-36.pyc │ │ │ └── resnet_dcn.cpython-36.pyc │ │ ├── dlav0.py │ │ ├── large_hourglass.py │ │ ├── mobilenetv2.py │ │ ├── msra_resnet.py │ │ ├── pose_dla_dcn.py │ │ └── resnet_dcn.py │ ├── scatter_gather.py │ └── utils.py ├── opts.py ├── pytorch2onnx.py ├── trains │ ├── __pycache__ │ │ ├── base_trainer.cpython-36.pyc │ │ ├── ctdet.cpython-36.pyc │ │ ├── ddd.cpython-36.pyc │ │ ├── exdet.cpython-36.pyc │ │ ├── multi_pose.cpython-36.pyc │ │ └── train_factory.cpython-36.pyc │ ├── base_trainer.py │ ├── ctdet.py │ ├── ddd.py │ ├── exdet.py │ ├── multi_pose.py │ └── train_factory.py └── utils │ ├── __init__.py │ ├── __pycache__ │ ├── __init__.cpython-36.pyc │ ├── ddd_utils.cpython-36.pyc │ ├── debugger.cpython-36.pyc │ ├── image.cpython-36.pyc │ ├── oracle_utils.cpython-36.pyc │ ├── post_process.cpython-36.pyc │ └── utils.cpython-36.pyc │ ├── ddd_utils.py │ ├── debugger.py │ ├── image.py │ ├── oracle_utils.py │ ├── post_process.py │ └── utils.py ├── main.py ├── test.py └── tools ├── _init_paths.py ├── calc_coco_overlap.py ├── convert_hourglass_weight.py ├── convert_kitti_to_coco.py ├── eval_coco.py ├── eval_coco_hp.py ├── get_kitti.sh ├── get_pascal_voc.sh ├── kitti_eval ├── README.md ├── evaluate_object_3d.cpp ├── evaluate_object_3d_offline ├── evaluate_object_3d_offline.cpp └── mail.h ├── merge_pascal_json.py ├── reval.py ├── vis_pred.py └── voc_eval_lib ├── LICENSE ├── Makefile ├── __init__.py ├── datasets ├── __init__.py ├── bbox.pyx ├── ds_utils.py ├── imdb.py ├── pascal_voc.py └── voc_eval.py ├── model ├── __init__.py ├── bbox_transform.py ├── config.py ├── nms_wrapper.py └── test.py ├── nms ├── .gitignore ├── __init__.py ├── cpu_nms.c ├── cpu_nms.pyx ├── gpu_nms.cpp ├── gpu_nms.hpp ├── gpu_nms.pyx ├── nms_kernel.cu └── py_cpu_nms.py ├── setup.py └── utils ├── .gitignore ├── __init__.py ├── bbox.pyx ├── blob.py ├── timer.py └── visualization.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Xingyi Zhou 4 | All rights reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | 24 | -------------------------------------------------------------------------------- /data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /exp/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /experiments/ctdet_coco_dla_1x.sh: -------------------------------------------------------------------------------- 1 | cd src 2 | # train 3 | python main.py ctdet --exp_id coco_dla_1x --batch_size 128 --master_batch 9 --lr 5e-4 --gpus 0,1,2,3,4,5,6,7 --num_workers 16 4 | # test 5 | python test.py ctdet --exp_id coco_dla_1x --keep_res --resume 6 | # flip test 7 | python test.py ctdet --exp_id coco_dla_1x --keep_res --resume --flip_test 8 | # multi scale test 9 | python test.py ctdet --exp_id coco_dla_1x --keep_res --resume --flip_test --test_scales 0.5,0.75,1,1.25,1.5 10 | cd .. 11 | -------------------------------------------------------------------------------- /experiments/ctdet_coco_dla_2x.sh: -------------------------------------------------------------------------------- 1 | cd src 2 | # train 3 | python main.py ctdet --exp_id coco_dla_2x --batch_size 128 --master_batch 9 --lr 5e-4 --gpus 0,1,2,3,4,5,6,7 --num_workers 16 --num_epochs 230 lr_step 180,210 4 | # or use the following command if your have coco_s2_dla_1x trained 5 | # python main.py ctdet --exp_id coco_dla_2x --batch_size 128 --master_batch 9 --lr 5e-4 --gpus 0,1,2,3,4,5,6,7 --num_workers 16 --load_model ../exp/ctdet/coco_dla_1x/model_90.pth --resume 6 | # test 7 | python test.py ctdet --exp_id coco_dla_2x --keep_res --resume 8 | # flip test 9 | python test.py ctdet --exp_id coco_dla_2x --keep_res --resume --flip_test 10 | # multi scale test 11 | python test.py ctdet --exp_id coco_dla_2x --keep_res --resume --flip_test --test_scales 0.5,0.75,1,1.25,1.5 12 | cd .. 13 | -------------------------------------------------------------------------------- /experiments/ctdet_coco_hg.sh: -------------------------------------------------------------------------------- 1 | cd src 2 | # train 3 | python main.py ctdet --exp_id coco_hg --arch hourglass --batch_size 24 --master_batch 4 --lr 2.5e-4 --load_model ../models/ExtremeNet_500000.pth --gpus 0,1,2,3,4 4 | # test 5 | python test.py ctdet --exp_id coco_hg --arch hourglass --keep_res --resume 6 | # flip test 7 | python test.py ctdet --exp_id coco_hg --arch hourglass --keep_res --resume --flip_test 8 | # multi scale test 9 | python test.py ctdet --exp_id coco_hg --arch hourglass --keep_res --resume --flip_test --test_scales 0.5,0.75,1,1.25,1.5 10 | cd .. -------------------------------------------------------------------------------- /experiments/ctdet_coco_resdcn101.sh: -------------------------------------------------------------------------------- 1 | cd src 2 | # train 3 | python main.py ctdet --exp_id coco_resdcn101 --arch resdcn_101 --batch_size 96 --master_batch 5 --lr 3.75e-4 --gpus 0,1,2,3,4,5,6,7 --num_workers 16 4 | # test 5 | python test.py ctdet --exp_id coco_resdcn101 --keep_res --resume 6 | # flip test 7 | python test.py ctdet --exp_id coco_resdcn101 --keep_res --resume --flip_test 8 | # multi scale test 9 | python test.py ctdet --exp_id coco_resdcn101 --keep_res --resume --flip_test --test_scales 0.5,0.75,1,1.25,1.5 10 | cd .. 11 | -------------------------------------------------------------------------------- /experiments/ctdet_coco_resdcn18.sh: -------------------------------------------------------------------------------- 1 | cd src 2 | # train 3 | python main.py ctdet --exp_id coco_resdcn18 --arch resdcn_18 --batch_size 114 --master_batch 18 --lr 5e-4 --gpus 0,1,2,3 --num_workers 16 4 | # test 5 | python test.py ctdet --exp_id coco_resdcn18 --arch resdcn_18 --keep_res --resume 6 | # flip test 7 | python test.py ctdet --exp_id coco_resdcn18 --arch resdcn_18 --keep_res --resume --flip_test 8 | # multi scale test 9 | python test.py ctdet --exp_id coco_resdcn18 --arch resdcn_18 --keep_res --resume --flip_test --test_scales 0.5,0.75,1,1.25,1.5 10 | cd .. 11 | -------------------------------------------------------------------------------- /experiments/ctdet_pascal_dla_384.sh: -------------------------------------------------------------------------------- 1 | cd src 2 | # train 3 | python main.py ctdet --exp_id pascal_dla_384 --dataset pascal --num_epochs 70 --lr_step 45,60 4 | # test 5 | python test.py ctdet --exp_id pascal_dla_384 --dataset pascal --resume 6 | # flip test 7 | python test.py ctdet --exp_id pascal_dla_384 --dataset pascal --resume --flip_test 8 | cd .. 9 | -------------------------------------------------------------------------------- /experiments/ctdet_pascal_dla_512.sh: -------------------------------------------------------------------------------- 1 | cd src 2 | # train 3 | python main.py ctdet --exp_id pascal_dla_512 --dataset pascal --input_res 512 --num_epochs 70 --lr_step 45,60 --gpus 0,1 4 | # test 5 | python test.py ctdet --exp_id pascal_dla_512 --dataset pascal --input_res 512 --resume 6 | # flip test 7 | python test.py ctdet --exp_id pascal_dla_512 --dataset pascal --input_res 512 --resume --flip_test 8 | cd .. 9 | -------------------------------------------------------------------------------- /experiments/ctdet_pascal_resdcn101_384.sh: -------------------------------------------------------------------------------- 1 | cd src 2 | # train 3 | python main.py ctdet --exp_id pascal_resdcn101_384 --arch resdcn_101 --dataset pascal --num_epochs 70 --lr_step 45,60 --gpus 0,1 4 | # test 5 | python test.py ctdet --exp_id pascal_resdcn101_384 --arch resdcn_101 --dataset pascal --resume 6 | # flip test 7 | python test.py ctdet --exp_id pascal_resdcn101_384 --arch resdcn_101 --dataset pascal --resume --flip_test 8 | cd .. 9 | -------------------------------------------------------------------------------- /experiments/ctdet_pascal_resdcn101_512.sh: -------------------------------------------------------------------------------- 1 | cd src 2 | # train 3 | python main.py ctdet --exp_id pascal_resdcn101_512 --arch resdcn_101 --dataset pascal --input_res 512 --num_epochs 70 --lr_step 45,60 --gpus 0,1,2,3 4 | # test 5 | python test.py ctdet --exp_id pascal_resdcn101_512 --arch resdcn_101 --dataset pascal --input_res 512 --resume 6 | # flip test 7 | python test.py ctdet --exp_id pascal_resdcn101_512 --arch resdcn_101 --dataset pascal --input_res 512 --resume --flip_test 8 | cd .. 9 | -------------------------------------------------------------------------------- /experiments/ctdet_pascal_resdcn18_384.sh: -------------------------------------------------------------------------------- 1 | cd src 2 | # train 3 | python main.py ctdet --exp_id pascal_resdcn18_384 --arch resdcn_18 --dataset pascal --num_epochs 70 --lr_step 45,60 4 | # test 5 | python test.py ctdet --exp_id pascal_resdcn18_384 --arch resdcn_18 --dataset pascal --resume 6 | # flip test 7 | python test.py ctdet --exp_id pascal_resdcn18_384 --arch resdcn_18 --dataset pascal --resume --flip_test 8 | cd .. 9 | -------------------------------------------------------------------------------- /experiments/ctdet_pascal_resdcn18_512.sh: -------------------------------------------------------------------------------- 1 | cd src 2 | # train 3 | python main.py ctdet --exp_id pascal_resdcn18_512 --arch resdcn_18 --dataset pascal --input_res 512 --num_epochs 70 --lr_step 45,60 4 | # test 5 | python test.py ctdet --exp_id pascal_resdcn18_512 --arch resdcn_18 --dataset pascal --input_res 512 --resume 6 | # flip test 7 | python test.py ctdet --exp_id pascal_resdcn18_512 --arch resdcn_18 --dataset pascal --input_res 512 --resume --flip_test 8 | cd .. 9 | -------------------------------------------------------------------------------- /experiments/ddd_3dop.sh: -------------------------------------------------------------------------------- 1 | cd src 2 | # train 3 | python main.py ddd --exp_id 3dop --dataset kitti --kitti_split 3dop --batch_size 16 --master_batch 7 --num_epochs 70 --lr_step 45,60 --gpus 0,1 4 | # test 5 | python test.py ddd --exp_id 3dop --dataset kitti --kitti_split 3dop --resume 6 | cd .. 7 | -------------------------------------------------------------------------------- /experiments/ddd_sub.sh: -------------------------------------------------------------------------------- 1 | cd src 2 | # train 3 | python main.py ddd --exp_id sub --dataset kitti --kitti_split subcnn --batch_size 16 --master_batch 7 --num_epochs 70 --lr_step 45,60 --gpus 0,1 4 | # test 5 | python test.py ddd --exp_id sub --dataset kitti --kitti_split subcnn --resume 6 | cd .. 7 | -------------------------------------------------------------------------------- /experiments/exdet_coco_dla.sh: -------------------------------------------------------------------------------- 1 | cd src 2 | # train 3 | python main.py exdet --exp_id coco_dla --batch_size 64 --master_batch 1 --lr 2.5e-4 --gpus 0,1,2,3,4,5,6,7 --num_workers 8 4 | # test 5 | python test.py exdet --exp_id coco_dla --keep_res --resume 6 | # flip test 7 | python test.py exdet --exp_id coco_dla --keep_res --resume --flip_test 8 | # multi scale test 9 | python test.py exdet --exp_id coco_dla --keep_res --resume --flip_test --test_scales 0.5,0.75,1,1.25,1.5 10 | cd .. 11 | -------------------------------------------------------------------------------- /experiments/exdet_coco_hg.sh: -------------------------------------------------------------------------------- 1 | cd src 2 | # train 3 | python main.py exdet --exp_id coco_hg --arch hourglass --batch_size 24 --master_batch 4 --lr 2.5e-4 --gpus 0,1,2,3,4 4 | # test 5 | python test.py exdet --exp_id coco_hg --arch hourglass --keep_res --resume 6 | # flip test 7 | python test.py exdet --exp_id coco_hg --arch hourglass --keep_res --resume --flip_test 8 | # multi scale test 9 | python test.py exdet --exp_id coco_hg --arch hourglass --keep_res --resume --flip_test --test_scales 0.5,0.75,1,1.25,1.5 10 | cd .. 11 | -------------------------------------------------------------------------------- /experiments/multi_pose_dla_1x.sh: -------------------------------------------------------------------------------- 1 | cd src 2 | # train 3 | python main.py multi_pose --exp_id dla_1x --dataset coco_hp --batch_size 128 --master_batch 9 --lr 5e-4 --load_model ../models/ctdet_coco_dla_2x.pth --gpus 0,1,2,3,4,5,6,7 --num_workers 16 4 | # test 5 | python test.py multi_pose --exp_id dla_1x --dataset coco_hp --keep_res --resume 6 | # flip test 7 | python test.py multi_pose --exp_id dla_1x --dataset coco_hp --keep_res --resume --flip_test 8 | cd .. 9 | -------------------------------------------------------------------------------- /experiments/multi_pose_dla_3x.sh: -------------------------------------------------------------------------------- 1 | cd src 2 | # train 3 | python main.py multi_pose --exp_id dla_3x --dataset coco_hp --batch_size 128 --master_batch 9 --lr 5e-4 --load_model ../models/ctdet_coco_dla_2x.pth --gpus 0,1,2,3,4,5,6,7 --num_workers 16 --num_epochs 320 lr_step 270,300 4 | # or use the following command if your have dla_1x trained 5 | # python main.py multi_pose --exp_id dla_3x --dataset coco_hp --batch_size 128 --master_batch 9 --lr 5e-4 --gpus 0,1,2,3,4,5,6,7 --num_workers 16 --load_model ../exp/multi_pose/dla_1x/model_90.pth --resume 6 | # test 7 | python test.py multi_pose --exp_id dla_3x --dataset coco_hp --keep_res --resume 8 | # flip test 9 | python test.py multi_pose --exp_id dla_3x --dataset coco_hp --keep_res --resume --flip_test 10 | cd .. 11 | -------------------------------------------------------------------------------- /experiments/multi_pose_hg_1x.sh: -------------------------------------------------------------------------------- 1 | cd src 2 | # train 3 | python main.py multi_pose --exp_id hg_1x --dataset coco_hp --arch hourglass --batch_size 24 --master_batch 4 --lr 2.5e-4 --load_model ../models/ctdet_coco_hg.pth --gpus 0,1,2,3,4 --num_epochs 50 --lr_step 40 4 | # test 5 | python test.py multi_pose --exp_id hg_1x --dataset coco_hp --arch hourglass --keep_res --resume 6 | # flip test 7 | python test.py multi_pose --exp_id hg_1x --dataset coco_hp --arch hourglass --keep_res --resume --flip_test 8 | cd .. 9 | -------------------------------------------------------------------------------- /experiments/multi_pose_hg_3x.sh: -------------------------------------------------------------------------------- 1 | cd src 2 | # train 3 | python main.py multi_pose --exp_id hg_3x --dataset coco_hp --arch hourglass --batch_size 24 --master_batch 4 --lr 2.5e-4 -load_model ../models/ctdet_coco_hg.pth --gpus 0,1,2,3,4 --num_epochs 150 --lr_step 130 4 | # or use the following command if your have dla_1x trained 5 | # python main.py multi_pose --exp_id hg_3x --dataset coco_hp --arch hourglass --batch_size 24 --master_batch 4 --lr 2.5e-4 --gpus 0,1,2,3,4 --num_epochs 150 --lr_step 130 --load_model ../exp/multi_pose/hg_1x/model_40.pth --resume 6 | # test 7 | python test.py multi_pose --exp_id hg_3x --dataset coco_hp --arch hourglass --keep_res --resume 8 | # flip test 9 | python test.py multi_pose --exp_id hg_3x --dataset coco_hp --arch hourglass --keep_res --resume --flip_test 10 | cd .. 11 | -------------------------------------------------------------------------------- /images/16004479832_a748d55f21_k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/images/16004479832_a748d55f21_k.jpg -------------------------------------------------------------------------------- /images/17790319373_bd19b24cfc_k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/images/17790319373_bd19b24cfc_k.jpg -------------------------------------------------------------------------------- /images/18124840932_e42b3e377c_k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/images/18124840932_e42b3e377c_k.jpg -------------------------------------------------------------------------------- /images/19064748793_bb942deea1_k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/images/19064748793_bb942deea1_k.jpg -------------------------------------------------------------------------------- /images/24274813513_0cfd2ce6d0_k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/images/24274813513_0cfd2ce6d0_k.jpg -------------------------------------------------------------------------------- /images/33823288584_1d21cf0a26_k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/images/33823288584_1d21cf0a26_k.jpg -------------------------------------------------------------------------------- /images/33887522274_eebd074106_k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/images/33887522274_eebd074106_k.jpg -------------------------------------------------------------------------------- /images/34501842524_3c858b3080_k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/images/34501842524_3c858b3080_k.jpg -------------------------------------------------------------------------------- /images/NOTICE: -------------------------------------------------------------------------------- 1 | The demo images are licensed as United States government work: 2 | https://www.usa.gov/government-works 3 | 4 | The image files were obtained on Jan 13, 2018 from the following 5 | URLs. 6 | 7 | 16004479832_a748d55f21_k.jpg 8 | https://www.flickr.com/photos/archivesnews/16004479832 9 | 10 | 18124840932_e42b3e377c_k.jpg 11 | https://www.flickr.com/photos/usnavy/18124840932 12 | 13 | 33887522274_eebd074106_k.jpg 14 | https://www.flickr.com/photos/usaid_pakistan/33887522274 15 | 16 | 15673749081_767a7fa63a_k.jpg 17 | https://www.flickr.com/photos/usnavy/15673749081 18 | 19 | 34501842524_3c858b3080_k.jpg 20 | https://www.flickr.com/photos/departmentofenergy/34501842524 21 | 22 | 24274813513_0cfd2ce6d0_k.jpg 23 | https://www.flickr.com/photos/dhsgov/24274813513 24 | 25 | 19064748793_bb942deea1_k.jpg 26 | https://www.flickr.com/photos/statephotos/19064748793 27 | 28 | 33823288584_1d21cf0a26_k.jpg 29 | https://www.flickr.com/photos/cbpphotos/33823288584 30 | 31 | 17790319373_bd19b24cfc_k.jpg 32 | https://www.flickr.com/photos/secdef/17790319373 33 | -------------------------------------------------------------------------------- /models/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /ncnn/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #1.cmake verson 2 | cmake_minimum_required(VERSION 2.8) 3 | 4 | 5 | 6 | #2.project name 7 | project(demo C CXX) 8 | 9 | #opencv 10 | find_package(OpenCV REQUIRED) 11 | 12 | #3.set environment variable 13 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 14 | 15 | #4. include 16 | include_directories(${CMAKE_CURRENT_LIST_DIR}/include 17 | ${CMAKE_CURRENT_LIST_DIR}/cpp) 18 | 19 | # ncnn lib 20 | add_library( libncnn STATIC IMPORTED ) 21 | set_target_properties( 22 | libncnn 23 | PROPERTIES IMPORTED_LOCATION 24 | ${CMAKE_CURRENT_LIST_DIR}/lib/libncnn.a 25 | ) 26 | 27 | #6.source directory 28 | file(GLOB TEST_SRC ${CMAKE_CURRENT_LIST_DIR}/cpp/*.cpp 29 | ${CMAKE_CURRENT_LIST_DIR}/demo.cpp) 30 | set(TEST_COMPILE_CODE ${TEST_SRC}) 31 | 32 | 33 | add_executable(demo ${TEST_COMPILE_CODE}) 34 | 35 | target_link_libraries(demo 36 | libncnn 37 | ${OpenCV_LIBS} 38 | ) -------------------------------------------------------------------------------- /ncnn/README.md: -------------------------------------------------------------------------------- 1 | ### the C++ version of centernet_mobilenetv2 with ncnn 2 | 3 | ## requirement 4 | - ncnn 5 | - opencv(optional) 6 | 7 | ## usage 8 | * cd centernet_mobilenetv2_ncnn 9 | * mkdir build && cd build && cmake && make 10 | * ./demo ../models/ your_image_path 11 | 12 | ## todo 13 | - The model is still being trained ,I'll update soon. 14 | - test in voc test data 15 | 16 | -------------------------------------------------------------------------------- /ncnn/__pycache__/mobilenetv2.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/__pycache__/mobilenetv2.cpython-36.pyc -------------------------------------------------------------------------------- /ncnn/build/CMakeFiles/3.10.2/CMakeCCompiler.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_C_COMPILER "/usr/bin/cc") 2 | set(CMAKE_C_COMPILER_ARG1 "") 3 | set(CMAKE_C_COMPILER_ID "GNU") 4 | set(CMAKE_C_COMPILER_VERSION "7.5.0") 5 | set(CMAKE_C_COMPILER_VERSION_INTERNAL "") 6 | set(CMAKE_C_COMPILER_WRAPPER "") 7 | set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "11") 8 | set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert") 9 | set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") 10 | set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") 11 | set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") 12 | 13 | set(CMAKE_C_PLATFORM_ID "Linux") 14 | set(CMAKE_C_SIMULATE_ID "") 15 | set(CMAKE_C_SIMULATE_VERSION "") 16 | 17 | 18 | 19 | set(CMAKE_AR "/usr/bin/ar") 20 | set(CMAKE_C_COMPILER_AR "/usr/bin/gcc-ar-7") 21 | set(CMAKE_RANLIB "/usr/bin/ranlib") 22 | set(CMAKE_C_COMPILER_RANLIB "/usr/bin/gcc-ranlib-7") 23 | set(CMAKE_LINKER "/usr/bin/ld") 24 | set(CMAKE_COMPILER_IS_GNUCC 1) 25 | set(CMAKE_C_COMPILER_LOADED 1) 26 | set(CMAKE_C_COMPILER_WORKS TRUE) 27 | set(CMAKE_C_ABI_COMPILED TRUE) 28 | set(CMAKE_COMPILER_IS_MINGW ) 29 | set(CMAKE_COMPILER_IS_CYGWIN ) 30 | if(CMAKE_COMPILER_IS_CYGWIN) 31 | set(CYGWIN 1) 32 | set(UNIX 1) 33 | endif() 34 | 35 | set(CMAKE_C_COMPILER_ENV_VAR "CC") 36 | 37 | if(CMAKE_COMPILER_IS_MINGW) 38 | set(MINGW 1) 39 | endif() 40 | set(CMAKE_C_COMPILER_ID_RUN 1) 41 | set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) 42 | set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) 43 | set(CMAKE_C_LINKER_PREFERENCE 10) 44 | 45 | # Save compiler ABI information. 46 | set(CMAKE_C_SIZEOF_DATA_PTR "8") 47 | set(CMAKE_C_COMPILER_ABI "ELF") 48 | set(CMAKE_C_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") 49 | 50 | if(CMAKE_C_SIZEOF_DATA_PTR) 51 | set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") 52 | endif() 53 | 54 | if(CMAKE_C_COMPILER_ABI) 55 | set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") 56 | endif() 57 | 58 | if(CMAKE_C_LIBRARY_ARCHITECTURE) 59 | set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") 60 | endif() 61 | 62 | set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") 63 | if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) 64 | set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") 65 | endif() 66 | 67 | 68 | 69 | 70 | 71 | set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "gcc;gcc_s;c;gcc;gcc_s") 72 | set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/7;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib") 73 | set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") 74 | -------------------------------------------------------------------------------- /ncnn/build/CMakeFiles/3.10.2/CMakeCXXCompiler.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_CXX_COMPILER "/usr/bin/c++") 2 | set(CMAKE_CXX_COMPILER_ARG1 "") 3 | set(CMAKE_CXX_COMPILER_ID "GNU") 4 | set(CMAKE_CXX_COMPILER_VERSION "7.5.0") 5 | set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "") 6 | set(CMAKE_CXX_COMPILER_WRAPPER "") 7 | set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "14") 8 | set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17") 9 | set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters") 10 | set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates") 11 | set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") 12 | set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17") 13 | 14 | set(CMAKE_CXX_PLATFORM_ID "Linux") 15 | set(CMAKE_CXX_SIMULATE_ID "") 16 | set(CMAKE_CXX_SIMULATE_VERSION "") 17 | 18 | 19 | 20 | set(CMAKE_AR "/usr/bin/ar") 21 | set(CMAKE_CXX_COMPILER_AR "/usr/bin/gcc-ar-7") 22 | set(CMAKE_RANLIB "/usr/bin/ranlib") 23 | set(CMAKE_CXX_COMPILER_RANLIB "/usr/bin/gcc-ranlib-7") 24 | set(CMAKE_LINKER "/usr/bin/ld") 25 | set(CMAKE_COMPILER_IS_GNUCXX 1) 26 | set(CMAKE_CXX_COMPILER_LOADED 1) 27 | set(CMAKE_CXX_COMPILER_WORKS TRUE) 28 | set(CMAKE_CXX_ABI_COMPILED TRUE) 29 | set(CMAKE_COMPILER_IS_MINGW ) 30 | set(CMAKE_COMPILER_IS_CYGWIN ) 31 | if(CMAKE_COMPILER_IS_CYGWIN) 32 | set(CYGWIN 1) 33 | set(UNIX 1) 34 | endif() 35 | 36 | set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") 37 | 38 | if(CMAKE_COMPILER_IS_MINGW) 39 | set(MINGW 1) 40 | endif() 41 | set(CMAKE_CXX_COMPILER_ID_RUN 1) 42 | set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) 43 | set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;mm;CPP) 44 | set(CMAKE_CXX_LINKER_PREFERENCE 30) 45 | set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) 46 | 47 | # Save compiler ABI information. 48 | set(CMAKE_CXX_SIZEOF_DATA_PTR "8") 49 | set(CMAKE_CXX_COMPILER_ABI "ELF") 50 | set(CMAKE_CXX_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") 51 | 52 | if(CMAKE_CXX_SIZEOF_DATA_PTR) 53 | set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") 54 | endif() 55 | 56 | if(CMAKE_CXX_COMPILER_ABI) 57 | set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") 58 | endif() 59 | 60 | if(CMAKE_CXX_LIBRARY_ARCHITECTURE) 61 | set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") 62 | endif() 63 | 64 | set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "") 65 | if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX) 66 | set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}") 67 | endif() 68 | 69 | 70 | 71 | 72 | 73 | set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "stdc++;m;gcc_s;gcc;c;gcc_s;gcc") 74 | set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/7;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib") 75 | set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") 76 | -------------------------------------------------------------------------------- /ncnn/build/CMakeFiles/3.10.2/CMakeDetermineCompilerABI_C.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/build/CMakeFiles/3.10.2/CMakeDetermineCompilerABI_C.bin -------------------------------------------------------------------------------- /ncnn/build/CMakeFiles/3.10.2/CMakeDetermineCompilerABI_CXX.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/build/CMakeFiles/3.10.2/CMakeDetermineCompilerABI_CXX.bin -------------------------------------------------------------------------------- /ncnn/build/CMakeFiles/3.10.2/CMakeSystem.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_HOST_SYSTEM "Linux-5.3.0-53-generic") 2 | set(CMAKE_HOST_SYSTEM_NAME "Linux") 3 | set(CMAKE_HOST_SYSTEM_VERSION "5.3.0-53-generic") 4 | set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") 5 | 6 | 7 | 8 | set(CMAKE_SYSTEM "Linux-5.3.0-53-generic") 9 | set(CMAKE_SYSTEM_NAME "Linux") 10 | set(CMAKE_SYSTEM_VERSION "5.3.0-53-generic") 11 | set(CMAKE_SYSTEM_PROCESSOR "x86_64") 12 | 13 | set(CMAKE_CROSSCOMPILING "FALSE") 14 | 15 | set(CMAKE_SYSTEM_LOADED 1) 16 | -------------------------------------------------------------------------------- /ncnn/build/CMakeFiles/3.10.2/CompilerIdC/a.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/build/CMakeFiles/3.10.2/CompilerIdC/a.out -------------------------------------------------------------------------------- /ncnn/build/CMakeFiles/3.10.2/CompilerIdCXX/a.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/build/CMakeFiles/3.10.2/CompilerIdCXX/a.out -------------------------------------------------------------------------------- /ncnn/build/CMakeFiles/CMakeDirectoryInformation.cmake: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.10 3 | 4 | # Relative path conversion top directories. 5 | set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/mario/Projects/Gaotong/centernet_mobilenetv2_ncnn-master") 6 | set(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/mario/Projects/Gaotong/centernet_mobilenetv2_ncnn-master/build") 7 | 8 | # Force unix paths in dependencies. 9 | set(CMAKE_FORCE_UNIX_PATHS 1) 10 | 11 | 12 | # The C and CXX include file regular expressions for this directory. 13 | set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") 14 | set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") 15 | set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) 16 | set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) 17 | -------------------------------------------------------------------------------- /ncnn/build/CMakeFiles/Makefile2: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.10 3 | 4 | # Default target executed when no arguments are given to make. 5 | default_target: all 6 | 7 | .PHONY : default_target 8 | 9 | # The main recursive all target 10 | all: 11 | 12 | .PHONY : all 13 | 14 | # The main recursive preinstall target 15 | preinstall: 16 | 17 | .PHONY : preinstall 18 | 19 | #============================================================================= 20 | # Special targets provided by cmake. 21 | 22 | # Disable implicit rules so canonical targets will work. 23 | .SUFFIXES: 24 | 25 | 26 | # Remove some rules from gmake that .SUFFIXES does not remove. 27 | SUFFIXES = 28 | 29 | .SUFFIXES: .hpux_make_needs_suffix_list 30 | 31 | 32 | # Suppress display of executed commands. 33 | $(VERBOSE).SILENT: 34 | 35 | 36 | # A target that is always out of date. 37 | cmake_force: 38 | 39 | .PHONY : cmake_force 40 | 41 | #============================================================================= 42 | # Set environment variables for the build. 43 | 44 | # The shell in which to execute make rules. 45 | SHELL = /bin/sh 46 | 47 | # The CMake executable. 48 | CMAKE_COMMAND = /usr/bin/cmake 49 | 50 | # The command to remove a file. 51 | RM = /usr/bin/cmake -E remove -f 52 | 53 | # Escaping for special characters. 54 | EQUALS = = 55 | 56 | # The top-level source directory on which CMake was run. 57 | CMAKE_SOURCE_DIR = /home/mario/Projects/Gaotong/centernet_mobilenetv2_ncnn-master 58 | 59 | # The top-level build directory on which CMake was run. 60 | CMAKE_BINARY_DIR = /home/mario/Projects/Gaotong/centernet_mobilenetv2_ncnn-master/build 61 | 62 | #============================================================================= 63 | # Target rules for target CMakeFiles/demo.dir 64 | 65 | # All Build rule for target. 66 | CMakeFiles/demo.dir/all: 67 | $(MAKE) -f CMakeFiles/demo.dir/build.make CMakeFiles/demo.dir/depend 68 | $(MAKE) -f CMakeFiles/demo.dir/build.make CMakeFiles/demo.dir/build 69 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/mario/Projects/Gaotong/centernet_mobilenetv2_ncnn-master/build/CMakeFiles --progress-num=1,2,3 "Built target demo" 70 | .PHONY : CMakeFiles/demo.dir/all 71 | 72 | # Include target in all. 73 | all: CMakeFiles/demo.dir/all 74 | 75 | .PHONY : all 76 | 77 | # Build rule for subdir invocation for target. 78 | CMakeFiles/demo.dir/rule: cmake_check_build_system 79 | $(CMAKE_COMMAND) -E cmake_progress_start /home/mario/Projects/Gaotong/centernet_mobilenetv2_ncnn-master/build/CMakeFiles 3 80 | $(MAKE) -f CMakeFiles/Makefile2 CMakeFiles/demo.dir/all 81 | $(CMAKE_COMMAND) -E cmake_progress_start /home/mario/Projects/Gaotong/centernet_mobilenetv2_ncnn-master/build/CMakeFiles 0 82 | .PHONY : CMakeFiles/demo.dir/rule 83 | 84 | # Convenience name for target. 85 | demo: CMakeFiles/demo.dir/rule 86 | 87 | .PHONY : demo 88 | 89 | # clean rule for target. 90 | CMakeFiles/demo.dir/clean: 91 | $(MAKE) -f CMakeFiles/demo.dir/build.make CMakeFiles/demo.dir/clean 92 | .PHONY : CMakeFiles/demo.dir/clean 93 | 94 | # clean rule for target. 95 | clean: CMakeFiles/demo.dir/clean 96 | 97 | .PHONY : clean 98 | 99 | #============================================================================= 100 | # Special targets to cleanup operation of make. 101 | 102 | # Special rule to run CMake to check the build system integrity. 103 | # No rule that depends on this can have commands that come from listfiles 104 | # because they might be regenerated. 105 | cmake_check_build_system: 106 | $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 107 | .PHONY : cmake_check_build_system 108 | 109 | -------------------------------------------------------------------------------- /ncnn/build/CMakeFiles/TargetDirectories.txt: -------------------------------------------------------------------------------- 1 | /home/mario/Projects/Gaotong/centernet_mobilenetv2_ncnn-master/build/CMakeFiles/rebuild_cache.dir 2 | /home/mario/Projects/Gaotong/centernet_mobilenetv2_ncnn-master/build/CMakeFiles/demo.dir 3 | /home/mario/Projects/Gaotong/centernet_mobilenetv2_ncnn-master/build/CMakeFiles/edit_cache.dir 4 | -------------------------------------------------------------------------------- /ncnn/build/CMakeFiles/cmake.check_cache: -------------------------------------------------------------------------------- 1 | # This file is generated by cmake for dependency checking of the CMakeCache.txt file 2 | -------------------------------------------------------------------------------- /ncnn/build/CMakeFiles/demo.dir/DependInfo.cmake: -------------------------------------------------------------------------------- 1 | # The set of languages for which implicit dependencies are needed: 2 | set(CMAKE_DEPENDS_LANGUAGES 3 | "CXX" 4 | ) 5 | # The set of files for implicit dependencies of each language: 6 | set(CMAKE_DEPENDS_CHECK_CXX 7 | "/home/mario/Projects/Gaotong/centernet_mobilenetv2_ncnn-master/cpp/ncnn_centernet.cpp" "/home/mario/Projects/Gaotong/centernet_mobilenetv2_ncnn-master/build/CMakeFiles/demo.dir/cpp/ncnn_centernet.cpp.o" 8 | "/home/mario/Projects/Gaotong/centernet_mobilenetv2_ncnn-master/demo.cpp" "/home/mario/Projects/Gaotong/centernet_mobilenetv2_ncnn-master/build/CMakeFiles/demo.dir/demo.cpp.o" 9 | ) 10 | set(CMAKE_CXX_COMPILER_ID "GNU") 11 | 12 | # The include file search paths: 13 | set(CMAKE_CXX_TARGET_INCLUDE_PATH 14 | "../include" 15 | "../cpp" 16 | "/usr/local/include" 17 | "/usr/local/include/opencv" 18 | ) 19 | 20 | # Targets to which this target links. 21 | set(CMAKE_TARGET_LINKED_INFO_FILES 22 | ) 23 | 24 | # Fortran module output directory. 25 | set(CMAKE_Fortran_TARGET_MODULE_DIR "") 26 | -------------------------------------------------------------------------------- /ncnn/build/CMakeFiles/demo.dir/cmake_clean.cmake: -------------------------------------------------------------------------------- 1 | file(REMOVE_RECURSE 2 | "CMakeFiles/demo.dir/cpp/ncnn_centernet.cpp.o" 3 | "CMakeFiles/demo.dir/demo.cpp.o" 4 | "demo.pdb" 5 | "demo" 6 | ) 7 | 8 | # Per-language clean rules from dependency scanning. 9 | foreach(lang CXX) 10 | include(CMakeFiles/demo.dir/cmake_clean_${lang}.cmake OPTIONAL) 11 | endforeach() 12 | -------------------------------------------------------------------------------- /ncnn/build/CMakeFiles/demo.dir/cpp/ncnn_centernet.cpp.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/build/CMakeFiles/demo.dir/cpp/ncnn_centernet.cpp.o -------------------------------------------------------------------------------- /ncnn/build/CMakeFiles/demo.dir/demo.cpp.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/build/CMakeFiles/demo.dir/demo.cpp.o -------------------------------------------------------------------------------- /ncnn/build/CMakeFiles/demo.dir/flags.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.10 3 | 4 | # compile CXX with /usr/bin/c++ 5 | CXX_FLAGS = -std=c++11 6 | 7 | CXX_DEFINES = 8 | 9 | CXX_INCLUDES = -I/home/mario/Projects/Gaotong/centernet_mobilenetv2_ncnn-master/include -I/home/mario/Projects/Gaotong/centernet_mobilenetv2_ncnn-master/cpp -isystem /usr/local/include -isystem /usr/local/include/opencv 10 | 11 | -------------------------------------------------------------------------------- /ncnn/build/CMakeFiles/demo.dir/link.txt: -------------------------------------------------------------------------------- 1 | /usr/bin/c++ -std=c++11 -rdynamic CMakeFiles/demo.dir/cpp/ncnn_centernet.cpp.o CMakeFiles/demo.dir/demo.cpp.o -o demo -Wl,-rpath,/usr/local/lib ../lib/libncnn.a /usr/local/lib/libopencv_dnn.so.3.4.0 /usr/local/lib/libopencv_ml.so.3.4.0 /usr/local/lib/libopencv_objdetect.so.3.4.0 /usr/local/lib/libopencv_shape.so.3.4.0 /usr/local/lib/libopencv_stitching.so.3.4.0 /usr/local/lib/libopencv_superres.so.3.4.0 /usr/local/lib/libopencv_videostab.so.3.4.0 /usr/local/lib/libopencv_calib3d.so.3.4.0 /usr/local/lib/libopencv_features2d.so.3.4.0 /usr/local/lib/libopencv_flann.so.3.4.0 /usr/local/lib/libopencv_highgui.so.3.4.0 /usr/local/lib/libopencv_photo.so.3.4.0 /usr/local/lib/libopencv_video.so.3.4.0 /usr/local/lib/libopencv_videoio.so.3.4.0 /usr/local/lib/libopencv_imgcodecs.so.3.4.0 /usr/local/lib/libopencv_imgproc.so.3.4.0 /usr/local/lib/libopencv_core.so.3.4.0 2 | -------------------------------------------------------------------------------- /ncnn/build/CMakeFiles/demo.dir/progress.make: -------------------------------------------------------------------------------- 1 | CMAKE_PROGRESS_1 = 1 2 | CMAKE_PROGRESS_2 = 2 3 | CMAKE_PROGRESS_3 = 3 4 | 5 | -------------------------------------------------------------------------------- /ncnn/build/CMakeFiles/feature_tests.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/build/CMakeFiles/feature_tests.bin -------------------------------------------------------------------------------- /ncnn/build/CMakeFiles/feature_tests.c: -------------------------------------------------------------------------------- 1 | 2 | const char features[] = {"\n" 3 | "C_FEATURE:" 4 | #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 304 5 | "1" 6 | #else 7 | "0" 8 | #endif 9 | "c_function_prototypes\n" 10 | "C_FEATURE:" 11 | #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 304 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L 12 | "1" 13 | #else 14 | "0" 15 | #endif 16 | "c_restrict\n" 17 | "C_FEATURE:" 18 | #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201000L 19 | "1" 20 | #else 21 | "0" 22 | #endif 23 | "c_static_assert\n" 24 | "C_FEATURE:" 25 | #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 304 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L 26 | "1" 27 | #else 28 | "0" 29 | #endif 30 | "c_variadic_macros\n" 31 | 32 | }; 33 | 34 | int main(int argc, char** argv) { (void)argv; return features[argc]; } 35 | -------------------------------------------------------------------------------- /ncnn/build/CMakeFiles/progress.marks: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /ncnn/build/cmake_install.cmake: -------------------------------------------------------------------------------- 1 | # Install script for directory: /home/mario/Projects/Gaotong/centernet_mobilenetv2_ncnn-master 2 | 3 | # Set the install prefix 4 | if(NOT DEFINED CMAKE_INSTALL_PREFIX) 5 | set(CMAKE_INSTALL_PREFIX "/usr/local") 6 | endif() 7 | string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") 8 | 9 | # Set the install configuration name. 10 | if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) 11 | if(BUILD_TYPE) 12 | string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" 13 | CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") 14 | else() 15 | set(CMAKE_INSTALL_CONFIG_NAME "") 16 | endif() 17 | message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") 18 | endif() 19 | 20 | # Set the component getting installed. 21 | if(NOT CMAKE_INSTALL_COMPONENT) 22 | if(COMPONENT) 23 | message(STATUS "Install component: \"${COMPONENT}\"") 24 | set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") 25 | else() 26 | set(CMAKE_INSTALL_COMPONENT) 27 | endif() 28 | endif() 29 | 30 | # Install shared libraries without execute permission? 31 | if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) 32 | set(CMAKE_INSTALL_SO_NO_EXE "1") 33 | endif() 34 | 35 | # Is this installation the result of a crosscompile? 36 | if(NOT DEFINED CMAKE_CROSSCOMPILING) 37 | set(CMAKE_CROSSCOMPILING "FALSE") 38 | endif() 39 | 40 | if(CMAKE_INSTALL_COMPONENT) 41 | set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") 42 | else() 43 | set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") 44 | endif() 45 | 46 | string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT 47 | "${CMAKE_INSTALL_MANIFEST_FILES}") 48 | file(WRITE "/home/mario/Projects/Gaotong/centernet_mobilenetv2_ncnn-master/build/${CMAKE_INSTALL_MANIFEST}" 49 | "${CMAKE_INSTALL_MANIFEST_CONTENT}") 50 | -------------------------------------------------------------------------------- /ncnn/build/demo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/build/demo -------------------------------------------------------------------------------- /ncnn/cpp/ncnn_centernet.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "net.h" 7 | 8 | #define NMS_UNION 1 9 | #define NMS_MIN 2 10 | 11 | typedef struct ObjInfo { 12 | float x1; 13 | float y1; 14 | float x2; 15 | float y2; 16 | float score; 17 | float area; 18 | int label; 19 | }; 20 | 21 | class Centerobj { 22 | public: 23 | Centerobj(); 24 | ~Centerobj(); 25 | 26 | int init(std::string model_path); 27 | 28 | 29 | //You can change the shape of input image by setting params :resized_w and resized_h 30 | int detect(ncnn::Mat &inblob, std::vector&objs, int resized_w,int resized_h, 31 | float scoreThresh = 0.2, float nmsThresh = 0.45); 32 | 33 | private: 34 | void dynamicScale(float in_w, float in_h); 35 | void genIds(float * heatmap, int h, int w,int c, float thresh, std::vector &ids); 36 | void nms(std::vector& input, std::vector& output, float nmsthreshold = 0.3,int type=NMS_MIN); 37 | void decode(ncnn::Mat & heatmap , ncnn::Mat &scale, ncnn::Mat &offset, 38 | std::vector&objs, float scoreThresh, float nmsThresh); 39 | private: 40 | ncnn::Net net; 41 | 42 | int d_h; 43 | int d_w; 44 | float d_scale_h; 45 | float d_scale_w; 46 | 47 | float scale_h; 48 | float scale_w; 49 | 50 | int image_h; 51 | int image_w; 52 | }; 53 | 54 | 55 | -------------------------------------------------------------------------------- /ncnn/demo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "ncnn_centernet.h" 4 | #include 5 | 6 | 7 | float getElapse(struct timeval *tv1,struct timeval *tv2) 8 | { 9 | float t = 0.0f; 10 | if (tv1->tv_sec == tv2->tv_sec) 11 | t = (tv2->tv_usec - tv1->tv_usec)/1000.0f; 12 | else 13 | t = ((tv2->tv_sec - tv1->tv_sec) * 1000 * 1000 + tv2->tv_usec - tv1->tv_usec)/1000.0f; 14 | return t; 15 | } 16 | 17 | 18 | 19 | static void draw_objects(const cv::Mat& bgr, const std::vector obj_info, float ratio) 20 | { 21 | // static const char* class_names[] = { 22 | // "aeroplane", "bicycle", "bird", "boat", 23 | // "bottle", "bus", "car", "cat", "chair", 24 | // "cow", "diningtable", "dog", "horse", 25 | // "motorbike", "person", "pottedplant", 26 | // "sheep", "sofa", "train", "tvmonitor"}; 27 | static const char* class_names[] = { 28 | "rgb_face"}; 29 | 30 | cv::Mat image = bgr.clone(); 31 | 32 | for (size_t i = 0; i < obj_info.size(); i++) 33 | { 34 | 35 | if (obj_info[i].score > 0.35) 36 | { 37 | const ObjInfo& obj = obj_info[i]; 38 | 39 | fprintf(stderr, "%d = %.5f at %.2f %.2f %.2f x %.2f\n", obj.label, obj.score, 40 | obj.x1, obj.y1, obj.x2, obj.y2); 41 | 42 | cv::rectangle(image, cv::Point(obj.x1 /ratio, obj.y1 / ratio), cv::Point(obj.x2 /ratio, obj.y2 /ratio), cv::Scalar(255, 0, 0)); 43 | 44 | char text[256]; 45 | sprintf(text, "%s %.1f%%", class_names[obj.label], obj.score * 100); 46 | 47 | int baseLine = 0; 48 | cv::Size label_size = cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine); 49 | 50 | int x = obj.x1 / ratio; 51 | int y = obj.y1 / ratio - label_size.height - baseLine; 52 | if (y < 0) 53 | y = 0; 54 | if (x + label_size.width > image.cols) 55 | x = image.cols - label_size.width; 56 | 57 | cv::rectangle(image, cv::Rect(cv::Point(x, y), cv::Size(label_size.width, label_size.height + baseLine)), 58 | cv::Scalar(255, 255, 255), -1); 59 | 60 | cv::putText(image, text, cv::Point(x, y + label_size.height), 61 | cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0)); 62 | } 63 | } 64 | 65 | cv::imwrite("result.jpg",image); 66 | } 67 | 68 | 69 | int main(int argc, char** argv) { 70 | if (argc !=3) 71 | { 72 | std::cout << " .exe mode_path image_file" << std::endl; 73 | return -1; 74 | } 75 | struct timeval tv1,tv2; 76 | struct timezone tz1,tz2; 77 | 78 | std::string model_path = argv[1]; 79 | std::string image_file = argv[2]; 80 | 81 | Centerobj centerobj; 82 | 83 | centerobj.init(model_path); 84 | 85 | cv::Mat image = cv::imread(image_file); 86 | 87 | // img_resize = image.clone(); 88 | int long_size = 320; 89 | int ori_w = image.cols; 90 | int ori_h = image.rows; 91 | float ratio = 320 *1.0 / ori_w; 92 | if (ori_h > ori_w) ratio = 320 *1.0 / ori_h; 93 | 94 | cv::Mat img_resize; 95 | cv::resize(image, img_resize, cv::Size(ori_w*ratio, ori_h*ratio), (0, 0), (0, 0), cv::INTER_LINEAR); 96 | std::vector obj_info; 97 | ncnn::Mat inmat = ncnn::Mat::from_pixels(img_resize.data, ncnn::Mat::PIXEL_BGR, img_resize.cols, img_resize.rows); 98 | std::cout << "cols = " << img_resize.cols << ", " << "rows = " << img_resize.rows << std::endl; 99 | for(int i = 0; i<10;i++){ 100 | gettimeofday(&tv1,&tz1); 101 | centerobj.detect(inmat, obj_info, img_resize.cols, img_resize.rows); 102 | gettimeofday(&tv2,&tz2); 103 | float tc = getElapse(&tv1, &tv2); 104 | std::cout << "耗时:" << tc << "ms" << std::endl; 105 | } 106 | 107 | // for (int i = 0; i < obj_info.size(); i++) { 108 | // cv::rectangle(img_resize, cv::Point(obj_info[i].x1, obj_info[i].y1), cv::Point(obj_info[i].x2, obj_info[i].y2), cv::Scalar(0, 255, 0), 2); 109 | 110 | // } 111 | // cv::imwrite("test.jpg",img_resize); 112 | 113 | 114 | draw_objects(image,obj_info,ratio); 115 | // cv::imshow("test", image); 116 | // cv::waitKey(); 117 | 118 | return 0; 119 | } -------------------------------------------------------------------------------- /ncnn/dog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/dog.jpg -------------------------------------------------------------------------------- /ncnn/faceimg/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/faceimg/1.jpg -------------------------------------------------------------------------------- /ncnn/faceimg/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/faceimg/2.jpg -------------------------------------------------------------------------------- /ncnn/faceimg/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/faceimg/3.jpg -------------------------------------------------------------------------------- /ncnn/faceimg/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/faceimg/4.jpg -------------------------------------------------------------------------------- /ncnn/faceimg/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/faceimg/5.jpg -------------------------------------------------------------------------------- /ncnn/include/benchmark.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_BENCHMARK_H 16 | #define NCNN_BENCHMARK_H 17 | 18 | #include "platform.h" 19 | #include "mat.h" 20 | #include "layer.h" 21 | 22 | namespace ncnn { 23 | 24 | // get now timestamp in ms 25 | double get_current_time(); 26 | 27 | #if NCNN_BENCHMARK 28 | 29 | void benchmark(const Layer* layer, double start, double end); 30 | void benchmark(const Layer* layer, const Mat& bottom_blob, Mat& top_blob, double start, double end); 31 | 32 | #endif // NCNN_BENCHMARK 33 | 34 | } // namespace ncnn 35 | 36 | #endif // NCNN_BENCHMARK_H 37 | -------------------------------------------------------------------------------- /ncnn/include/blob.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_BLOB_H 16 | #define NCNN_BLOB_H 17 | 18 | #include 19 | #include 20 | #include "platform.h" 21 | 22 | namespace ncnn { 23 | 24 | class Blob 25 | { 26 | public: 27 | // empty 28 | Blob(); 29 | 30 | public: 31 | #if NCNN_STRING 32 | // blob name 33 | std::string name; 34 | #endif // NCNN_STRING 35 | // layer index which produce this blob as output 36 | int producer; 37 | // layer index which need this blob as input 38 | std::vector consumers; 39 | }; 40 | 41 | } // namespace ncnn 42 | 43 | #endif // NCNN_BLOB_H 44 | -------------------------------------------------------------------------------- /ncnn/include/cpu.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_CPU_H 16 | #define NCNN_CPU_H 17 | 18 | namespace ncnn { 19 | 20 | // test optional cpu features 21 | // neon = armv7 neon or aarch64 asimd 22 | int cpu_support_arm_neon(); 23 | // vfpv4 = armv7 fp16 + fma 24 | int cpu_support_arm_vfpv4(); 25 | // asimdhp = aarch64 asimd half precision 26 | int cpu_support_arm_asimdhp(); 27 | 28 | // cpu info 29 | int get_cpu_count(); 30 | 31 | // bind all threads on little clusters if powersave enabled 32 | // affacts HMP arch cpu like ARM big.LITTLE 33 | // only implemented on android at the moment 34 | // switching powersave is expensive and not thread-safe 35 | // 0 = all cores enabled(default) 36 | // 1 = only little clusters enabled 37 | // 2 = only big clusters enabled 38 | // return 0 if success for setter function 39 | int get_cpu_powersave(); 40 | int set_cpu_powersave(int powersave); 41 | 42 | // misc function wrapper for openmp routines 43 | int get_omp_num_threads(); 44 | void set_omp_num_threads(int num_threads); 45 | 46 | int get_omp_dynamic(); 47 | void set_omp_dynamic(int dynamic); 48 | 49 | } // namespace ncnn 50 | 51 | #endif // NCNN_CPU_H 52 | -------------------------------------------------------------------------------- /ncnn/include/layer.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_LAYER_H 16 | #define NCNN_LAYER_H 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include "platform.h" 23 | #include "mat.h" 24 | #include "modelbin.h" 25 | #include "option.h" 26 | #include "paramdict.h" 27 | 28 | #if NCNN_VULKAN 29 | #include 30 | #include "command.h" 31 | #include "pipeline.h" 32 | #endif // NCNN_VULKAN 33 | 34 | namespace ncnn { 35 | 36 | class Layer 37 | { 38 | public: 39 | // empty 40 | Layer(); 41 | // virtual destructor 42 | virtual ~Layer(); 43 | 44 | // load layer specific parameter from parsed dict 45 | // return 0 if success 46 | virtual int load_param(const ParamDict& pd); 47 | 48 | // load layer specific weight data from model binary 49 | // return 0 if success 50 | virtual int load_model(const ModelBin& mb); 51 | 52 | // layer implementation specific setup 53 | // return 0 if success 54 | virtual int create_pipeline(const Option& opt = Option()); 55 | 56 | // layer implementation specific clean 57 | // return 0 if success 58 | virtual int destroy_pipeline(const Option& opt = Option()); 59 | 60 | public: 61 | // one input and one output blob 62 | bool one_blob_only; 63 | 64 | // support inplace inference 65 | bool support_inplace; 66 | 67 | // support vulkan compute 68 | bool support_vulkan; 69 | 70 | public: 71 | // implement inference 72 | // return 0 if success 73 | virtual int forward(const std::vector& bottom_blobs, std::vector& top_blobs, const Option& opt = Option()) const; 74 | virtual int forward(const Mat& bottom_blob, Mat& top_blob, const Option& opt = Option()) const; 75 | 76 | // implement inplace inference 77 | // return 0 if success 78 | virtual int forward_inplace(std::vector& bottom_top_blobs, const Option& opt = Option()) const; 79 | virtual int forward_inplace(Mat& bottom_top_blob, const Option& opt = Option()) const; 80 | 81 | #if NCNN_VULKAN 82 | public: 83 | // upload weight blob from host to device 84 | virtual int upload_model(VkTransfer& cmd, const Option& opt = Option()); 85 | 86 | public: 87 | // implement inference 88 | // return 0 if success 89 | virtual int forward(const std::vector& bottom_blobs, std::vector& top_blobs, VkCompute& cmd, const Option& opt = Option()) const; 90 | virtual int forward(const VkMat& bottom_blob, VkMat& top_blob, VkCompute& cmd, const Option& opt = Option()) const; 91 | 92 | // implement inplace inference 93 | // return 0 if success 94 | virtual int forward_inplace(std::vector& bottom_top_blobs, VkCompute& cmd, const Option& opt = Option()) const; 95 | virtual int forward_inplace(VkMat& bottom_top_blob, VkCompute& cmd, const Option& opt = Option()) const; 96 | 97 | public: 98 | // assigned immediately after creating this layer 99 | const VulkanDevice* vkdev; 100 | #endif // NCNN_VULKAN 101 | 102 | public: 103 | // layer type index 104 | int typeindex; 105 | #if NCNN_STRING 106 | // layer type name 107 | std::string type; 108 | // layer name 109 | std::string name; 110 | #endif // NCNN_STRING 111 | // blob index which this layer needs as input 112 | std::vector bottoms; 113 | // blob index which this layer produces as output 114 | std::vector tops; 115 | }; 116 | 117 | // layer factory function 118 | typedef Layer* (*layer_creator_func)(); 119 | 120 | struct layer_registry_entry 121 | { 122 | #if NCNN_STRING 123 | // layer type name 124 | const char* name; 125 | #endif // NCNN_STRING 126 | // layer factory entry 127 | layer_creator_func creator; 128 | }; 129 | 130 | #if NCNN_STRING 131 | // get layer type from type name 132 | int layer_to_index(const char* type); 133 | // create layer from type name 134 | Layer* create_layer(const char* type); 135 | #endif // NCNN_STRING 136 | // create layer from layer type 137 | Layer* create_layer(int index); 138 | 139 | #define DEFINE_LAYER_CREATOR(name) \ 140 | ::ncnn::Layer* name##_layer_creator() { return new name; } 141 | 142 | } // namespace ncnn 143 | 144 | #endif // NCNN_LAYER_H 145 | -------------------------------------------------------------------------------- /ncnn/include/layer_type.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_LAYER_TYPE_H 16 | #define NCNN_LAYER_TYPE_H 17 | 18 | namespace ncnn { 19 | 20 | namespace LayerType { 21 | enum 22 | { 23 | #include "layer_type_enum.h" 24 | CustomBit = (1<<8), 25 | }; 26 | } // namespace LayerType 27 | 28 | } // namespace ncnn 29 | 30 | #endif // NCNN_LAYER_TYPE_H 31 | -------------------------------------------------------------------------------- /ncnn/include/layer_type_enum.h: -------------------------------------------------------------------------------- 1 | // Layer Type Enum header 2 | // 3 | // This file is auto-generated by cmake, don't edit it. 4 | 5 | AbsVal = 0, 6 | ArgMax = 1, 7 | BatchNorm = 2, 8 | Bias = 3, 9 | BNLL = 4, 10 | Concat = 5, 11 | Convolution = 6, 12 | Crop = 7, 13 | Deconvolution = 8, 14 | Dropout = 9, 15 | Eltwise = 10, 16 | ELU = 11, 17 | Embed = 12, 18 | Exp = 13, 19 | Flatten = 14, 20 | InnerProduct = 15, 21 | Input = 16, 22 | Log = 17, 23 | LRN = 18, 24 | MemoryData = 19, 25 | MVN = 20, 26 | Pooling = 21, 27 | Power = 22, 28 | PReLU = 23, 29 | Proposal = 24, 30 | Reduction = 25, 31 | ReLU = 26, 32 | Reshape = 27, 33 | ROIPooling = 28, 34 | Scale = 29, 35 | Sigmoid = 30, 36 | Slice = 31, 37 | Softmax = 32, 38 | Split = 33, 39 | SPP = 34, 40 | TanH = 35, 41 | Threshold = 36, 42 | Tile = 37, 43 | RNN = 38, 44 | LSTM = 39, 45 | BinaryOp = 40, 46 | UnaryOp = 41, 47 | ConvolutionDepthWise = 42, 48 | Padding = 43, 49 | Squeeze = 44, 50 | ExpandDims = 45, 51 | Normalize = 46, 52 | Permute = 47, 53 | PriorBox = 48, 54 | DetectionOutput = 49, 55 | Interp = 50, 56 | DeconvolutionDepthWise = 51, 57 | ShuffleChannel = 52, 58 | InstanceNorm = 53, 59 | Clip = 54, 60 | Reorg = 55, 61 | YoloDetectionOutput = 56, 62 | Quantize = 57, 63 | Dequantize = 58, 64 | Yolov3DetectionOutput = 59, 65 | PSROIPooling = 60, 66 | ROIAlign = 61, 67 | Packing = 62, 68 | Requantize = 63, 69 | Cast = 64, 70 | 71 | -------------------------------------------------------------------------------- /ncnn/include/modelbin.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_MODELBIN_H 16 | #define NCNN_MODELBIN_H 17 | 18 | #include 19 | #include "mat.h" 20 | #include "platform.h" 21 | 22 | namespace ncnn { 23 | 24 | class Net; 25 | class ModelBin 26 | { 27 | public: 28 | // element type 29 | // 0 = auto 30 | // 1 = float32 31 | // 2 = float16 32 | // 3 = int8 33 | // load vec 34 | virtual Mat load(int w, int type) const = 0; 35 | // load image 36 | virtual Mat load(int w, int h, int type) const; 37 | // load dim 38 | virtual Mat load(int w, int h, int c, int type) const; 39 | }; 40 | 41 | #if NCNN_STDIO 42 | class ModelBinFromStdio : public ModelBin 43 | { 44 | public: 45 | // construct from file 46 | ModelBinFromStdio(FILE* binfp); 47 | 48 | virtual Mat load(int w, int type) const; 49 | 50 | protected: 51 | FILE* binfp; 52 | }; 53 | #endif // NCNN_STDIO 54 | 55 | class ModelBinFromMemory : public ModelBin 56 | { 57 | public: 58 | // construct from external memory 59 | ModelBinFromMemory(const unsigned char*& mem); 60 | 61 | virtual Mat load(int w, int type) const; 62 | 63 | protected: 64 | const unsigned char*& mem; 65 | }; 66 | 67 | class ModelBinFromMatArray : public ModelBin 68 | { 69 | public: 70 | // construct from weight blob array 71 | ModelBinFromMatArray(const Mat* weights); 72 | 73 | virtual Mat load(int w, int type) const; 74 | 75 | protected: 76 | mutable const Mat* weights; 77 | }; 78 | 79 | } // namespace ncnn 80 | 81 | #endif // NCNN_MODELBIN_H 82 | -------------------------------------------------------------------------------- /ncnn/include/option.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_OPTION_H 16 | #define NCNN_OPTION_H 17 | 18 | #include "platform.h" 19 | 20 | namespace ncnn { 21 | 22 | #if NCNN_VULKAN 23 | class VkAllocator; 24 | #endif // NCNN_VULKAN 25 | 26 | class Allocator; 27 | class Option 28 | { 29 | public: 30 | // default option 31 | Option(); 32 | 33 | public: 34 | // light mode 35 | // intermediate blob will be recycled when enabled 36 | // enabled by default 37 | bool lightmode; 38 | 39 | // thread count 40 | // default value is the one returned by get_cpu_count() 41 | int num_threads; 42 | 43 | // blob memory allocator 44 | Allocator* blob_allocator; 45 | 46 | // workspace memory allocator 47 | Allocator* workspace_allocator; 48 | 49 | #if NCNN_VULKAN 50 | // blob memory allocator 51 | VkAllocator* blob_vkallocator; 52 | 53 | // workspace memory allocator 54 | VkAllocator* workspace_vkallocator; 55 | 56 | // staging memory allocator 57 | VkAllocator* staging_vkallocator; 58 | #endif // NCNN_VULKAN 59 | 60 | // enable winograd convolution optimization 61 | // improve convolution 3x3 stride1 performace, may consume more memory 62 | // changes should be applied before loading network structure and weight 63 | // enabled by default 64 | bool use_winograd_convolution; 65 | 66 | // enable sgemm convolution optimization 67 | // improve convolution 1x1 stride1 performace, may consume more memory 68 | // changes should be applied before loading network structure and weight 69 | // enabled by default 70 | bool use_sgemm_convolution; 71 | 72 | // enable quantized int8 inference 73 | // use low-precision int8 path for quantized model 74 | // changes should be applied before loading network structure and weight 75 | // enabled by default 76 | bool use_int8_inference; 77 | 78 | // enable vulkan compute 79 | bool use_vulkan_compute; 80 | 81 | // enable options for gpu inference 82 | bool use_fp16_packed; 83 | bool use_fp16_storage; 84 | bool use_fp16_arithmetic; 85 | bool use_int8_storage; 86 | bool use_int8_arithmetic; 87 | }; 88 | 89 | } // namespace ncnn 90 | 91 | #endif // NCNN_OPTION_H 92 | -------------------------------------------------------------------------------- /ncnn/include/paramdict.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_PARAMDICT_H 16 | #define NCNN_PARAMDICT_H 17 | 18 | #include 19 | #include "mat.h" 20 | #include "platform.h" 21 | 22 | // at most 20 parameters 23 | #define NCNN_MAX_PARAM_COUNT 20 24 | 25 | namespace ncnn { 26 | 27 | class Net; 28 | class ParamDict 29 | { 30 | public: 31 | // empty 32 | ParamDict(); 33 | 34 | // get int 35 | int get(int id, int def) const; 36 | // get float 37 | float get(int id, float def) const; 38 | // get array 39 | Mat get(int id, const Mat& def) const; 40 | 41 | // set int 42 | void set(int id, int i); 43 | // set float 44 | void set(int id, float f); 45 | // set array 46 | void set(int id, const Mat& v); 47 | 48 | protected: 49 | friend class Net; 50 | 51 | void clear(); 52 | 53 | #if NCNN_STDIO 54 | #if NCNN_STRING 55 | int load_param(FILE* fp); 56 | int load_param_mem(const char*& mem); 57 | #endif // NCNN_STRING 58 | int load_param_bin(FILE* fp); 59 | #endif // NCNN_STDIO 60 | int load_param(const unsigned char*& mem); 61 | 62 | protected: 63 | struct 64 | { 65 | int loaded; 66 | union { int i; float f; }; 67 | Mat v; 68 | } params[NCNN_MAX_PARAM_COUNT]; 69 | }; 70 | 71 | } // namespace ncnn 72 | 73 | #endif // NCNN_PARAMDICT_H 74 | -------------------------------------------------------------------------------- /ncnn/include/pipeline.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_PIPELINE_H 16 | #define NCNN_PIPELINE_H 17 | 18 | #include "platform.h" 19 | #include "mat.h" 20 | #if NCNN_VULKAN 21 | #include 22 | #include "gpu.h" 23 | #endif // NCNN_VULKAN 24 | 25 | namespace ncnn { 26 | 27 | #if NCNN_VULKAN 28 | class Option; 29 | class Pipeline 30 | { 31 | public: 32 | Pipeline(const VulkanDevice* vkdev); 33 | ~Pipeline(); 34 | 35 | public: 36 | void set_optimal_local_size_xyz(int w = 32, int h = 32, int c = 32); 37 | void set_local_size_xyz(int w, int h, int c); 38 | 39 | int create(const uint32_t* spv_data, size_t spv_data_size, const char* entry_name, 40 | const std::vector& specializations, int binding_count, int push_constant_count); 41 | int create(VkShaderModule shader_module, const char* entry_name, 42 | const std::vector& specializations, int binding_count, int push_constant_count); 43 | int create(const char* name, const Option& opt, const std::vector& specializations, 44 | int binding_count, int push_constant_count); 45 | void destroy(); 46 | 47 | protected: 48 | int create_descriptorset_layout(int binding_count); 49 | int create_pipeline_layout(int push_constant_count); 50 | int create_pipeline(VkShaderModule shader_module, const char* entry_name, const std::vector& specializations); 51 | int create_descriptor_update_template(int binding_count); 52 | 53 | public: 54 | const VulkanDevice* vkdev; 55 | 56 | // local shader module 57 | VkShaderModule local_shader_module; 58 | 59 | VkDescriptorSetLayout descriptorset_layout; 60 | VkPipelineLayout pipeline_layout; 61 | 62 | // op forward TODO use pipeline cache ? 63 | VkPipeline pipeline; 64 | 65 | VkDescriptorUpdateTemplateKHR descriptor_update_template; 66 | 67 | uint32_t local_size_x; 68 | uint32_t local_size_y; 69 | uint32_t local_size_z; 70 | }; 71 | #endif // NCNN_VULKAN 72 | 73 | } // namespace ncnn 74 | 75 | #endif // NCNN_PIPELINE_H 76 | -------------------------------------------------------------------------------- /ncnn/include/platform.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_PLATFORM_H 16 | #define NCNN_PLATFORM_H 17 | 18 | #define NCNN_STDIO 1 19 | #define NCNN_STRING 1 20 | #define NCNN_OPENCV 0 21 | #define NCNN_BENCHMARK 0 22 | #define NCNN_PIXEL 1 23 | #define NCNN_PIXEL_ROTATE 0 24 | #define NCNN_VULKAN 0 25 | #define NCNN_REQUANT 0 26 | #define NCNN_AVX2 0 27 | 28 | #ifdef _WIN32 29 | #define WIN32_LEAN_AND_MEAN 30 | #include 31 | #else 32 | #include 33 | #endif 34 | 35 | namespace ncnn { 36 | 37 | #ifdef _WIN32 38 | class Mutex 39 | { 40 | public: 41 | Mutex() { InitializeSRWLock(&srwlock); } 42 | ~Mutex() {} 43 | void lock() { AcquireSRWLockExclusive(&srwlock); } 44 | void unlock() { ReleaseSRWLockExclusive(&srwlock); } 45 | private: 46 | // NOTE SRWLock is available from windows vista 47 | SRWLOCK srwlock; 48 | }; 49 | #else // _WIN32 50 | class Mutex 51 | { 52 | public: 53 | Mutex() { pthread_mutex_init(&mutex, 0); } 54 | ~Mutex() { pthread_mutex_destroy(&mutex); } 55 | void lock() { pthread_mutex_lock(&mutex); } 56 | void unlock() { pthread_mutex_unlock(&mutex); } 57 | private: 58 | pthread_mutex_t mutex; 59 | }; 60 | #endif // _WIN32 61 | 62 | class MutexLockGuard 63 | { 64 | public: 65 | MutexLockGuard(Mutex& _mutex) : mutex(_mutex) { mutex.lock(); } 66 | ~MutexLockGuard() { mutex.unlock(); } 67 | private: 68 | Mutex& mutex; 69 | }; 70 | 71 | } // namespace ncnn 72 | 73 | #endif // NCNN_PLATFORM_H 74 | -------------------------------------------------------------------------------- /ncnn/lib/libncnn.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/lib/libncnn.a -------------------------------------------------------------------------------- /ncnn/model.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | import torchvision.models as models 6 | import torch 7 | import torch.nn as nn 8 | import os 9 | 10 | from .networks.msra_resnet import get_pose_net 11 | from .networks.dlav0 import get_pose_net as get_dlav0 12 | from .networks.pose_dla_dcn import get_pose_net as get_dla_dcn 13 | from .networks.resnet_dcn import get_pose_net as get_pose_net_dcn 14 | from .networks.large_hourglass import get_large_hourglass_net 15 | from .networks.mobilenetv2 import get_mobile_net 16 | 17 | _model_factory = { 18 | 'res': get_pose_net, # default Resnet with deconv 19 | 'dlav0': get_dlav0, # default DLAup 20 | 'dla': get_dla_dcn, 21 | 'resdcn': get_pose_net_dcn, 22 | 'hourglass': get_large_hourglass_net, 23 | 'mobilenetv2': get_mobile_net, 24 | } 25 | 26 | def create_model(arch, heads, head_conv): 27 | num_layers = int(arch[arch.find('_') + 1:]) if '_' in arch else 0 28 | arch = arch[:arch.find('_')] if '_' in arch else arch 29 | get_model = _model_factory[arch] 30 | model = get_model(num_layers=num_layers, heads=heads, head_conv=head_conv) 31 | return model 32 | 33 | def load_model(model, model_path, optimizer=None, resume=False, 34 | lr=None, lr_step=None): 35 | start_epoch = 0 36 | checkpoint = torch.load(model_path, map_location=lambda storage, loc: storage) 37 | print('loaded {}, epoch {}'.format(model_path, checkpoint['epoch'])) 38 | state_dict_ = checkpoint['state_dict'] 39 | state_dict = {} 40 | 41 | # convert data_parallal to model 42 | for k in state_dict_: 43 | if k.startswith('module') and not k.startswith('module_list'): 44 | state_dict[k[7:]] = state_dict_[k] 45 | else: 46 | state_dict[k] = state_dict_[k] 47 | model_state_dict = model.state_dict() 48 | 49 | # check loaded parameters and created model parameters 50 | msg = 'If you see this, your model does not fully load the ' + \ 51 | 'pre-trained weight. Please make sure ' + \ 52 | 'you have correctly specified --arch xxx ' + \ 53 | 'or set the correct --num_classes for your own dataset.' 54 | for k in state_dict: 55 | if k in model_state_dict: 56 | if state_dict[k].shape != model_state_dict[k].shape: 57 | print('Skip loading parameter {}, required shape{}, '\ 58 | 'loaded shape{}. {}'.format( 59 | k, model_state_dict[k].shape, state_dict[k].shape, msg)) 60 | state_dict[k] = model_state_dict[k] 61 | else: 62 | print('Drop parameter {}.'.format(k) + msg) 63 | for k in model_state_dict: 64 | if not (k in state_dict): 65 | print('No param {}.'.format(k) + msg) 66 | state_dict[k] = model_state_dict[k] 67 | model.load_state_dict(state_dict, strict=False) 68 | 69 | # resume optimizer parameters 70 | if optimizer is not None and resume: 71 | if 'optimizer' in checkpoint: 72 | optimizer.load_state_dict(checkpoint['optimizer']) 73 | start_epoch = checkpoint['epoch'] 74 | start_lr = lr 75 | for step in lr_step: 76 | if start_epoch >= step: 77 | start_lr *= 0.1 78 | for param_group in optimizer.param_groups: 79 | param_group['lr'] = start_lr 80 | print('Resumed optimizer with start lr', start_lr) 81 | else: 82 | print('No optimizer parameters in checkpoint.') 83 | if optimizer is not None: 84 | return model, optimizer, start_epoch 85 | else: 86 | return model 87 | 88 | def save_model(path, epoch, model, optimizer=None): 89 | if isinstance(model, torch.nn.DataParallel): 90 | state_dict = model.module.state_dict() 91 | else: 92 | state_dict = model.state_dict() 93 | data = {'epoch': epoch, 94 | 'state_dict': state_dict} 95 | if not (optimizer is None): 96 | data['optimizer'] = optimizer.state_dict() 97 | torch.save(data, path) 98 | 99 | -------------------------------------------------------------------------------- /ncnn/models/bus_face/centernet_mbv2.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/models/bus_face/centernet_mbv2.bin -------------------------------------------------------------------------------- /ncnn/models/bus_face/res18.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/models/bus_face/res18.bin -------------------------------------------------------------------------------- /ncnn/models/voc/centernet_mbv2.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/models/voc/centernet_mbv2.bin -------------------------------------------------------------------------------- /ncnn/plane.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/plane.jpg -------------------------------------------------------------------------------- /ncnn/plate/centernet_mbv2.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/plate/centernet_mbv2.bin -------------------------------------------------------------------------------- /ncnn/plate/centernet_mbv2.onnx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/plate/centernet_mbv2.onnx -------------------------------------------------------------------------------- /ncnn/plate/model_best.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/plate/model_best.pth -------------------------------------------------------------------------------- /ncnn/result.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/ncnn/result.jpg -------------------------------------------------------------------------------- /readme/DATA.md: -------------------------------------------------------------------------------- 1 | # Dataset preparation 2 | 3 | If you want to reproduce the results in the paper for benchmark evaluation and training, you will need to setup dataset. 4 | 5 | 6 | ### COCO 7 | - Download the images (2017 Train, 2017 Val, 2017 Test) from [coco website](http://cocodataset.org/#download). 8 | - Download annotation files (2017 train/val and test image info) from [coco website](http://cocodataset.org/#download). 9 | - Place the data (or create symlinks) to make the data folder like: 10 | 11 | ~~~ 12 | ${CenterNet_ROOT} 13 | |-- data 14 | `-- |-- coco 15 | `-- |-- annotations 16 | | |-- instances_train2017.json 17 | | |-- instances_val2017.json 18 | | |-- person_keypoints_train2017.json 19 | | |-- person_keypoints_val2017.json 20 | | |-- image_info_test-dev2017.json 21 | |---|-- train2017 22 | |---|-- val2017 23 | `---|-- test2017 24 | ~~~ 25 | 26 | - [Optional] If you want to train ExtremeNet, generate extreme point annotation from segmentation: 27 | 28 | ~~~ 29 | cd $CenterNet_ROOT/tools/ 30 | python gen_coco_extreme_points.py 31 | ~~~ 32 | It generates `instances_extreme_train2017.json` and `instances_extreme_val2017.json` in `data/coco/annotations/`. 33 | 34 | ### Pascal VOC 35 | 36 | - Run 37 | 38 | ~~~ 39 | cd $CenterNet_ROOT/tools/ 40 | bash get_pascal_voc.sh 41 | ~~~ 42 | - The above script includes: 43 | - Download, unzip, and move Pascal VOC images from the [VOC website](http://host.robots.ox.ac.uk/pascal/VOC/). 44 | - [Download](https://storage.googleapis.com/coco-dataset/external/PASCAL_VOC.zip) Pascal VOC annotation in COCO format (from [Detectron](https://github.com/facebookresearch/Detectron/tree/master/detectron/datasets/data)). 45 | - Combine train/val 2007/2012 annotation files into a single json. 46 | 47 | 48 | - Move the created `voc` folder to `data` (or create symlinks) to make the data folder like: 49 | 50 | ~~~ 51 | ${CenterNet_ROOT} 52 | |-- data 53 | `-- |-- voc 54 | `-- |-- annotations 55 | | |-- pascal_trainval0712.json 56 | | |-- pascal_test2017.json 57 | |-- images 58 | | |-- 000001.jpg 59 | | ...... 60 | `-- VOCdevkit 61 | 62 | ~~~ 63 | The `VOCdevkit` folder is needed to run the evaluation script from [faster rcnn](https://github.com/rbgirshick/py-faster-rcnn/blob/master/tools/reval.py). 64 | 65 | ### KITTI 66 | 67 | - Download [images](http://www.cvlibs.net/download.php?file=data_object_image_2.zip), [annotations](http://www.cvlibs.net/download.php?file=data_object_label_2.zip), and [calibrations](http://www.cvlibs.net/download.php?file=data_object_calib.zip) from [KITTI website](http://www.cvlibs.net/datasets/kitti/eval_object.php?obj_benchmark=3d) and unzip. 68 | 69 | - Download the train-val split of [3DOP](https://xiaozhichen.github.io/files/mv3d/imagesets.tar.gz) and [SubCNN](https://github.com/tanshen/SubCNN/tree/master/fast-rcnn/data/KITTI) and place the data as below 70 | 71 | ~~~ 72 | ${CenterNet_ROOT} 73 | |-- data 74 | `-- |-- kitti 75 | `-- |-- training 76 | | |-- image_2 77 | | |-- label_2 78 | | |-- calib 79 | |-- ImageSets_3dop 80 | | |-- test.txt 81 | | |-- train.txt 82 | | |-- val.txt 83 | | |-- trainval.txt 84 | `-- ImageSets_subcnn 85 | |-- test.txt 86 | |-- train.txt 87 | |-- val.txt 88 | |-- trainval.txt 89 | ~~~ 90 | 91 | - Run `python convert_kitti_to_coco.py` in `tools` to convert the annotation into COCO format. You can set `DEBUG=True` in `line 5` to visualize the annotation. 92 | 93 | - Link image folder 94 | 95 | ~~~ 96 | cd ${CenterNet_ROOT}/data/kitti/ 97 | mkdir images 98 | ln -s training/image_2 images/trainval 99 | ~~~ 100 | 101 | - The data structure should look like: 102 | 103 | ~~~ 104 | ${CenterNet_ROOT} 105 | |-- data 106 | `-- |-- kitti 107 | `-- |-- annotations 108 | | |-- kitti_3dop_train.json 109 | | |-- kitti_3dop_val.json 110 | | |-- kitti_subcnn_train.json 111 | | |-- kitti_subcnn_val.json 112 | `-- images 113 | |-- trainval 114 | |-- test 115 | ~~~ 116 | -------------------------------------------------------------------------------- /readme/DEVELOP.md: -------------------------------------------------------------------------------- 1 | # Develop 2 | 3 | This document provides tutorials to develop CenterNet. `lib/src/opts` lists a few more options that the current version supports. 4 | 5 | ## New dataset 6 | Basically there are three steps: 7 | 8 | - Convert the dataset annotation to [COCO format](http://cocodataset.org/#format-data). Please refer to [src/tools/convert_kitti_to_coco.py](../src/tools/convert_kitti_to_coco.py) for an example to convert kitti format to coco format. 9 | - Create a dataset intilization file in `src/lib/datasets/dataset`. In most cases you can just copy `src/lib/datasets/dataset/coco.py` to your dataset name and change the category information, and annotation path. 10 | - Import your dataset at `src/lib/datasets/dataset_factory`. 11 | 12 | ## New task 13 | 14 | You will need to add files to `src/lib/datasets/sample/`, `src/lib/datasets/trains/`, and `src/lib/datasets/detectors/`, which specify the data generation during training, the training targets, and the testing, respectively. 15 | 16 | ## New architecture 17 | 18 | - Add your model file to `src/lib/models/networks/`. The model should accept a dict `heads` of `{name: channels}`, which specify the name of each network output and its number of channels. Make sure your model returns a list (for multiple stages. Single stage model should return a list containing a single element.). The element of the list is a dict contraining the same keys with `heads`. 19 | - Add your model in `model_factory` of `src/lib/models/model.py`. 20 | -------------------------------------------------------------------------------- /readme/GETTING_STARTED.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | This document provides tutorials to train and evaluate CenterNet. Before getting started, make sure you have finished [installation](INSTALL.md) and [dataset setup](DATA.md). 4 | 5 | ## Benchmark evaluation 6 | 7 | First, download the models you want to evaluate from our [model zoo](MODEL_ZOO.md) and put them in `CenterNet_ROOT/models/`. 8 | 9 | ### COCO 10 | 11 | To evaluate COCO object detection with DLA 12 | run 13 | 14 | ~~~ 15 | python test.py ctdet --exp_id coco_dla --keep_res --load_model ../models/ctdet_coco_dla_2x.pth 16 | ~~~ 17 | 18 | This will give an AP of `37.4` if setup correctly. `--keep_res` is for keep the original image resolution. Without `--keep_res` it will resize the images to `512 x 512`. You can add `--flip_test` and `--flip_test --test_scales 0.5,0.75,1,1.25,1.5` to the above commend, for flip test and multi_scale test, respectively. The expected APs are `39.2` and `41.7`, respectively. 19 | 20 | To test with hourglass net, run 21 | 22 | ~~~ 23 | python test.py ctdet --exp_id coco_hg --arch hourglass --fix_res --load_model ../models/ctdet_coco_hg.pth 24 | ~~~ 25 | 26 | Similarly, to evaluate human pose estimation, run the following command for dla 27 | 28 | ~~~ 29 | python test.py multi_pose --exp_id dla --keep_res --load_model ../models/multi_pose_dla_3x.pth --flip_test 30 | ~~~ 31 | 32 | and the following for hourglass 33 | 34 | ~~~ 35 | python test.py multi_pose --exp_id hg --arch hourglass --keep_res --load_model ../models/multi_pose_dla_3x.pth --flip_test 36 | ~~~ 37 | 38 | The expected results can be found in the model zoo. 39 | 40 | ### Pascal 41 | 42 | To evaluate object detection on Pascal VOC (test2007), run 43 | 44 | ~~~ 45 | python test.py ctdet --exp_id dla --dataset pascal --load_model ../models/ctdet_pascal_dla.pth --flip_test 46 | ~~~ 47 | 48 | Note that we fix the resolution during testing. 49 | And you can change to other network architectures and resolutions by specifying `--arch` and `--input_res 512`. 50 | 51 | ### KITTI 52 | 53 | To evaluate the kitti dataset, first compile the evaluation tool (from [here](https://github.com/prclibo/kitti_eval)): 54 | 55 | ~~~ 56 | cd CenterNet_ROOT/src/tools/kitti_eval 57 | g++ -o evaluate_object_3d_offline evaluate_object_3d_offline.cpp -O3 58 | ~~~ 59 | 60 | Then run the evaluation with pretrained model: 61 | 62 | ~~~ 63 | python test.py ddd --exp_id 3dop --dataset kitti --kitti_split 3dop --load_model ../models/ddd_3dop.pth 64 | ~~~ 65 | 66 | to evaluate the 3DOP split. For the subcnn split, change `--kitti_split` to `subcnn` and load the corresponding models. 67 | Note that test time augmentation is not trivially applicable for 3D orientation. 68 | 69 | ## Training 70 | 71 | We have packed all the training scripts in the [experiments](../experiments) folder. 72 | The experiment names are correspond to the model name in the [model zoo](MODEL_ZOO.md). 73 | The number of GPUs for each experiments can be found in the scripts and the model zoo. 74 | In the case that you don't have 8 GPUs, you can follow the [linear learning rate rule](https://arxiv.org/abs/1706.02677) to scale the learning rate as batch size. 75 | For example, to train COCO object detection with dla on 2 GPUs, run 76 | 77 | ~~~ 78 | python main.py ctdet --exp_id coco_dla --batch_size 32 --master_batch 15 --lr 1.25e-4 --gpus 0,1 79 | ~~~ 80 | 81 | The default learning rate is `1.25e-4` for batch size `32` (on 2 GPUs). 82 | By default, pytorch evenly splits the total batch size to each GPUs. 83 | `--master_batch` allows using different batchsize for the master GPU, which usually costs more memory than other GPUs. 84 | If it encounters GPU memory out, using slightly less batch size (e.g., `112` of `128`) with the same learning is fine. 85 | 86 | If the training is terminated before finishing, you can use the same commond with `--resume` to resume training. It will found the lastest model with the same `exp_id`. 87 | 88 | Our HourglassNet model is finetuned from the pretrained [ExtremeNet model](https://drive.google.com/file/d/1omiOUjWCrFbTJREypuZaODu0bOlF_7Fg/view?usp=sharing) (from the [ExtremeNet repo](https://github.com/xingyizhou/ExtremeNet)). 89 | You will need to download the model, run `python convert_hourglass_weight.py` to convert the model format, and load the model for training (see the [script](../experiments/ctdet_coco_hg.sh)). 90 | -------------------------------------------------------------------------------- /readme/INSTALL.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | 4 | The code was tested on Ubuntu 16.04, with [Anaconda](https://www.anaconda.com/download) Python 3.6 and [PyTorch]((http://pytorch.org/)) v0.4.1. NVIDIA GPUs are needed for both training and testing. 5 | After install Anaconda: 6 | 7 | 0. [Optional but recommended] create a new conda environment. 8 | 9 | ~~~ 10 | conda create --name CenterNet python=3.6 11 | ~~~ 12 | And activate the environment. 13 | 14 | ~~~ 15 | conda activate CenterNet 16 | ~~~ 17 | 18 | 1. Install pytorch0.4.1: 19 | 20 | ~~~ 21 | conda install pytorch=0.4.1 torchvision -c pytorch 22 | ~~~ 23 | 24 | And disable cudnn batch normalization(Due to [this issue](https://github.com/xingyizhou/pytorch-pose-hg-3d/issues/16)). 25 | 26 | ~~~ 27 | # PYTORCH=/path/to/pytorch # usually ~/anaconda3/envs/CenterNet/lib/python3.6/site-packages/ 28 | # for pytorch v0.4.0 29 | sed -i "1194s/torch\.backends\.cudnn\.enabled/False/g" ${PYTORCH}/torch/nn/functional.py 30 | # for pytorch v0.4.1 31 | sed -i "1254s/torch\.backends\.cudnn\.enabled/False/g" ${PYTORCH}/torch/nn/functional.py 32 | ~~~ 33 | 34 | For other pytorch version, you can manually open `torch/nn/functional.py` and find the line with `torch.batch_norm` and replace the `torch.backends.cudnn.enabled` with `False`. We observed slight worse training results without doing so. 35 | 36 | 2. Install [COCOAPI](https://github.com/cocodataset/cocoapi): 37 | 38 | ~~~ 39 | # COCOAPI=/path/to/clone/cocoapi 40 | git clone https://github.com/cocodataset/cocoapi.git $COCOAPI 41 | cd $COCOAPI/PythonAPI 42 | make 43 | python setup.py install --user 44 | ~~~ 45 | 46 | 3. Clone this repo: 47 | 48 | ~~~ 49 | CenterNet_ROOT=/path/to/clone/CenterNet 50 | git clone https://github.com/xingyizhou/CenterNet $CenterNet_ROOT 51 | ~~~ 52 | 53 | 54 | 4. Install the requirements 55 | 56 | ~~~ 57 | pip install -r requirements.txt 58 | ~~~ 59 | 60 | 61 | 5. Compile deformable convolutional (from [DCNv2](https://github.com/CharlesShang/DCNv2/tree/pytorch_0.4)). 62 | 63 | ~~~ 64 | cd $CenterNet_ROOT/src/lib/models/networks/DCNv2 65 | ./make.sh 66 | ~~~ 67 | 6. [Optional, only required if you are using extremenet or multi-scale testing] Compile NMS if your want to use multi-scale testing or test ExtremeNet. 68 | 69 | ~~~ 70 | cd $CenterNet_ROOT/src/lib/external 71 | make 72 | ~~~ 73 | 74 | 7. Download pertained models for [detection]() or [pose estimation]() and move them to `$CenterNet_ROOT/models/`. More models can be found in [Model zoo](MODEL_ZOO.md). 75 | -------------------------------------------------------------------------------- /readme/det1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/readme/det1.png -------------------------------------------------------------------------------- /readme/det2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/readme/det2.png -------------------------------------------------------------------------------- /readme/fig2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/readme/fig2.png -------------------------------------------------------------------------------- /readme/pose1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/readme/pose1.png -------------------------------------------------------------------------------- /readme/pose2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/readme/pose2.png -------------------------------------------------------------------------------- /readme/pose3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/readme/pose3.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | opencv-python 2 | Cython 3 | numba 4 | progress 5 | matplotlib 6 | easydict 7 | scipy 8 | -------------------------------------------------------------------------------- /src/__pycache__/_init_paths.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/__pycache__/_init_paths.cpython-36.pyc -------------------------------------------------------------------------------- /src/_init_paths.py: -------------------------------------------------------------------------------- 1 | import os.path as osp 2 | import sys 3 | 4 | def add_path(path): 5 | if path not in sys.path: 6 | sys.path.insert(0, path) 7 | 8 | this_dir = osp.dirname(__file__) 9 | 10 | # Add lib to PYTHONPATH 11 | lib_path = osp.join(this_dir, 'lib') 12 | add_path(lib_path) 13 | -------------------------------------------------------------------------------- /src/_init_paths.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/_init_paths.pyc -------------------------------------------------------------------------------- /src/demo.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | import _init_paths 6 | 7 | import os 8 | import cv2 9 | 10 | from opts import opts 11 | from detectors.detector_factory import detector_factory 12 | 13 | image_ext = ['jpg', 'jpeg', 'png', 'webp'] 14 | video_ext = ['mp4', 'mov', 'avi', 'mkv'] 15 | time_stats = ['tot', 'load', 'pre', 'net', 'dec', 'post', 'merge'] 16 | 17 | def demo(opt): 18 | os.environ['CUDA_VISIBLE_DEVICES'] = opt.gpus_str 19 | opt.debug = max(opt.debug, 1) 20 | Detector = detector_factory[opt.task] 21 | detector = Detector(opt) 22 | 23 | if opt.demo == 'webcam' or \ 24 | opt.demo[opt.demo.rfind('.') + 1:].lower() in video_ext: 25 | cam = cv2.VideoCapture(0 if opt.demo == 'webcam' else opt.demo) 26 | detector.pause = False 27 | while True: 28 | _, img = cam.read() 29 | cv2.imshow('input', img) 30 | ret = detector.run(img) 31 | time_str = '' 32 | for stat in time_stats: 33 | time_str = time_str + '{} {:.3f}s |'.format(stat, ret[stat]) 34 | print(time_str) 35 | if cv2.waitKey(1) == 27: 36 | return # esc to quit 37 | else: 38 | if os.path.isdir(opt.demo): 39 | image_names = [] 40 | ls = os.listdir(opt.demo) 41 | for file_name in sorted(ls): 42 | ext = file_name[file_name.rfind('.') + 1:].lower() 43 | if ext in image_ext: 44 | image_names.append(os.path.join(opt.demo, file_name)) 45 | else: 46 | image_names = [opt.demo] 47 | 48 | for (image_name) in image_names: 49 | ret = detector.run(image_name) 50 | time_str = '' 51 | for stat in time_stats: 52 | time_str = time_str + '{} {:.3f}s |'.format(stat, ret[stat]) 53 | print(time_str) 54 | if __name__ == '__main__': 55 | opt = opts().init() 56 | demo(opt) 57 | -------------------------------------------------------------------------------- /src/lib/__pycache__/logger.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/__pycache__/logger.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/__pycache__/opts.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/__pycache__/opts.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/datasets/__pycache__/dataset_factory.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/datasets/__pycache__/dataset_factory.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/datasets/dataset/__pycache__/coco.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/datasets/dataset/__pycache__/coco.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/datasets/dataset/__pycache__/coco_hp.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/datasets/dataset/__pycache__/coco_hp.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/datasets/dataset/__pycache__/face.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/datasets/dataset/__pycache__/face.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/datasets/dataset/__pycache__/kitti.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/datasets/dataset/__pycache__/kitti.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/datasets/dataset/__pycache__/pascal.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/datasets/dataset/__pycache__/pascal.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/datasets/dataset/coco_hp.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | import pycocotools.coco as coco 6 | from pycocotools.cocoeval import COCOeval 7 | import numpy as np 8 | import json 9 | import os 10 | 11 | import torch.utils.data as data 12 | 13 | class COCOHP(data.Dataset): 14 | num_classes = 1 15 | num_joints = 17 16 | default_resolution = [512, 512] 17 | mean = np.array([0.40789654, 0.44719302, 0.47026115], 18 | dtype=np.float32).reshape(1, 1, 3) 19 | std = np.array([0.28863828, 0.27408164, 0.27809835], 20 | dtype=np.float32).reshape(1, 1, 3) 21 | flip_idx = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], 22 | [11, 12], [13, 14], [15, 16]] 23 | def __init__(self, opt, split): 24 | super(COCOHP, self).__init__() 25 | self.edges = [[0, 1], [0, 2], [1, 3], [2, 4], 26 | [4, 6], [3, 5], [5, 6], 27 | [5, 7], [7, 9], [6, 8], [8, 10], 28 | [6, 12], [5, 11], [11, 12], 29 | [12, 14], [14, 16], [11, 13], [13, 15]] 30 | 31 | self.acc_idxs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] 32 | self.data_dir = os.path.join(opt.data_dir, 'coco') 33 | self.img_dir = os.path.join(self.data_dir, '{}2017'.format(split)) 34 | if split == 'test': 35 | self.annot_path = os.path.join( 36 | self.data_dir, 'annotations', 37 | 'image_info_test-dev2017.json').format(split) 38 | else: 39 | self.annot_path = os.path.join( 40 | self.data_dir, 'annotations', 41 | 'person_keypoints_{}2017.json').format(split) 42 | self.max_objs = 32 43 | self._data_rng = np.random.RandomState(123) 44 | self._eig_val = np.array([0.2141788, 0.01817699, 0.00341571], 45 | dtype=np.float32) 46 | self._eig_vec = np.array([ 47 | [-0.58752847, -0.69563484, 0.41340352], 48 | [-0.5832747, 0.00994535, -0.81221408], 49 | [-0.56089297, 0.71832671, 0.41158938] 50 | ], dtype=np.float32) 51 | self.split = split 52 | self.opt = opt 53 | 54 | print('==> initializing coco 2017 {} data.'.format(split)) 55 | self.coco = coco.COCO(self.annot_path) 56 | image_ids = self.coco.getImgIds() 57 | 58 | if split == 'train': 59 | self.images = [] 60 | for img_id in image_ids: 61 | idxs = self.coco.getAnnIds(imgIds=[img_id]) 62 | if len(idxs) > 0: 63 | self.images.append(img_id) 64 | else: 65 | self.images = image_ids 66 | self.num_samples = len(self.images) 67 | print('Loaded {} {} samples'.format(split, self.num_samples)) 68 | 69 | def _to_float(self, x): 70 | return float("{:.2f}".format(x)) 71 | 72 | def convert_eval_format(self, all_bboxes): 73 | # import pdb; pdb.set_trace() 74 | detections = [] 75 | for image_id in all_bboxes: 76 | for cls_ind in all_bboxes[image_id]: 77 | category_id = 1 78 | for dets in all_bboxes[image_id][cls_ind]: 79 | bbox = dets[:4] 80 | bbox[2] -= bbox[0] 81 | bbox[3] -= bbox[1] 82 | score = dets[4] 83 | bbox_out = list(map(self._to_float, bbox)) 84 | keypoints = np.concatenate([ 85 | np.array(dets[5:39], dtype=np.float32).reshape(-1, 2), 86 | np.ones((17, 1), dtype=np.float32)], axis=1).reshape(51).tolist() 87 | keypoints = list(map(self._to_float, keypoints)) 88 | 89 | detection = { 90 | "image_id": int(image_id), 91 | "category_id": int(category_id), 92 | "bbox": bbox_out, 93 | "score": float("{:.2f}".format(score)), 94 | "keypoints": keypoints 95 | } 96 | detections.append(detection) 97 | return detections 98 | 99 | def __len__(self): 100 | return self.num_samples 101 | 102 | def save_results(self, results, save_dir): 103 | json.dump(self.convert_eval_format(results), 104 | open('{}/results.json'.format(save_dir), 'w')) 105 | 106 | 107 | def run_eval(self, results, save_dir): 108 | # result_json = os.path.join(opt.save_dir, "results.json") 109 | # detections = convert_eval_format(all_boxes) 110 | # json.dump(detections, open(result_json, "w")) 111 | self.save_results(results, save_dir) 112 | coco_dets = self.coco.loadRes('{}/results.json'.format(save_dir)) 113 | coco_eval = COCOeval(self.coco, coco_dets, "keypoints") 114 | coco_eval.evaluate() 115 | coco_eval.accumulate() 116 | coco_eval.summarize() 117 | coco_eval = COCOeval(self.coco, coco_dets, "bbox") 118 | coco_eval.evaluate() 119 | coco_eval.accumulate() 120 | coco_eval.summarize() -------------------------------------------------------------------------------- /src/lib/datasets/dataset/face.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | import pycocotools.coco as coco 6 | from pycocotools.cocoeval import COCOeval 7 | import numpy as np 8 | import json 9 | import os 10 | 11 | import torch.utils.data as data 12 | 13 | class Face(data.Dataset): 14 | num_classes = 1 15 | default_resolution = [512, 512] 16 | mean = np.array([0.40789654, 0.44719302, 0.47026115], 17 | dtype=np.float32).reshape(1, 1, 3) 18 | std = np.array([0.28863828, 0.27408164, 0.27809835], 19 | dtype=np.float32).reshape(1, 1, 3) 20 | 21 | def __init__(self, opt, split): 22 | super(Face, self).__init__() 23 | # self.data_dir = os.path.join(opt.data_dir, 'coco') 24 | # self.img_dir = os.path.join(self.data_dir, '{}2017'.format(split)) 25 | self.data_dir = os.path.join(opt.data_dir, 'bus_face') 26 | self.img_dir = os.path.join(self.data_dir, 'JPEGImages') 27 | if split == 'val': 28 | self.annot_path = os.path.join( 29 | self.data_dir, 'val.json') 30 | else: 31 | if opt.task == 'exdet': 32 | self.annot_path = os.path.join( 33 | self.data_dir, 'train.json') 34 | else: 35 | self.annot_path = os.path.join( 36 | self.data_dir, 'train.json') 37 | self.max_objs = 128 38 | self.class_name = [ 39 | '__background__', 'rgb_face'] 40 | self._valid_ids = [ 41 | 1, 2] 42 | self.cat_ids = {v: i for i, v in enumerate(self._valid_ids)} 43 | self.voc_color = [(v // 32 * 64 + 64, (v // 8) % 4 * 64, v % 8 * 32) \ 44 | for v in range(1, self.num_classes + 1)] 45 | self._data_rng = np.random.RandomState(123) 46 | self._eig_val = np.array([0.2141788, 0.01817699, 0.00341571], 47 | dtype=np.float32) 48 | self._eig_vec = np.array([ 49 | [-0.58752847, -0.69563484, 0.41340352], 50 | [-0.5832747, 0.00994535, -0.81221408], 51 | [-0.56089297, 0.71832671, 0.41158938] 52 | ], dtype=np.float32) 53 | # self.mean = np.array([0.485, 0.456, 0.406], np.float32).reshape(1, 1, 3) 54 | # self.std = np.array([0.229, 0.224, 0.225], np.float32).reshape(1, 1, 3) 55 | 56 | self.split = split 57 | self.opt = opt 58 | 59 | print('==> initializing coco 2017 {} data.'.format(split)) 60 | self.coco = coco.COCO(self.annot_path) 61 | self.images = self.coco.getImgIds() 62 | self.num_samples = len(self.images) 63 | 64 | print('Loaded {} {} samples'.format(split, self.num_samples)) 65 | 66 | def _to_float(self, x): 67 | return float("{:.2f}".format(x)) 68 | 69 | def convert_eval_format(self, all_bboxes): 70 | # import pdb; pdb.set_trace() 71 | detections = [] 72 | for image_id in all_bboxes: 73 | for cls_ind in all_bboxes[image_id]: 74 | category_id = self._valid_ids[cls_ind - 1] 75 | for bbox in all_bboxes[image_id][cls_ind]: 76 | bbox[2] -= bbox[0] 77 | bbox[3] -= bbox[1] 78 | score = bbox[4] 79 | bbox_out = list(map(self._to_float, bbox[0:4])) 80 | 81 | detection = { 82 | "image_id": int(image_id), 83 | "category_id": int(category_id), 84 | "bbox": bbox_out, 85 | "score": float("{:.2f}".format(score)) 86 | } 87 | if len(bbox) > 5: 88 | extreme_points = list(map(self._to_float, bbox[5:13])) 89 | detection["extreme_points"] = extreme_points 90 | detections.append(detection) 91 | return detections 92 | 93 | def __len__(self): 94 | return self.num_samples 95 | 96 | def save_results(self, results, save_dir): 97 | json.dump(self.convert_eval_format(results), 98 | open('{}/results.json'.format(save_dir), 'w')) 99 | 100 | def run_eval(self, results, save_dir): 101 | # result_json = os.path.join(save_dir, "results.json") 102 | # detections = self.convert_eval_format(results) 103 | # json.dump(detections, open(result_json, "w")) 104 | self.save_results(results, save_dir) 105 | coco_dets = self.coco.loadRes('{}/results.json'.format(save_dir)) 106 | coco_eval = COCOeval(self.coco, coco_dets, "bbox") 107 | coco_eval.evaluate() 108 | coco_eval.accumulate() 109 | coco_eval.summarize() 110 | -------------------------------------------------------------------------------- /src/lib/datasets/dataset/kitti.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | import torch.utils.data as data 6 | import pycocotools.coco as coco 7 | import numpy as np 8 | import torch 9 | import json 10 | import cv2 11 | import os 12 | import math 13 | 14 | import torch.utils.data as data 15 | 16 | 17 | class KITTI(data.Dataset): 18 | num_classes = 3 19 | default_resolution = [384, 1280] 20 | mean = np.array([0.485, 0.456, 0.406], np.float32).reshape(1, 1, 3) 21 | std = np.array([0.229, 0.224, 0.225], np.float32).reshape(1, 1, 3) 22 | 23 | def __init__(self, opt, split): 24 | super(KITTI, self).__init__() 25 | self.data_dir = os.path.join(opt.data_dir, 'kitti') 26 | self.img_dir = os.path.join(self.data_dir, 'images', 'trainval') 27 | if opt.trainval: 28 | split = 'trainval' if split == 'train' else 'test' 29 | self.img_dir = os.path.join(self.data_dir, 'images', split) 30 | self.annot_path = os.path.join( 31 | self.data_dir, 'annotations', 'kitti_{}.json').format(split) 32 | else: 33 | self.annot_path = os.path.join(self.data_dir, 34 | 'annotations', 'kitti_{}_{}.json').format(opt.kitti_split, split) 35 | self.max_objs = 50 36 | self.class_name = [ 37 | '__background__', 'Pedestrian', 'Car', 'Cyclist'] 38 | self.cat_ids = {1:0, 2:1, 3:2, 4:-3, 5:-3, 6:-2, 7:-99, 8:-99, 9:-1} 39 | 40 | self._data_rng = np.random.RandomState(123) 41 | self._eig_val = np.array([0.2141788, 0.01817699, 0.00341571], 42 | dtype=np.float32) 43 | self._eig_vec = np.array([ 44 | [-0.58752847, -0.69563484, 0.41340352], 45 | [-0.5832747, 0.00994535, -0.81221408], 46 | [-0.56089297, 0.71832671, 0.41158938] 47 | ], dtype=np.float32) 48 | self.split = split 49 | self.opt = opt 50 | self.alpha_in_degree = False 51 | 52 | print('==> initializing kitti {}, {} data.'.format(opt.kitti_split, split)) 53 | self.coco = coco.COCO(self.annot_path) 54 | self.images = self.coco.getImgIds() 55 | self.num_samples = len(self.images) 56 | 57 | print('Loaded {} {} samples'.format(split, self.num_samples)) 58 | 59 | def __len__(self): 60 | return self.num_samples 61 | 62 | def _to_float(self, x): 63 | return float("{:.2f}".format(x)) 64 | 65 | def convert_eval_format(self, all_bboxes): 66 | pass 67 | 68 | def save_results(self, results, save_dir): 69 | results_dir = os.path.join(save_dir, 'results') 70 | if not os.path.exists(results_dir): 71 | os.mkdir(results_dir) 72 | for img_id in results.keys(): 73 | out_path = os.path.join(results_dir, '{:06d}.txt'.format(img_id)) 74 | f = open(out_path, 'w') 75 | for cls_ind in results[img_id]: 76 | for j in range(len(results[img_id][cls_ind])): 77 | class_name = self.class_name[cls_ind] 78 | f.write('{} 0.0 0'.format(class_name)) 79 | for i in range(len(results[img_id][cls_ind][j])): 80 | f.write(' {:.2f}'.format(results[img_id][cls_ind][j][i])) 81 | f.write('\n') 82 | f.close() 83 | 84 | def run_eval(self, results, save_dir): 85 | self.save_results(results, save_dir) 86 | os.system('./tools/kitti_eval/evaluate_object_3d_offline ' + \ 87 | '../data/kitti/training/label_val ' + \ 88 | '{}/results/'.format(save_dir)) 89 | 90 | -------------------------------------------------------------------------------- /src/lib/datasets/dataset/pascal.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | import pycocotools.coco as coco 6 | import numpy as np 7 | import torch 8 | import json 9 | import os 10 | 11 | import torch.utils.data as data 12 | 13 | class PascalVOC(data.Dataset): 14 | num_classes = 20 15 | default_resolution = [384, 384] 16 | mean = np.array([0.485, 0.456, 0.406], 17 | dtype=np.float32).reshape(1, 1, 3) 18 | std = np.array([0.229, 0.224, 0.225], 19 | dtype=np.float32).reshape(1, 1, 3) 20 | 21 | def __init__(self, opt, split): 22 | super(PascalVOC, self).__init__() 23 | self.data_dir = os.path.join(opt.data_dir, 'voc') 24 | self.img_dir = os.path.join(self.data_dir, 'images') 25 | _ann_name = {'train': 'trainval0712', 'val': 'test2007'} 26 | self.annot_path = os.path.join( 27 | self.data_dir, 'annotations', 28 | 'pascal_{}.json').format(_ann_name[split]) 29 | self.max_objs = 50 30 | self.class_name = ['__background__', "aeroplane", "bicycle", "bird", "boat", 31 | "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog", 32 | "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", 33 | "train", "tvmonitor"] 34 | self._valid_ids = np.arange(1, 21, dtype=np.int32) 35 | self.cat_ids = {v: i for i, v in enumerate(self._valid_ids)} 36 | self._data_rng = np.random.RandomState(123) 37 | self._eig_val = np.array([0.2141788, 0.01817699, 0.00341571], 38 | dtype=np.float32) 39 | self._eig_vec = np.array([ 40 | [-0.58752847, -0.69563484, 0.41340352], 41 | [-0.5832747, 0.00994535, -0.81221408], 42 | [-0.56089297, 0.71832671, 0.41158938] 43 | ], dtype=np.float32) 44 | self.split = split 45 | self.opt = opt 46 | 47 | print('==> initializing pascal {} data.'.format(_ann_name[split])) 48 | self.coco = coco.COCO(self.annot_path) 49 | self.images = sorted(self.coco.getImgIds()) 50 | self.num_samples = len(self.images) 51 | 52 | print('Loaded {} {} samples'.format(split, self.num_samples)) 53 | 54 | def _to_float(self, x): 55 | return float("{:.2f}".format(x)) 56 | 57 | def convert_eval_format(self, all_bboxes): 58 | detections = [[[] for __ in range(self.num_samples)] \ 59 | for _ in range(self.num_classes + 1)] 60 | for i in range(self.num_samples): 61 | img_id = self.images[i] 62 | for j in range(1, self.num_classes + 1): 63 | if isinstance(all_bboxes[img_id][j], np.ndarray): 64 | detections[j][i] = all_bboxes[img_id][j].tolist() 65 | else: 66 | detections[j][i] = all_bboxes[img_id][j] 67 | return detections 68 | 69 | def __len__(self): 70 | return self.num_samples 71 | 72 | def save_results(self, results, save_dir): 73 | json.dump(self.convert_eval_format(results), 74 | open('{}/results.json'.format(save_dir), 'w')) 75 | 76 | def run_eval(self, results, save_dir): 77 | # result_json = os.path.join(save_dir, "results.json") 78 | # detections = self.convert_eval_format(results) 79 | # json.dump(detections, open(result_json, "w")) 80 | self.save_results(results, save_dir) 81 | os.system('python tools/reval.py ' + \ 82 | '{}/results.json'.format(save_dir)) 83 | -------------------------------------------------------------------------------- /src/lib/datasets/dataset_factory.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | from .sample.ddd import DddDataset 6 | from .sample.exdet import EXDetDataset 7 | from .sample.ctdet import CTDetDataset 8 | from .sample.multi_pose import MultiPoseDataset 9 | 10 | from .dataset.coco import COCO 11 | from .dataset.pascal import PascalVOC 12 | from .dataset.kitti import KITTI 13 | from .dataset.coco_hp import COCOHP 14 | from .dataset.face import Face 15 | 16 | 17 | dataset_factory = { 18 | 'coco': COCO, 19 | 'pascal': PascalVOC, 20 | 'kitti': KITTI, 21 | 'coco_hp': COCOHP, 22 | 'face': Face 23 | } 24 | 25 | _sample_factory = { 26 | 'exdet': EXDetDataset, 27 | 'ctdet': CTDetDataset, 28 | 'ddd': DddDataset, 29 | 'multi_pose': MultiPoseDataset 30 | } 31 | 32 | 33 | def get_dataset(dataset, task): 34 | class Dataset(dataset_factory[dataset], _sample_factory[task]): 35 | pass 36 | return Dataset 37 | 38 | -------------------------------------------------------------------------------- /src/lib/datasets/sample/__pycache__/ctdet.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/datasets/sample/__pycache__/ctdet.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/datasets/sample/__pycache__/ddd.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/datasets/sample/__pycache__/ddd.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/datasets/sample/__pycache__/exdet.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/datasets/sample/__pycache__/exdet.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/datasets/sample/__pycache__/multi_pose.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/datasets/sample/__pycache__/multi_pose.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/detectors/__pycache__/base_detector.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/detectors/__pycache__/base_detector.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/detectors/__pycache__/ctdet.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/detectors/__pycache__/ctdet.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/detectors/__pycache__/ddd.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/detectors/__pycache__/ddd.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/detectors/__pycache__/detector_factory.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/detectors/__pycache__/detector_factory.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/detectors/__pycache__/exdet.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/detectors/__pycache__/exdet.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/detectors/__pycache__/multi_pose.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/detectors/__pycache__/multi_pose.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/detectors/ctdet.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | import cv2 6 | import numpy as np 7 | from progress.bar import Bar 8 | import time 9 | import torch 10 | 11 | try: 12 | from external.nms import soft_nms 13 | except: 14 | print('NMS not imported! If you need it,' 15 | ' do \n cd $CenterNet_ROOT/src/lib/external \n make') 16 | from models.decode import ctdet_decode 17 | from models.utils import flip_tensor 18 | from utils.image import get_affine_transform 19 | from utils.post_process import ctdet_post_process 20 | from utils.debugger import Debugger 21 | 22 | from .base_detector import BaseDetector 23 | 24 | class CtdetDetector(BaseDetector): 25 | def __init__(self, opt): 26 | super(CtdetDetector, self).__init__(opt) 27 | 28 | def process(self, images, return_time=False): 29 | with torch.no_grad(): 30 | output = self.model(images)[-1] 31 | hm = output['hm'].sigmoid_() 32 | wh = output['wh'] 33 | reg = output['reg'] if self.opt.reg_offset else None 34 | if self.opt.flip_test: 35 | hm = (hm[0:1] + flip_tensor(hm[1:2])) / 2 36 | wh = (wh[0:1] + flip_tensor(wh[1:2])) / 2 37 | reg = reg[0:1] if reg is not None else None 38 | torch.cuda.synchronize() 39 | forward_time = time.time() 40 | dets = ctdet_decode(hm, wh, reg=reg, cat_spec_wh=self.opt.cat_spec_wh, K=self.opt.K) 41 | 42 | if return_time: 43 | return output, dets, forward_time 44 | else: 45 | return output, dets 46 | 47 | def post_process(self, dets, meta, scale=1): 48 | dets = dets.detach().cpu().numpy() 49 | dets = dets.reshape(1, -1, dets.shape[2]) 50 | dets = ctdet_post_process( 51 | dets.copy(), [meta['c']], [meta['s']], 52 | meta['out_height'], meta['out_width'], self.opt.num_classes) 53 | for j in range(1, self.num_classes + 1): 54 | dets[0][j] = np.array(dets[0][j], dtype=np.float32).reshape(-1, 5) 55 | dets[0][j][:, :4] /= scale 56 | return dets[0] 57 | 58 | def merge_outputs(self, detections): 59 | results = {} 60 | for j in range(1, self.num_classes + 1): 61 | results[j] = np.concatenate( 62 | [detection[j] for detection in detections], axis=0).astype(np.float32) 63 | if len(self.scales) > 1 or self.opt.nms: 64 | soft_nms(results[j], Nt=0.5, method=2) 65 | scores = np.hstack( 66 | [results[j][:, 4] for j in range(1, self.num_classes + 1)]) 67 | if len(scores) > self.max_per_image: 68 | kth = len(scores) - self.max_per_image 69 | thresh = np.partition(scores, kth)[kth] 70 | for j in range(1, self.num_classes + 1): 71 | keep_inds = (results[j][:, 4] >= thresh) 72 | results[j] = results[j][keep_inds] 73 | return results 74 | 75 | def debug(self, debugger, images, dets, output, scale=1): 76 | detection = dets.detach().cpu().numpy().copy() 77 | detection[:, :, :4] *= self.opt.down_ratio 78 | for i in range(1): 79 | img = images[i].detach().cpu().numpy().transpose(1, 2, 0) 80 | img = ((img * self.std + self.mean) * 255).astype(np.uint8) 81 | pred = debugger.gen_colormap(output['hm'][i].detach().cpu().numpy()) 82 | debugger.add_blend_img(img, pred, 'pred_hm_{:.1f}'.format(scale)) 83 | debugger.add_img(img, img_id='out_pred_{:.1f}'.format(scale)) 84 | for k in range(len(dets[i])): 85 | if detection[i, k, 4] > self.opt.center_thresh: 86 | debugger.add_coco_bbox(detection[i, k, :4], detection[i, k, -1], 87 | detection[i, k, 4], 88 | img_id='out_pred_{:.1f}'.format(scale)) 89 | 90 | def show_results(self, debugger, image, results): 91 | debugger.add_img(image, img_id='ctdet') 92 | for j in range(1, self.num_classes + 1): 93 | for bbox in results[j]: 94 | if bbox[4] > self.opt.vis_thresh: 95 | debugger.add_coco_bbox(bbox[:4], j - 1, bbox[4], img_id='ctdet') 96 | debugger.show_all_imgs(pause=self.pause) 97 | # debugger.save_all_imgs(path='/home/mario/Projects/Obj_det/CenterNet/output/', genID=True) 98 | -------------------------------------------------------------------------------- /src/lib/detectors/ddd.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | import cv2 6 | import numpy as np 7 | from progress.bar import Bar 8 | import time 9 | import torch 10 | 11 | 12 | from models.decode import ddd_decode 13 | from models.utils import flip_tensor 14 | from utils.image import get_affine_transform 15 | from utils.post_process import ddd_post_process 16 | from utils.debugger import Debugger 17 | from utils.ddd_utils import compute_box_3d, project_to_image, alpha2rot_y 18 | from utils.ddd_utils import draw_box_3d, unproject_2d_to_3d 19 | 20 | from .base_detector import BaseDetector 21 | 22 | class DddDetector(BaseDetector): 23 | def __init__(self, opt): 24 | super(DddDetector, self).__init__(opt) 25 | self.calib = np.array([[707.0493, 0, 604.0814, 45.75831], 26 | [0, 707.0493, 180.5066, -0.3454157], 27 | [0, 0, 1., 0.004981016]], dtype=np.float32) 28 | 29 | 30 | def pre_process(self, image, scale, calib=None): 31 | height, width = image.shape[0:2] 32 | 33 | inp_height, inp_width = self.opt.input_h, self.opt.input_w 34 | c = np.array([width / 2, height / 2], dtype=np.float32) 35 | if self.opt.keep_res: 36 | s = np.array([inp_width, inp_height], dtype=np.int32) 37 | else: 38 | s = np.array([width, height], dtype=np.int32) 39 | 40 | trans_input = get_affine_transform(c, s, 0, [inp_width, inp_height]) 41 | resized_image = image #cv2.resize(image, (width, height)) 42 | inp_image = cv2.warpAffine( 43 | resized_image, trans_input, (inp_width, inp_height), 44 | flags=cv2.INTER_LINEAR) 45 | inp_image = (inp_image.astype(np.float32) / 255.) 46 | inp_image = (inp_image - self.mean) / self.std 47 | images = inp_image.transpose(2, 0, 1)[np.newaxis, ...] 48 | calib = np.array(calib, dtype=np.float32) if calib is not None \ 49 | else self.calib 50 | images = torch.from_numpy(images) 51 | meta = {'c': c, 's': s, 52 | 'out_height': inp_height // self.opt.down_ratio, 53 | 'out_width': inp_width // self.opt.down_ratio, 54 | 'calib': calib} 55 | return images, meta 56 | 57 | def process(self, images, return_time=False): 58 | with torch.no_grad(): 59 | torch.cuda.synchronize() 60 | output = self.model(images)[-1] 61 | output['hm'] = output['hm'].sigmoid_() 62 | output['dep'] = 1. / (output['dep'].sigmoid() + 1e-6) - 1. 63 | wh = output['wh'] if self.opt.reg_bbox else None 64 | reg = output['reg'] if self.opt.reg_offset else None 65 | torch.cuda.synchronize() 66 | forward_time = time.time() 67 | 68 | dets = ddd_decode(output['hm'], output['rot'], output['dep'], 69 | output['dim'], wh=wh, reg=reg, K=self.opt.K) 70 | if return_time: 71 | return output, dets, forward_time 72 | else: 73 | return output, dets 74 | 75 | def post_process(self, dets, meta, scale=1): 76 | dets = dets.detach().cpu().numpy() 77 | detections = ddd_post_process( 78 | dets.copy(), [meta['c']], [meta['s']], [meta['calib']], self.opt) 79 | self.this_calib = meta['calib'] 80 | return detections[0] 81 | 82 | def merge_outputs(self, detections): 83 | results = detections[0] 84 | for j in range(1, self.num_classes + 1): 85 | if len(results[j] > 0): 86 | keep_inds = (results[j][:, -1] > self.opt.peak_thresh) 87 | results[j] = results[j][keep_inds] 88 | return results 89 | 90 | def debug(self, debugger, images, dets, output, scale=1): 91 | dets = dets.detach().cpu().numpy() 92 | img = images[0].detach().cpu().numpy().transpose(1, 2, 0) 93 | img = ((img * self.std + self.mean) * 255).astype(np.uint8) 94 | pred = debugger.gen_colormap(output['hm'][0].detach().cpu().numpy()) 95 | debugger.add_blend_img(img, pred, 'pred_hm') 96 | debugger.add_ct_detection( 97 | img, dets[0], show_box=self.opt.reg_bbox, 98 | center_thresh=self.opt.vis_thresh, img_id='det_pred') 99 | 100 | def show_results(self, debugger, image, results): 101 | debugger.add_3d_detection( 102 | image, results, self.this_calib, 103 | center_thresh=self.opt.vis_thresh, img_id='add_pred') 104 | debugger.add_bird_view( 105 | results, center_thresh=self.opt.vis_thresh, img_id='bird_pred') 106 | debugger.show_all_imgs(pause=self.pause) -------------------------------------------------------------------------------- /src/lib/detectors/detector_factory.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | from .exdet import ExdetDetector 6 | from .ddd import DddDetector 7 | from .ctdet import CtdetDetector 8 | from .multi_pose import MultiPoseDetector 9 | 10 | detector_factory = { 11 | 'exdet': ExdetDetector, 12 | 'ddd': DddDetector, 13 | 'ctdet': CtdetDetector, 14 | 'multi_pose': MultiPoseDetector, 15 | } 16 | -------------------------------------------------------------------------------- /src/lib/detectors/multi_pose.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | import cv2 6 | import numpy as np 7 | from progress.bar import Bar 8 | import time 9 | import torch 10 | 11 | try: 12 | from external.nms import soft_nms_39 13 | except: 14 | print('NMS not imported! If you need it,' 15 | ' do \n cd $CenterNet_ROOT/src/lib/external \n make') 16 | from models.decode import multi_pose_decode 17 | from models.utils import flip_tensor, flip_lr_off, flip_lr 18 | from utils.image import get_affine_transform 19 | from utils.post_process import multi_pose_post_process 20 | from utils.debugger import Debugger 21 | 22 | from .base_detector import BaseDetector 23 | 24 | class MultiPoseDetector(BaseDetector): 25 | def __init__(self, opt): 26 | super(MultiPoseDetector, self).__init__(opt) 27 | self.flip_idx = opt.flip_idx 28 | 29 | def process(self, images, return_time=False): 30 | with torch.no_grad(): 31 | torch.cuda.synchronize() 32 | output = self.model(images)[-1] 33 | output['hm'] = output['hm'].sigmoid_() 34 | if self.opt.hm_hp and not self.opt.mse_loss: 35 | output['hm_hp'] = output['hm_hp'].sigmoid_() 36 | 37 | reg = output['reg'] if self.opt.reg_offset else None 38 | hm_hp = output['hm_hp'] if self.opt.hm_hp else None 39 | hp_offset = output['hp_offset'] if self.opt.reg_hp_offset else None 40 | torch.cuda.synchronize() 41 | forward_time = time.time() 42 | 43 | if self.opt.flip_test: 44 | output['hm'] = (output['hm'][0:1] + flip_tensor(output['hm'][1:2])) / 2 45 | output['wh'] = (output['wh'][0:1] + flip_tensor(output['wh'][1:2])) / 2 46 | output['hps'] = (output['hps'][0:1] + 47 | flip_lr_off(output['hps'][1:2], self.flip_idx)) / 2 48 | hm_hp = (hm_hp[0:1] + flip_lr(hm_hp[1:2], self.flip_idx)) / 2 \ 49 | if hm_hp is not None else None 50 | reg = reg[0:1] if reg is not None else None 51 | hp_offset = hp_offset[0:1] if hp_offset is not None else None 52 | 53 | dets = multi_pose_decode( 54 | output['hm'], output['wh'], output['hps'], 55 | reg=reg, hm_hp=hm_hp, hp_offset=hp_offset, K=self.opt.K) 56 | 57 | if return_time: 58 | return output, dets, forward_time 59 | else: 60 | return output, dets 61 | 62 | def post_process(self, dets, meta, scale=1): 63 | dets = dets.detach().cpu().numpy().reshape(1, -1, dets.shape[2]) 64 | dets = multi_pose_post_process( 65 | dets.copy(), [meta['c']], [meta['s']], 66 | meta['out_height'], meta['out_width']) 67 | for j in range(1, self.num_classes + 1): 68 | dets[0][j] = np.array(dets[0][j], dtype=np.float32).reshape(-1, 39) 69 | # import pdb; pdb.set_trace() 70 | dets[0][j][:, :4] /= scale 71 | dets[0][j][:, 5:] /= scale 72 | return dets[0] 73 | 74 | def merge_outputs(self, detections): 75 | results = {} 76 | results[1] = np.concatenate( 77 | [detection[1] for detection in detections], axis=0).astype(np.float32) 78 | if self.opt.nms or len(self.opt.test_scales) > 1: 79 | soft_nms_39(results[1], Nt=0.5, method=2) 80 | results[1] = results[1].tolist() 81 | return results 82 | 83 | def debug(self, debugger, images, dets, output, scale=1): 84 | dets = dets.detach().cpu().numpy().copy() 85 | dets[:, :, :4] *= self.opt.down_ratio 86 | dets[:, :, 5:39] *= self.opt.down_ratio 87 | img = images[0].detach().cpu().numpy().transpose(1, 2, 0) 88 | img = np.clip((( 89 | img * self.std + self.mean) * 255.), 0, 255).astype(np.uint8) 90 | pred = debugger.gen_colormap(output['hm'][0].detach().cpu().numpy()) 91 | debugger.add_blend_img(img, pred, 'pred_hm') 92 | if self.opt.hm_hp: 93 | pred = debugger.gen_colormap_hp( 94 | output['hm_hp'][0].detach().cpu().numpy()) 95 | debugger.add_blend_img(img, pred, 'pred_hmhp') 96 | 97 | def show_results(self, debugger, image, results): 98 | debugger.add_img(image, img_id='multi_pose') 99 | for bbox in results[1]: 100 | if bbox[4] > self.opt.vis_thresh: 101 | debugger.add_coco_bbox(bbox[:4], 0, bbox[4], img_id='multi_pose') 102 | debugger.add_coco_hp(bbox[5:39], img_id='multi_pose') 103 | debugger.show_all_imgs(pause=self.pause) -------------------------------------------------------------------------------- /src/lib/external/.gitignore: -------------------------------------------------------------------------------- 1 | bbox.c 2 | bbox.cpython-35m-x86_64-linux-gnu.so 3 | bbox.cpython-36m-x86_64-linux-gnu.so 4 | 5 | nms.c 6 | nms.cpython-35m-x86_64-linux-gnu.so 7 | nms.cpython-36m-x86_64-linux-gnu.so 8 | -------------------------------------------------------------------------------- /src/lib/external/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | python setup.py build_ext --inplace 3 | rm -rf build 4 | -------------------------------------------------------------------------------- /src/lib/external/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/external/__init__.py -------------------------------------------------------------------------------- /src/lib/external/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/external/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/external/setup.py: -------------------------------------------------------------------------------- 1 | import numpy 2 | from distutils.core import setup 3 | from distutils.extension import Extension 4 | from Cython.Build import cythonize 5 | 6 | extensions = [ 7 | Extension( 8 | "nms", 9 | ["nms.pyx"], 10 | extra_compile_args=["-Wno-cpp", "-Wno-unused-function"] 11 | ) 12 | ] 13 | 14 | setup( 15 | name="coco", 16 | ext_modules=cythonize(extensions), 17 | include_dirs=[numpy.get_include()] 18 | ) 19 | -------------------------------------------------------------------------------- /src/lib/logger.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | # Code referenced from https://gist.github.com/gyglim/1f8dfb1b5c82627ae3efcfbbadb9f514 6 | import os 7 | import time 8 | import sys 9 | import torch 10 | USE_TENSORBOARD = True 11 | try: 12 | import tensorboardX 13 | print('Using tensorboardX') 14 | except: 15 | USE_TENSORBOARD = False 16 | 17 | class Logger(object): 18 | def __init__(self, opt): 19 | """Create a summary writer logging to log_dir.""" 20 | if not os.path.exists(opt.save_dir): 21 | os.makedirs(opt.save_dir) 22 | if not os.path.exists(opt.debug_dir): 23 | os.makedirs(opt.debug_dir) 24 | 25 | time_str = time.strftime('%Y-%m-%d-%H-%M') 26 | 27 | args = dict((name, getattr(opt, name)) for name in dir(opt) 28 | if not name.startswith('_')) 29 | file_name = os.path.join(opt.save_dir, 'opt.txt') 30 | with open(file_name, 'wt') as opt_file: 31 | opt_file.write('==> torch version: {}\n'.format(torch.__version__)) 32 | opt_file.write('==> cudnn version: {}\n'.format( 33 | torch.backends.cudnn.version())) 34 | opt_file.write('==> Cmd:\n') 35 | opt_file.write(str(sys.argv)) 36 | opt_file.write('\n==> Opt:\n') 37 | for k, v in sorted(args.items()): 38 | opt_file.write(' %s: %s\n' % (str(k), str(v))) 39 | 40 | log_dir = opt.save_dir + '/logs_{}'.format(time_str) 41 | if USE_TENSORBOARD: 42 | self.writer = tensorboardX.SummaryWriter(log_dir=log_dir) 43 | else: 44 | if not os.path.exists(os.path.dirname(log_dir)): 45 | os.mkdir(os.path.dirname(log_dir)) 46 | if not os.path.exists(log_dir): 47 | os.mkdir(log_dir) 48 | self.log = open(log_dir + '/log.txt', 'w') 49 | try: 50 | os.system('cp {}/opt.txt {}/'.format(opt.save_dir, log_dir)) 51 | except: 52 | pass 53 | self.start_line = True 54 | 55 | def write(self, txt): 56 | if self.start_line: 57 | time_str = time.strftime('%Y-%m-%d-%H-%M') 58 | self.log.write('{}: {}'.format(time_str, txt)) 59 | else: 60 | self.log.write(txt) 61 | self.start_line = False 62 | if '\n' in txt: 63 | self.start_line = True 64 | self.log.flush() 65 | 66 | def close(self): 67 | self.log.close() 68 | 69 | def scalar_summary(self, tag, value, step): 70 | """Log a scalar variable.""" 71 | if USE_TENSORBOARD: 72 | self.writer.add_scalar(tag, value, step) 73 | -------------------------------------------------------------------------------- /src/lib/models/__pycache__/data_parallel.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/models/__pycache__/data_parallel.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/models/__pycache__/decode.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/models/__pycache__/decode.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/models/__pycache__/losses.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/models/__pycache__/losses.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/models/__pycache__/model.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/models/__pycache__/model.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/models/__pycache__/scatter_gather.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/models/__pycache__/scatter_gather.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/models/__pycache__/utils.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/models/__pycache__/utils.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/models/model.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | import torchvision.models as models 6 | import torch 7 | import torch.nn as nn 8 | import os 9 | 10 | from .networks.msra_resnet import get_pose_net 11 | from .networks.dlav0 import get_pose_net as get_dlav0 12 | from .networks.pose_dla_dcn import get_pose_net as get_dla_dcn 13 | from .networks.resnet_dcn import get_pose_net as get_pose_net_dcn 14 | from .networks.large_hourglass import get_large_hourglass_net 15 | from .networks.mobilenetv2 import get_mobile_net 16 | 17 | _model_factory = { 18 | 'res': get_pose_net, # default Resnet with deconv 19 | 'dlav0': get_dlav0, # default DLAup 20 | 'dla': get_dla_dcn, 21 | 'resdcn': get_pose_net_dcn, 22 | 'hourglass': get_large_hourglass_net, 23 | 'mobilenetv2': get_mobile_net, 24 | } 25 | 26 | def create_model(arch, heads, head_conv): 27 | num_layers = int(arch[arch.find('_') + 1:]) if '_' in arch else 0 28 | arch = arch[:arch.find('_')] if '_' in arch else arch 29 | get_model = _model_factory[arch] 30 | model = get_model(num_layers=num_layers, heads=heads, head_conv=head_conv) 31 | return model 32 | 33 | def load_model(model, model_path, optimizer=None, resume=False, 34 | lr=None, lr_step=None): 35 | start_epoch = 0 36 | checkpoint = torch.load(model_path, map_location=lambda storage, loc: storage) 37 | print('loaded {}, epoch {}'.format(model_path, checkpoint['epoch'])) 38 | state_dict_ = checkpoint['state_dict'] 39 | state_dict = {} 40 | 41 | # convert data_parallal to model 42 | for k in state_dict_: 43 | if k.startswith('module') and not k.startswith('module_list'): 44 | state_dict[k[7:]] = state_dict_[k] 45 | else: 46 | state_dict[k] = state_dict_[k] 47 | model_state_dict = model.state_dict() 48 | 49 | # check loaded parameters and created model parameters 50 | msg = 'If you see this, your model does not fully load the ' + \ 51 | 'pre-trained weight. Please make sure ' + \ 52 | 'you have correctly specified --arch xxx ' + \ 53 | 'or set the correct --num_classes for your own dataset.' 54 | for k in state_dict: 55 | if k in model_state_dict: 56 | if state_dict[k].shape != model_state_dict[k].shape: 57 | print('Skip loading parameter {}, required shape{}, '\ 58 | 'loaded shape{}. {}'.format( 59 | k, model_state_dict[k].shape, state_dict[k].shape, msg)) 60 | state_dict[k] = model_state_dict[k] 61 | else: 62 | print('Drop parameter {}.'.format(k) + msg) 63 | for k in model_state_dict: 64 | if not (k in state_dict): 65 | print('No param {}.'.format(k) + msg) 66 | state_dict[k] = model_state_dict[k] 67 | model.load_state_dict(state_dict, strict=False) 68 | 69 | # resume optimizer parameters 70 | if optimizer is not None and resume: 71 | if 'optimizer' in checkpoint: 72 | optimizer.load_state_dict(checkpoint['optimizer']) 73 | start_epoch = checkpoint['epoch'] 74 | start_lr = lr 75 | for step in lr_step: 76 | if start_epoch >= step: 77 | start_lr *= 0.1 78 | for param_group in optimizer.param_groups: 79 | param_group['lr'] = start_lr 80 | print('Resumed optimizer with start lr', start_lr) 81 | else: 82 | print('No optimizer parameters in checkpoint.') 83 | if optimizer is not None: 84 | return model, optimizer, start_epoch 85 | else: 86 | return model 87 | 88 | def save_model(path, epoch, model, optimizer=None): 89 | if isinstance(model, torch.nn.DataParallel): 90 | state_dict = model.module.state_dict() 91 | else: 92 | state_dict = model.state_dict() 93 | data = {'epoch': epoch, 94 | 'state_dict': state_dict} 95 | if not (optimizer is None): 96 | data['optimizer'] = optimizer.state_dict() 97 | torch.save(data, path) 98 | 99 | -------------------------------------------------------------------------------- /src/lib/models/networks/__pycache__/dlav0.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/models/networks/__pycache__/dlav0.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/models/networks/__pycache__/large_hourglass.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/models/networks/__pycache__/large_hourglass.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/models/networks/__pycache__/mobilenetv2.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/models/networks/__pycache__/mobilenetv2.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/models/networks/__pycache__/msra_resnet.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/models/networks/__pycache__/msra_resnet.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/models/networks/__pycache__/pose_dla_dcn.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/models/networks/__pycache__/pose_dla_dcn.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/models/networks/__pycache__/resnet_dcn.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/models/networks/__pycache__/resnet_dcn.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/models/scatter_gather.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch.autograd import Variable 3 | from torch.nn.parallel._functions import Scatter, Gather 4 | 5 | 6 | def scatter(inputs, target_gpus, dim=0, chunk_sizes=None): 7 | r""" 8 | Slices variables into approximately equal chunks and 9 | distributes them across given GPUs. Duplicates 10 | references to objects that are not variables. Does not 11 | support Tensors. 12 | """ 13 | def scatter_map(obj): 14 | if isinstance(obj, Variable): 15 | return Scatter.apply(target_gpus, chunk_sizes, dim, obj) 16 | assert not torch.is_tensor(obj), "Tensors not supported in scatter." 17 | if isinstance(obj, tuple): 18 | return list(zip(*map(scatter_map, obj))) 19 | if isinstance(obj, list): 20 | return list(map(list, zip(*map(scatter_map, obj)))) 21 | if isinstance(obj, dict): 22 | return list(map(type(obj), zip(*map(scatter_map, obj.items())))) 23 | return [obj for targets in target_gpus] 24 | 25 | return scatter_map(inputs) 26 | 27 | 28 | def scatter_kwargs(inputs, kwargs, target_gpus, dim=0, chunk_sizes=None): 29 | r"""Scatter with support for kwargs dictionary""" 30 | inputs = scatter(inputs, target_gpus, dim, chunk_sizes) if inputs else [] 31 | kwargs = scatter(kwargs, target_gpus, dim, chunk_sizes) if kwargs else [] 32 | if len(inputs) < len(kwargs): 33 | inputs.extend([() for _ in range(len(kwargs) - len(inputs))]) 34 | elif len(kwargs) < len(inputs): 35 | kwargs.extend([{} for _ in range(len(inputs) - len(kwargs))]) 36 | inputs = tuple(inputs) 37 | kwargs = tuple(kwargs) 38 | return inputs, kwargs 39 | -------------------------------------------------------------------------------- /src/lib/models/utils.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | import torch 6 | import torch.nn as nn 7 | 8 | def _sigmoid(x): 9 | y = torch.clamp(x.sigmoid_(), min=1e-4, max=1-1e-4) 10 | return y 11 | 12 | def _gather_feat(feat, ind, mask=None): 13 | dim = feat.size(2) 14 | ind = ind.unsqueeze(2).expand(ind.size(0), ind.size(1), dim) 15 | feat = feat.gather(1, ind) 16 | if mask is not None: 17 | mask = mask.unsqueeze(2).expand_as(feat) 18 | feat = feat[mask] 19 | feat = feat.view(-1, dim) 20 | return feat 21 | 22 | def _transpose_and_gather_feat(feat, ind): 23 | feat = feat.permute(0, 2, 3, 1).contiguous() 24 | feat = feat.view(feat.size(0), -1, feat.size(3)) 25 | feat = _gather_feat(feat, ind) 26 | return feat 27 | 28 | def flip_tensor(x): 29 | return torch.flip(x, [3]) 30 | # tmp = x.detach().cpu().numpy()[..., ::-1].copy() 31 | # return torch.from_numpy(tmp).to(x.device) 32 | 33 | def flip_lr(x, flip_idx): 34 | tmp = x.detach().cpu().numpy()[..., ::-1].copy() 35 | shape = tmp.shape 36 | for e in flip_idx: 37 | tmp[:, e[0], ...], tmp[:, e[1], ...] = \ 38 | tmp[:, e[1], ...].copy(), tmp[:, e[0], ...].copy() 39 | return torch.from_numpy(tmp.reshape(shape)).to(x.device) 40 | 41 | def flip_lr_off(x, flip_idx): 42 | tmp = x.detach().cpu().numpy()[..., ::-1].copy() 43 | shape = tmp.shape 44 | tmp = tmp.reshape(tmp.shape[0], 17, 2, 45 | tmp.shape[2], tmp.shape[3]) 46 | tmp[:, :, 0, :, :] *= -1 47 | for e in flip_idx: 48 | tmp[:, e[0], ...], tmp[:, e[1], ...] = \ 49 | tmp[:, e[1], ...].copy(), tmp[:, e[0], ...].copy() 50 | return torch.from_numpy(tmp.reshape(shape)).to(x.device) -------------------------------------------------------------------------------- /src/lib/pytorch2onnx.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torchvision 3 | import torch.onnx 4 | from models.model import create_model, load_model 5 | 6 | input = torch.randn(1, 3, 512, 512) 7 | ## mobilenetv2_10 8 | # model = create_model('mobilenetv2_10', heads={'hm': 1, 'wh': 2, 'reg': 2}, head_conv=24) 9 | ## resnet18 10 | model = create_model('res_18', heads={'hm': 1, 'wh': 2, 'reg': 2}, head_conv=64) 11 | model = load_model(model, '/home/mario/Projects/Obj_det/CenterNet/exp/ctdet/face_res18/model_best.pth') 12 | 13 | 14 | torch.onnx.export(model, input, "/home/mario/Projects/Obj_det/CenterNet/exp/ctdet/face_res18/res18.onnx", input_names=["input"], output_names=["hm","wh","reg"]) 15 | -------------------------------------------------------------------------------- /src/lib/trains/__pycache__/base_trainer.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/trains/__pycache__/base_trainer.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/trains/__pycache__/ctdet.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/trains/__pycache__/ctdet.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/trains/__pycache__/ddd.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/trains/__pycache__/ddd.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/trains/__pycache__/exdet.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/trains/__pycache__/exdet.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/trains/__pycache__/multi_pose.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/trains/__pycache__/multi_pose.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/trains/__pycache__/train_factory.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/trains/__pycache__/train_factory.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/trains/base_trainer.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | import time 6 | import torch 7 | from progress.bar import Bar 8 | from models.data_parallel import DataParallel 9 | from utils.utils import AverageMeter 10 | 11 | 12 | class ModelWithLoss(torch.nn.Module): 13 | def __init__(self, model, loss): 14 | super(ModelWithLoss, self).__init__() 15 | self.model = model 16 | self.loss = loss 17 | 18 | def forward(self, batch): 19 | outputs = self.model(batch['input']) 20 | loss, loss_stats = self.loss(outputs, batch) 21 | return outputs[-1], loss, loss_stats 22 | 23 | class BaseTrainer(object): 24 | def __init__( 25 | self, opt, model, optimizer=None): 26 | self.opt = opt 27 | self.optimizer = optimizer 28 | self.loss_stats, self.loss = self._get_losses(opt) 29 | self.model_with_loss = ModelWithLoss(model, self.loss) 30 | 31 | def set_device(self, gpus, chunk_sizes, device): 32 | if len(gpus) > 1: 33 | self.model_with_loss = DataParallel( 34 | self.model_with_loss, device_ids=gpus, 35 | chunk_sizes=chunk_sizes).to(device) 36 | else: 37 | self.model_with_loss = self.model_with_loss.to(device) 38 | 39 | for state in self.optimizer.state.values(): 40 | for k, v in state.items(): 41 | if isinstance(v, torch.Tensor): 42 | state[k] = v.to(device=device, non_blocking=True) 43 | 44 | def run_epoch(self, phase, epoch, data_loader): 45 | model_with_loss = self.model_with_loss 46 | if phase == 'train': 47 | model_with_loss.train() 48 | else: 49 | if len(self.opt.gpus) > 1: 50 | model_with_loss = self.model_with_loss.module 51 | model_with_loss.eval() 52 | torch.cuda.empty_cache() 53 | 54 | opt = self.opt 55 | results = {} 56 | data_time, batch_time = AverageMeter(), AverageMeter() 57 | avg_loss_stats = {l: AverageMeter() for l in self.loss_stats} 58 | num_iters = len(data_loader) if opt.num_iters < 0 else opt.num_iters 59 | bar = Bar('{}/{}'.format(opt.task, opt.exp_id), max=num_iters) 60 | end = time.time() 61 | for iter_id, batch in enumerate(data_loader): 62 | if iter_id >= num_iters: 63 | break 64 | data_time.update(time.time() - end) 65 | 66 | for k in batch: 67 | if k != 'meta': 68 | batch[k] = batch[k].to(device=opt.device, non_blocking=True) 69 | output, loss, loss_stats = model_with_loss(batch) 70 | loss = loss.mean() 71 | if phase == 'train': 72 | self.optimizer.zero_grad() 73 | loss.backward() 74 | self.optimizer.step() 75 | batch_time.update(time.time() - end) 76 | end = time.time() 77 | 78 | Bar.suffix = '{phase}: [{0}][{1}/{2}]|Tot: {total:} |ETA: {eta:} '.format( 79 | epoch, iter_id, num_iters, phase=phase, 80 | total=bar.elapsed_td, eta=bar.eta_td) 81 | for l in avg_loss_stats: 82 | avg_loss_stats[l].update( 83 | loss_stats[l].mean().item(), batch['input'].size(0)) 84 | Bar.suffix = Bar.suffix + '|{} {:.4f} '.format(l, avg_loss_stats[l].avg) 85 | if not opt.hide_data_time: 86 | Bar.suffix = Bar.suffix + '|Data {dt.val:.3f}s({dt.avg:.3f}s) ' \ 87 | '|Net {bt.avg:.3f}s'.format(dt=data_time, bt=batch_time) 88 | if opt.print_iter > 0: 89 | if iter_id % opt.print_iter == 0: 90 | print('{}/{}| {}'.format(opt.task, opt.exp_id, Bar.suffix)) 91 | else: 92 | bar.next() 93 | 94 | if opt.debug > 0: 95 | self.debug(batch, output, iter_id) 96 | 97 | if opt.test: 98 | self.save_result(output, batch, results) 99 | del output, loss, loss_stats 100 | 101 | bar.finish() 102 | ret = {k: v.avg for k, v in avg_loss_stats.items()} 103 | ret['time'] = bar.elapsed_td.total_seconds() / 60. 104 | return ret, results 105 | 106 | def debug(self, batch, output, iter_id): 107 | raise NotImplementedError 108 | 109 | def save_result(self, output, batch, results): 110 | raise NotImplementedError 111 | 112 | def _get_losses(self, opt): 113 | raise NotImplementedError 114 | 115 | def val(self, epoch, data_loader): 116 | return self.run_epoch('val', epoch, data_loader) 117 | 118 | def train(self, epoch, data_loader): 119 | return self.run_epoch('train', epoch, data_loader) -------------------------------------------------------------------------------- /src/lib/trains/exdet.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | import torch 6 | import numpy as np 7 | import cv2 8 | import sys 9 | import time 10 | from utils.debugger import Debugger 11 | from models.data_parallel import DataParallel 12 | from models.losses import FocalLoss, RegL1Loss 13 | from models.decode import agnex_ct_decode, exct_decode 14 | from models.utils import _sigmoid 15 | from .base_trainer import BaseTrainer 16 | 17 | class ExdetLoss(torch.nn.Module): 18 | def __init__(self, opt): 19 | super(ExdetLoss, self).__init__() 20 | self.crit = torch.nn.MSELoss() if opt.mse_loss else FocalLoss() 21 | self.crit_reg = RegL1Loss() 22 | self.opt = opt 23 | self.parts = ['t', 'l', 'b', 'r', 'c'] 24 | 25 | def forward(self, outputs, batch): 26 | opt = self.opt 27 | hm_loss, reg_loss = 0, 0 28 | for s in range(opt.num_stacks): 29 | output = outputs[s] 30 | for p in self.parts: 31 | tag = 'hm_{}'.format(p) 32 | output[tag] = _sigmoid(output[tag]) 33 | hm_loss += self.crit(output[tag], batch[tag]) / opt.num_stacks 34 | if p != 'c' and opt.reg_offset and opt.off_weight > 0: 35 | reg_loss += self.crit_reg(output['reg_{}'.format(p)], 36 | batch['reg_mask'], 37 | batch['ind_{}'.format(p)], 38 | batch['reg_{}'.format(p)]) / opt.num_stacks 39 | loss = opt.hm_weight * hm_loss + opt.off_weight * reg_loss 40 | loss_stats = {'loss': loss, 'off_loss': reg_loss, 'hm_loss': hm_loss} 41 | return loss, loss_stats 42 | 43 | class ExdetTrainer(BaseTrainer): 44 | def __init__(self, opt, model, optimizer=None): 45 | super(ExdetTrainer, self).__init__(opt, model, optimizer=optimizer) 46 | self.decode = agnex_ct_decode if opt.agnostic_ex else exct_decode 47 | 48 | def _get_losses(self, opt): 49 | loss_states = ['loss', 'hm_loss', 'off_loss'] 50 | loss = ExdetLoss(opt) 51 | return loss_states, loss 52 | 53 | def debug(self, batch, output, iter_id): 54 | opt = self.opt 55 | detections = self.decode(output['hm_t'], output['hm_l'], 56 | output['hm_b'], output['hm_r'], 57 | output['hm_c']).detach().cpu().numpy() 58 | detections[:, :, :4] *= opt.input_res / opt.output_res 59 | for i in range(1): 60 | debugger = Debugger( 61 | dataset=opt.dataset, ipynb=(opt.debug==3), theme=opt.debugger_theme) 62 | pred_hm = np.zeros((opt.input_res, opt.input_res, 3), dtype=np.uint8) 63 | gt_hm = np.zeros((opt.input_res, opt.input_res, 3), dtype=np.uint8) 64 | img = batch['input'][i].detach().cpu().numpy().transpose(1, 2, 0) 65 | img = ((img * self.opt.std + self.opt.mean) * 255.).astype(np.uint8) 66 | for p in self.parts: 67 | tag = 'hm_{}'.format(p) 68 | pred = debugger.gen_colormap(output[tag][i].detach().cpu().numpy()) 69 | gt = debugger.gen_colormap(batch[tag][i].detach().cpu().numpy()) 70 | if p != 'c': 71 | pred_hm = np.maximum(pred_hm, pred) 72 | gt_hm = np.maximum(gt_hm, gt) 73 | if p == 'c' or opt.debug > 2: 74 | debugger.add_blend_img(img, pred, 'pred_{}'.format(p)) 75 | debugger.add_blend_img(img, gt, 'gt_{}'.format(p)) 76 | debugger.add_blend_img(img, pred_hm, 'pred') 77 | debugger.add_blend_img(img, gt_hm, 'gt') 78 | debugger.add_img(img, img_id='out') 79 | for k in range(len(detections[i])): 80 | if detections[i, k, 4] > 0.1: 81 | debugger.add_coco_bbox(detections[i, k, :4], detections[i, k, -1], 82 | detections[i, k, 4], img_id='out') 83 | if opt.debug == 4: 84 | debugger.save_all_imgs(opt.debug_dir, prefix='{}'.format(iter_id)) 85 | else: 86 | debugger.show_all_imgs(pause=True) -------------------------------------------------------------------------------- /src/lib/trains/train_factory.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | from .ctdet import CtdetTrainer 6 | from .ddd import DddTrainer 7 | from .exdet import ExdetTrainer 8 | from .multi_pose import MultiPoseTrainer 9 | 10 | train_factory = { 11 | 'exdet': ExdetTrainer, 12 | 'ddd': DddTrainer, 13 | 'ctdet': CtdetTrainer, 14 | 'multi_pose': MultiPoseTrainer, 15 | } 16 | -------------------------------------------------------------------------------- /src/lib/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/utils/__init__.py -------------------------------------------------------------------------------- /src/lib/utils/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/utils/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/utils/__pycache__/ddd_utils.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/utils/__pycache__/ddd_utils.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/utils/__pycache__/debugger.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/utils/__pycache__/debugger.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/utils/__pycache__/image.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/utils/__pycache__/image.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/utils/__pycache__/oracle_utils.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/utils/__pycache__/oracle_utils.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/utils/__pycache__/post_process.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/utils/__pycache__/post_process.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/utils/__pycache__/utils.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/lib/utils/__pycache__/utils.cpython-36.pyc -------------------------------------------------------------------------------- /src/lib/utils/ddd_utils.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | import numpy as np 6 | import cv2 7 | 8 | def compute_box_3d(dim, location, rotation_y): 9 | # dim: 3 10 | # location: 3 11 | # rotation_y: 1 12 | # return: 8 x 3 13 | c, s = np.cos(rotation_y), np.sin(rotation_y) 14 | R = np.array([[c, 0, s], [0, 1, 0], [-s, 0, c]], dtype=np.float32) 15 | l, w, h = dim[2], dim[1], dim[0] 16 | x_corners = [l/2, l/2, -l/2, -l/2, l/2, l/2, -l/2, -l/2] 17 | y_corners = [0,0,0,0,-h,-h,-h,-h] 18 | z_corners = [w/2, -w/2, -w/2, w/2, w/2, -w/2, -w/2, w/2] 19 | 20 | corners = np.array([x_corners, y_corners, z_corners], dtype=np.float32) 21 | corners_3d = np.dot(R, corners) 22 | corners_3d = corners_3d + np.array(location, dtype=np.float32).reshape(3, 1) 23 | return corners_3d.transpose(1, 0) 24 | 25 | def project_to_image(pts_3d, P): 26 | # pts_3d: n x 3 27 | # P: 3 x 4 28 | # return: n x 2 29 | pts_3d_homo = np.concatenate( 30 | [pts_3d, np.ones((pts_3d.shape[0], 1), dtype=np.float32)], axis=1) 31 | pts_2d = np.dot(P, pts_3d_homo.transpose(1, 0)).transpose(1, 0) 32 | pts_2d = pts_2d[:, :2] / pts_2d[:, 2:] 33 | # import pdb; pdb.set_trace() 34 | return pts_2d 35 | 36 | def compute_orientation_3d(dim, location, rotation_y): 37 | # dim: 3 38 | # location: 3 39 | # rotation_y: 1 40 | # return: 2 x 3 41 | c, s = np.cos(rotation_y), np.sin(rotation_y) 42 | R = np.array([[c, 0, s], [0, 1, 0], [-s, 0, c]], dtype=np.float32) 43 | orientation_3d = np.array([[0, dim[2]], [0, 0], [0, 0]], dtype=np.float32) 44 | orientation_3d = np.dot(R, orientation_3d) 45 | orientation_3d = orientation_3d + \ 46 | np.array(location, dtype=np.float32).reshape(3, 1) 47 | return orientation_3d.transpose(1, 0) 48 | 49 | def draw_box_3d(image, corners, c=(0, 0, 255)): 50 | face_idx = [[0,1,5,4], 51 | [1,2,6, 5], 52 | [2,3,7,6], 53 | [3,0,4,7]] 54 | for ind_f in range(3, -1, -1): 55 | f = face_idx[ind_f] 56 | for j in range(4): 57 | cv2.line(image, (corners[f[j], 0], corners[f[j], 1]), 58 | (corners[f[(j+1)%4], 0], corners[f[(j+1)%4], 1]), c, 2, lineType=cv2.LINE_AA) 59 | if ind_f == 0: 60 | cv2.line(image, (corners[f[0], 0], corners[f[0], 1]), 61 | (corners[f[2], 0], corners[f[2], 1]), c, 1, lineType=cv2.LINE_AA) 62 | cv2.line(image, (corners[f[1], 0], corners[f[1], 1]), 63 | (corners[f[3], 0], corners[f[3], 1]), c, 1, lineType=cv2.LINE_AA) 64 | return image 65 | 66 | def unproject_2d_to_3d(pt_2d, depth, P): 67 | # pts_2d: 2 68 | # depth: 1 69 | # P: 3 x 4 70 | # return: 3 71 | z = depth - P[2, 3] 72 | x = (pt_2d[0] * depth - P[0, 3] - P[0, 2] * z) / P[0, 0] 73 | y = (pt_2d[1] * depth - P[1, 3] - P[1, 2] * z) / P[1, 1] 74 | pt_3d = np.array([x, y, z], dtype=np.float32) 75 | return pt_3d 76 | 77 | def alpha2rot_y(alpha, x, cx, fx): 78 | """ 79 | Get rotation_y by alpha + theta - 180 80 | alpha : Observation angle of object, ranging [-pi..pi] 81 | x : Object center x to the camera center (x-W/2), in pixels 82 | rotation_y : Rotation ry around Y-axis in camera coordinates [-pi..pi] 83 | """ 84 | rot_y = alpha + np.arctan2(x - cx, fx) 85 | if rot_y > np.pi: 86 | rot_y -= 2 * np.pi 87 | if rot_y < -np.pi: 88 | rot_y += 2 * np.pi 89 | return rot_y 90 | 91 | def rot_y2alpha(rot_y, x, cx, fx): 92 | """ 93 | Get rotation_y by alpha + theta - 180 94 | alpha : Observation angle of object, ranging [-pi..pi] 95 | x : Object center x to the camera center (x-W/2), in pixels 96 | rotation_y : Rotation ry around Y-axis in camera coordinates [-pi..pi] 97 | """ 98 | alpha = rot_y - np.arctan2(x - cx, fx) 99 | if alpha > np.pi: 100 | alpha -= 2 * np.pi 101 | if alpha < -np.pi: 102 | alpha += 2 * np.pi 103 | return alpha 104 | 105 | 106 | def ddd2locrot(center, alpha, dim, depth, calib): 107 | # single image 108 | locations = unproject_2d_to_3d(center, depth, calib) 109 | locations[1] += dim[0] / 2 110 | rotation_y = alpha2rot_y(alpha, center[0], calib[0, 2], calib[0, 0]) 111 | return locations, rotation_y 112 | 113 | def project_3d_bbox(location, dim, rotation_y, calib): 114 | box_3d = compute_box_3d(dim, location, rotation_y) 115 | box_2d = project_to_image(box_3d, calib) 116 | return box_2d 117 | 118 | 119 | if __name__ == '__main__': 120 | calib = np.array( 121 | [[7.070493000000e+02, 0.000000000000e+00, 6.040814000000e+02, 4.575831000000e+01], 122 | [0.000000000000e+00, 7.070493000000e+02, 1.805066000000e+02, -3.454157000000e-01], 123 | [0.000000000000e+00, 0.000000000000e+00, 1.000000000000e+00, 4.981016000000e-03]], 124 | dtype=np.float32) 125 | alpha = -0.20 126 | tl = np.array([712.40, 143.00], dtype=np.float32) 127 | br = np.array([810.73, 307.92], dtype=np.float32) 128 | ct = (tl + br) / 2 129 | rotation_y = 0.01 130 | print('alpha2rot_y', alpha2rot_y(alpha, ct[0], calib[0, 2], calib[0, 0])) 131 | print('rotation_y', rotation_y) -------------------------------------------------------------------------------- /src/lib/utils/oracle_utils.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | import numpy as np 6 | import numba 7 | 8 | @numba.jit(nopython=True, nogil=True) 9 | def gen_oracle_map(feat, ind, w, h): 10 | # feat: B x maxN x featDim 11 | # ind: B x maxN 12 | batch_size = feat.shape[0] 13 | max_objs = feat.shape[1] 14 | feat_dim = feat.shape[2] 15 | out = np.zeros((batch_size, feat_dim, h, w), dtype=np.float32) 16 | vis = np.zeros((batch_size, h, w), dtype=np.uint8) 17 | ds = [(0, 1), (0, -1), (1, 0), (-1, 0)] 18 | for i in range(batch_size): 19 | queue_ind = np.zeros((h*w*2, 2), dtype=np.int32) 20 | queue_feat = np.zeros((h*w*2, feat_dim), dtype=np.float32) 21 | head, tail = 0, 0 22 | for j in range(max_objs): 23 | if ind[i][j] > 0: 24 | x, y = ind[i][j] % w, ind[i][j] // w 25 | out[i, :, y, x] = feat[i][j] 26 | vis[i, y, x] = 1 27 | queue_ind[tail] = x, y 28 | queue_feat[tail] = feat[i][j] 29 | tail += 1 30 | while tail - head > 0: 31 | x, y = queue_ind[head] 32 | f = queue_feat[head] 33 | head += 1 34 | for (dx, dy) in ds: 35 | xx, yy = x + dx, y + dy 36 | if xx >= 0 and yy >= 0 and xx < w and yy < h and vis[i, yy, xx] < 1: 37 | out[i, :, yy, xx] = f 38 | vis[i, yy, xx] = 1 39 | queue_ind[tail] = xx, yy 40 | queue_feat[tail] = f 41 | tail += 1 42 | return out -------------------------------------------------------------------------------- /src/lib/utils/post_process.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | import numpy as np 6 | from .image import transform_preds 7 | from .ddd_utils import ddd2locrot 8 | 9 | 10 | def get_pred_depth(depth): 11 | return depth 12 | 13 | def get_alpha(rot): 14 | # output: (B, 8) [bin1_cls[0], bin1_cls[1], bin1_sin, bin1_cos, 15 | # bin2_cls[0], bin2_cls[1], bin2_sin, bin2_cos] 16 | # return rot[:, 0] 17 | idx = rot[:, 1] > rot[:, 5] 18 | alpha1 = np.arctan2(rot[:, 2], rot[:, 3]) + (-0.5 * np.pi) 19 | alpha2 = np.arctan2(rot[:, 6], rot[:, 7]) + ( 0.5 * np.pi) 20 | return alpha1 * idx + alpha2 * (1 - idx) 21 | 22 | 23 | def ddd_post_process_2d(dets, c, s, opt): 24 | # dets: batch x max_dets x dim 25 | # return 1-based class det list 26 | ret = [] 27 | include_wh = dets.shape[2] > 16 28 | for i in range(dets.shape[0]): 29 | top_preds = {} 30 | dets[i, :, :2] = transform_preds( 31 | dets[i, :, 0:2], c[i], s[i], (opt.output_w, opt.output_h)) 32 | classes = dets[i, :, -1] 33 | for j in range(opt.num_classes): 34 | inds = (classes == j) 35 | top_preds[j + 1] = np.concatenate([ 36 | dets[i, inds, :3].astype(np.float32), 37 | get_alpha(dets[i, inds, 3:11])[:, np.newaxis].astype(np.float32), 38 | get_pred_depth(dets[i, inds, 11:12]).astype(np.float32), 39 | dets[i, inds, 12:15].astype(np.float32)], axis=1) 40 | if include_wh: 41 | top_preds[j + 1] = np.concatenate([ 42 | top_preds[j + 1], 43 | transform_preds( 44 | dets[i, inds, 15:17], c[i], s[i], (opt.output_w, opt.output_h)) 45 | .astype(np.float32)], axis=1) 46 | ret.append(top_preds) 47 | return ret 48 | 49 | def ddd_post_process_3d(dets, calibs): 50 | # dets: batch x max_dets x dim 51 | # return 1-based class det list 52 | ret = [] 53 | for i in range(len(dets)): 54 | preds = {} 55 | for cls_ind in dets[i].keys(): 56 | preds[cls_ind] = [] 57 | for j in range(len(dets[i][cls_ind])): 58 | center = dets[i][cls_ind][j][:2] 59 | score = dets[i][cls_ind][j][2] 60 | alpha = dets[i][cls_ind][j][3] 61 | depth = dets[i][cls_ind][j][4] 62 | dimensions = dets[i][cls_ind][j][5:8] 63 | wh = dets[i][cls_ind][j][8:10] 64 | locations, rotation_y = ddd2locrot( 65 | center, alpha, dimensions, depth, calibs[0]) 66 | bbox = [center[0] - wh[0] / 2, center[1] - wh[1] / 2, 67 | center[0] + wh[0] / 2, center[1] + wh[1] / 2] 68 | pred = [alpha] + bbox + dimensions.tolist() + \ 69 | locations.tolist() + [rotation_y, score] 70 | preds[cls_ind].append(pred) 71 | preds[cls_ind] = np.array(preds[cls_ind], dtype=np.float32) 72 | ret.append(preds) 73 | return ret 74 | 75 | def ddd_post_process(dets, c, s, calibs, opt): 76 | # dets: batch x max_dets x dim 77 | # return 1-based class det list 78 | dets = ddd_post_process_2d(dets, c, s, opt) 79 | dets = ddd_post_process_3d(dets, calibs) 80 | return dets 81 | 82 | 83 | def ctdet_post_process(dets, c, s, h, w, num_classes): 84 | # dets: batch x max_dets x dim 85 | # return 1-based class det dict 86 | ret = [] 87 | for i in range(dets.shape[0]): 88 | top_preds = {} 89 | dets[i, :, :2] = transform_preds( 90 | dets[i, :, 0:2], c[i], s[i], (w, h)) 91 | dets[i, :, 2:4] = transform_preds( 92 | dets[i, :, 2:4], c[i], s[i], (w, h)) 93 | classes = dets[i, :, -1] 94 | for j in range(num_classes): 95 | inds = (classes == j) 96 | top_preds[j + 1] = np.concatenate([ 97 | dets[i, inds, :4].astype(np.float32), 98 | dets[i, inds, 4:5].astype(np.float32)], axis=1).tolist() 99 | ret.append(top_preds) 100 | return ret 101 | 102 | 103 | def multi_pose_post_process(dets, c, s, h, w): 104 | # dets: batch x max_dets x 40 105 | # return list of 39 in image coord 106 | ret = [] 107 | for i in range(dets.shape[0]): 108 | bbox = transform_preds(dets[i, :, :4].reshape(-1, 2), c[i], s[i], (w, h)) 109 | pts = transform_preds(dets[i, :, 5:39].reshape(-1, 2), c[i], s[i], (w, h)) 110 | top_preds = np.concatenate( 111 | [bbox.reshape(-1, 4), dets[i, :, 4:5], 112 | pts.reshape(-1, 34)], axis=1).astype(np.float32).tolist() 113 | ret.append({np.ones(1, dtype=np.int32)[0]: top_preds}) 114 | return ret 115 | -------------------------------------------------------------------------------- /src/lib/utils/utils.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | import torch 6 | 7 | class AverageMeter(object): 8 | """Computes and stores the average and current value""" 9 | def __init__(self): 10 | self.reset() 11 | 12 | def reset(self): 13 | self.val = 0 14 | self.avg = 0 15 | self.sum = 0 16 | self.count = 0 17 | 18 | def update(self, val, n=1): 19 | self.val = val 20 | self.sum += val * n 21 | self.count += n 22 | if self.count > 0: 23 | self.avg = self.sum / self.count -------------------------------------------------------------------------------- /src/main.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | import _init_paths 6 | 7 | import os 8 | 9 | import torch 10 | import torch.utils.data 11 | from opts import opts 12 | from models.model import create_model, load_model, save_model 13 | from models.data_parallel import DataParallel 14 | from logger import Logger 15 | from datasets.dataset_factory import get_dataset 16 | from trains.train_factory import train_factory 17 | 18 | 19 | def main(opt): 20 | torch.manual_seed(opt.seed) 21 | torch.backends.cudnn.benchmark = not opt.not_cuda_benchmark and not opt.test 22 | Dataset = get_dataset(opt.dataset, opt.task) 23 | opt = opts().update_dataset_info_and_set_heads(opt, Dataset) 24 | print(opt) 25 | 26 | logger = Logger(opt) 27 | 28 | os.environ['CUDA_VISIBLE_DEVICES'] = opt.gpus_str 29 | opt.device = torch.device('cuda' if opt.gpus[0] >= 0 else 'cpu') 30 | 31 | print('Creating model...') 32 | model = create_model(opt.arch, opt.heads, opt.head_conv) 33 | optimizer = torch.optim.Adam(model.parameters(), opt.lr) 34 | start_epoch = 0 35 | if opt.load_model != '': 36 | model, optimizer, start_epoch = load_model( 37 | model, opt.load_model, optimizer, opt.resume, opt.lr, opt.lr_step) 38 | 39 | Trainer = train_factory[opt.task] 40 | trainer = Trainer(opt, model, optimizer) 41 | trainer.set_device(opt.gpus, opt.chunk_sizes, opt.device) 42 | 43 | print('Setting up data...') 44 | val_loader = torch.utils.data.DataLoader( 45 | Dataset(opt, 'val'), 46 | batch_size=1, 47 | shuffle=False, 48 | num_workers=1, 49 | pin_memory=True 50 | ) 51 | 52 | if opt.test: 53 | _, preds = trainer.val(0, val_loader) 54 | val_loader.dataset.run_eval(preds, opt.save_dir) 55 | return 56 | 57 | train_loader = torch.utils.data.DataLoader( 58 | Dataset(opt, 'train'), 59 | batch_size=opt.batch_size, 60 | shuffle=True, 61 | num_workers=opt.num_workers, 62 | pin_memory=True, 63 | drop_last=True 64 | ) 65 | 66 | print('Starting training...') 67 | best = 1e10 68 | for epoch in range(start_epoch + 1, opt.num_epochs + 1): 69 | mark = epoch if opt.save_all else 'last' 70 | log_dict_train, _ = trainer.train(epoch, train_loader) 71 | logger.write('epoch: {} |'.format(epoch)) 72 | for k, v in log_dict_train.items(): 73 | logger.scalar_summary('train_{}'.format(k), v, epoch) 74 | logger.write('{} {:8f} | '.format(k, v)) 75 | if opt.val_intervals > 0 and epoch % opt.val_intervals == 0: 76 | save_model(os.path.join(opt.save_dir, 'model_{}.pth'.format(mark)), 77 | epoch, model, optimizer) 78 | with torch.no_grad(): 79 | log_dict_val, preds = trainer.val(epoch, val_loader) 80 | for k, v in log_dict_val.items(): 81 | logger.scalar_summary('val_{}'.format(k), v, epoch) 82 | logger.write('{} {:8f} | '.format(k, v)) 83 | if log_dict_val[opt.metric] < best: 84 | best = log_dict_val[opt.metric] 85 | save_model(os.path.join(opt.save_dir, 'model_best.pth'), 86 | epoch, model) 87 | else: 88 | save_model(os.path.join(opt.save_dir, 'model_last.pth'), 89 | epoch, model, optimizer) 90 | logger.write('\n') 91 | if epoch in opt.lr_step: 92 | save_model(os.path.join(opt.save_dir, 'model_{}.pth'.format(epoch)), 93 | epoch, model, optimizer) 94 | lr = opt.lr * (0.1 ** (opt.lr_step.index(epoch) + 1)) 95 | print('Drop LR to', lr) 96 | for param_group in optimizer.param_groups: 97 | param_group['lr'] = lr 98 | logger.close() 99 | 100 | if __name__ == '__main__': 101 | opt = opts().parse() 102 | main(opt) -------------------------------------------------------------------------------- /src/test.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | import _init_paths 6 | 7 | import os 8 | import json 9 | import cv2 10 | import numpy as np 11 | import time 12 | from progress.bar import Bar 13 | import torch 14 | 15 | from external.nms import soft_nms 16 | from opts import opts 17 | from logger import Logger 18 | from utils.utils import AverageMeter 19 | from datasets.dataset_factory import dataset_factory 20 | from detectors.detector_factory import detector_factory 21 | 22 | class PrefetchDataset(torch.utils.data.Dataset): 23 | def __init__(self, opt, dataset, pre_process_func): 24 | self.images = dataset.images 25 | self.load_image_func = dataset.coco.loadImgs 26 | self.img_dir = dataset.img_dir 27 | self.pre_process_func = pre_process_func 28 | self.opt = opt 29 | 30 | def __getitem__(self, index): 31 | img_id = self.images[index] 32 | img_info = self.load_image_func(ids=[img_id])[0] 33 | img_path = os.path.join(self.img_dir, img_info['file_name']) 34 | image = cv2.imread(img_path) 35 | images, meta = {}, {} 36 | for scale in opt.test_scales: 37 | if opt.task == 'ddd': 38 | images[scale], meta[scale] = self.pre_process_func( 39 | image, scale, img_info['calib']) 40 | else: 41 | images[scale], meta[scale] = self.pre_process_func(image, scale) 42 | return img_id, {'images': images, 'image': image, 'meta': meta} 43 | 44 | def __len__(self): 45 | return len(self.images) 46 | 47 | def prefetch_test(opt): 48 | os.environ['CUDA_VISIBLE_DEVICES'] = opt.gpus_str 49 | 50 | Dataset = dataset_factory[opt.dataset] 51 | opt = opts().update_dataset_info_and_set_heads(opt, Dataset) 52 | print(opt) 53 | Logger(opt) 54 | Detector = detector_factory[opt.task] 55 | 56 | split = 'val' if not opt.trainval else 'test' 57 | dataset = Dataset(opt, split) 58 | detector = Detector(opt) 59 | 60 | data_loader = torch.utils.data.DataLoader( 61 | PrefetchDataset(opt, dataset, detector.pre_process), 62 | batch_size=1, shuffle=False, num_workers=1, pin_memory=True) 63 | 64 | results = {} 65 | num_iters = len(dataset) 66 | bar = Bar('{}'.format(opt.exp_id), max=num_iters) 67 | time_stats = ['tot', 'load', 'pre', 'net', 'dec', 'post', 'merge'] 68 | avg_time_stats = {t: AverageMeter() for t in time_stats} 69 | for ind, (img_id, pre_processed_images) in enumerate(data_loader): 70 | ret = detector.run(pre_processed_images) 71 | results[img_id.numpy().astype(np.int32)[0]] = ret['results'] 72 | Bar.suffix = '[{0}/{1}]|Tot: {total:} |ETA: {eta:} '.format( 73 | ind, num_iters, total=bar.elapsed_td, eta=bar.eta_td) 74 | for t in avg_time_stats: 75 | avg_time_stats[t].update(ret[t]) 76 | Bar.suffix = Bar.suffix + '|{} {tm.val:.3f}s ({tm.avg:.3f}s) '.format( 77 | t, tm = avg_time_stats[t]) 78 | bar.next() 79 | bar.finish() 80 | dataset.run_eval(results, opt.save_dir) 81 | 82 | def test(opt): 83 | os.environ['CUDA_VISIBLE_DEVICES'] = opt.gpus_str 84 | 85 | Dataset = dataset_factory[opt.dataset] 86 | opt = opts().update_dataset_info_and_set_heads(opt, Dataset) 87 | print(opt) 88 | Logger(opt) 89 | Detector = detector_factory[opt.task] 90 | 91 | split = 'val' if not opt.trainval else 'test' 92 | dataset = Dataset(opt, split) 93 | detector = Detector(opt) 94 | 95 | results = {} 96 | num_iters = len(dataset) 97 | bar = Bar('{}'.format(opt.exp_id), max=num_iters) 98 | time_stats = ['tot', 'load', 'pre', 'net', 'dec', 'post', 'merge'] 99 | avg_time_stats = {t: AverageMeter() for t in time_stats} 100 | for ind in range(num_iters): 101 | img_id = dataset.images[ind] 102 | img_info = dataset.coco.loadImgs(ids=[img_id])[0] 103 | img_path = os.path.join(dataset.img_dir, img_info['file_name']) 104 | 105 | if opt.task == 'ddd': 106 | ret = detector.run(img_path, img_info['calib']) 107 | else: 108 | ret = detector.run(img_path) 109 | 110 | results[img_id] = ret['results'] 111 | 112 | Bar.suffix = '[{0}/{1}]|Tot: {total:} |ETA: {eta:} '.format( 113 | ind, num_iters, total=bar.elapsed_td, eta=bar.eta_td) 114 | for t in avg_time_stats: 115 | avg_time_stats[t].update(ret[t]) 116 | Bar.suffix = Bar.suffix + '|{} {:.3f} '.format(t, avg_time_stats[t].avg) 117 | bar.next() 118 | bar.finish() 119 | dataset.run_eval(results, opt.save_dir) 120 | 121 | if __name__ == '__main__': 122 | opt = opts().parse() 123 | if opt.not_prefetch_test: 124 | test(opt) 125 | else: 126 | prefetch_test(opt) -------------------------------------------------------------------------------- /src/tools/_init_paths.py: -------------------------------------------------------------------------------- 1 | import os.path as osp 2 | import sys 3 | 4 | def add_path(path): 5 | if path not in sys.path: 6 | sys.path.insert(0, path) 7 | 8 | this_dir = osp.dirname(__file__) 9 | 10 | # Add lib to PYTHONPATH 11 | lib_path = osp.join(this_dir, '../lib') 12 | add_path(lib_path) 13 | -------------------------------------------------------------------------------- /src/tools/convert_hourglass_weight.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | MODEL_PATH = '../../models/ExtremeNet_500000.pkl' 6 | OUT_PATH = '../../models/ExtremeNet_500000.pth' 7 | 8 | import torch 9 | state_dict = torch.load(MODEL_PATH) 10 | key_map = {'t_heats': 'hm_t', 'l_heats': 'hm_l', 'b_heats': 'hm_b', \ 11 | 'r_heats': 'hm_r', 'ct_heats': 'hm_c', \ 12 | 't_regrs': 'reg_t', 'l_regrs': 'reg_l', \ 13 | 'b_regrs': 'reg_b', 'r_regrs': 'reg_r'} 14 | 15 | out = {} 16 | for k in state_dict.keys(): 17 | changed = False 18 | for m in key_map.keys(): 19 | if m in k: 20 | if 'ct_heats' in k and m == 't_heats': 21 | continue 22 | new_k = k.replace(m, key_map[m]) 23 | out[new_k] = state_dict[k] 24 | changed = True 25 | print('replace {} to {}'.format(k, new_k)) 26 | if not changed: 27 | out[k] = state_dict[k] 28 | data = {'epoch': 0, 29 | 'state_dict': out} 30 | torch.save(data, OUT_PATH) 31 | -------------------------------------------------------------------------------- /src/tools/eval_coco.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | import pycocotools.coco as coco 6 | from pycocotools.cocoeval import COCOeval 7 | import sys 8 | import cv2 9 | import numpy as np 10 | import pickle 11 | import os 12 | 13 | this_dir = os.path.dirname(__file__) 14 | ANN_PATH = this_dir + '../../data/coco/annotations/instances_val2017.json' 15 | print(ANN_PATH) 16 | if __name__ == '__main__': 17 | pred_path = sys.argv[1] 18 | coco = coco.COCO(ANN_PATH) 19 | dets = coco.loadRes(pred_path) 20 | img_ids = coco.getImgIds() 21 | num_images = len(img_ids) 22 | coco_eval = COCOeval(coco, dets, "bbox") 23 | coco_eval.evaluate() 24 | coco_eval.accumulate() 25 | coco_eval.summarize() 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/tools/eval_coco_hp.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | 5 | import pycocotools.coco as coco 6 | from pycocotools.cocoeval import COCOeval 7 | import sys 8 | import cv2 9 | import numpy as np 10 | import pickle 11 | import os 12 | 13 | this_dir = os.path.dirname(__file__) 14 | ANN_PATH = this_dir + '../../data/coco/annotations/person_keypoints_val2017.json' 15 | print(ANN_PATH) 16 | if __name__ == '__main__': 17 | pred_path = sys.argv[1] 18 | coco = coco.COCO(ANN_PATH) 19 | dets = coco.loadRes(pred_path) 20 | img_ids = coco.getImgIds() 21 | num_images = len(img_ids) 22 | coco_eval = COCOeval(coco, dets, "keypoints") 23 | coco_eval.evaluate() 24 | coco_eval.accumulate() 25 | coco_eval.summarize() 26 | coco_eval = COCOeval(coco, dets, "bbox") 27 | coco_eval.evaluate() 28 | coco_eval.accumulate() 29 | coco_eval.summarize() 30 | 31 | -------------------------------------------------------------------------------- /src/tools/get_kitti.sh: -------------------------------------------------------------------------------- 1 | mkdir kitti 2 | cd kitti 3 | wget http://www.cvlibs.net/download.php?file=data_object_image_2.zip 4 | wget http://www.cvlibs.net/download.php?file=data_object_label_2.zip 5 | wget http://www.cvlibs.net/download.php?file=data_object_calib.zip 6 | unzip data_object_image_2.zip 7 | unzip data_object_label_2.zip 8 | unzip data_object_calib.zip 9 | 10 | -------------------------------------------------------------------------------- /src/tools/get_pascal_voc.sh: -------------------------------------------------------------------------------- 1 | mkdir voc 2 | cd voc 3 | wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtrainval_06-Nov-2007.tar 4 | wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtest_06-Nov-2007.tar 5 | wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCdevkit_08-Jun-2007.tar 6 | wget http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar 7 | wget http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCdevkit_18-May-2011.tar 8 | tar xvf VOCtrainval_06-Nov-2007.tar 9 | tar xvf VOCtest_06-Nov-2007.tar 10 | tar xvf VOCdevkit_08-Jun-2007.tar 11 | tar xvf VOCtrainval_11-May-2012.tar 12 | tar xvf VOCdevkit_18-May-2011.tar 13 | rm VOCtrainval_06-Nov-2007.tar 14 | rm VOCtest_06-Nov-2007.tar 15 | rm VOCdevkit_08-Jun-2007.tar 16 | rm VOCtrainval_11-May-2012.tar 17 | rm VOCdevkit_18-May-2011.tar 18 | mkdir images 19 | cp VOCdevkit/VOC2007/JPEGImages/* images/ 20 | cp VOCdevkit/VOC2012/JPEGImages/* images/ 21 | wget https://storage.googleapis.com/coco-dataset/external/PASCAL_VOC.zip 22 | unzip PASCAL_VOC.zip 23 | rm PASCAL_VOC.zip 24 | mv PASCAL_VOC annotations/ 25 | cd .. 26 | python merge_pascal_json.py 27 | -------------------------------------------------------------------------------- /src/tools/kitti_eval/README.md: -------------------------------------------------------------------------------- 1 | # kitti_eval 2 | 3 | `evaluate_object_3d_offline.cpp`evaluates your KITTI detection locally on your own computer using your validation data selected from KITTI training dataset, with the following metrics: 4 | 5 | - overlap on image (AP) 6 | - oriented overlap on image (AOS) 7 | - overlap on ground-plane (AP) 8 | - overlap in 3D (AP) 9 | 10 | Compile `evaluate_object_3d_offline.cpp` with dependency of Boost and Linux `dirent.h` (You should already have it under most Linux). 11 | 12 | Run the evalutaion by: 13 | 14 | ./evaluate_object_3d_offline groundtruth_dir result_dir 15 | 16 | Note that you don't have to detect over all KITTI training data. The evaluator only evaluates samples whose result files exist. 17 | 18 | 19 | ### Updates 20 | 21 | - June, 2017: 22 | * Fixed the bug of detection box filtering based on min height according to KITTI's note on 25.04.2017. 23 | -------------------------------------------------------------------------------- /src/tools/kitti_eval/evaluate_object_3d_offline: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/tools/kitti_eval/evaluate_object_3d_offline -------------------------------------------------------------------------------- /src/tools/kitti_eval/mail.h: -------------------------------------------------------------------------------- 1 | #ifndef MAIL_H 2 | #define MAIL_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class Mail { 9 | 10 | public: 11 | 12 | Mail (std::string email = "") { 13 | if (email.compare("")) { 14 | mail = popen("/usr/lib/sendmail -t -f noreply@cvlibs.net","w"); 15 | fprintf(mail,"To: %s\n", email.c_str()); 16 | fprintf(mail,"From: noreply@cvlibs.net\n"); 17 | fprintf(mail,"Subject: KITTI Evaluation Benchmark\n"); 18 | fprintf(mail,"\n\n"); 19 | } else { 20 | mail = 0; 21 | } 22 | } 23 | 24 | ~Mail() { 25 | if (mail) { 26 | pclose(mail); 27 | } 28 | } 29 | 30 | void msg (const char *format, ...) { 31 | va_list args; 32 | va_start(args,format); 33 | if (mail) { 34 | vfprintf(mail,format,args); 35 | fprintf(mail,"\n"); 36 | } 37 | vprintf(format,args); 38 | printf("\n"); 39 | va_end(args); 40 | } 41 | 42 | private: 43 | 44 | FILE *mail; 45 | 46 | }; 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /src/tools/merge_pascal_json.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | # ANNOT_PATH = '/home/zxy/Datasets/VOC/annotations/' 4 | ANNOT_PATH = 'voc/annotations/' 5 | OUT_PATH = ANNOT_PATH 6 | INPUT_FILES = ['pascal_train2012.json', 'pascal_val2012.json', 7 | 'pascal_train2007.json', 'pascal_val2007.json'] 8 | OUTPUT_FILE = 'pascal_trainval0712.json' 9 | KEYS = ['images', 'type', 'annotations', 'categories'] 10 | MERGE_KEYS = ['images', 'annotations'] 11 | 12 | out = {} 13 | tot_anns = 0 14 | for i, file_name in enumerate(INPUT_FILES): 15 | data = json.load(open(ANNOT_PATH + file_name, 'r')) 16 | print('keys', data.keys()) 17 | if i == 0: 18 | for key in KEYS: 19 | out[key] = data[key] 20 | print(file_name, key, len(data[key])) 21 | else: 22 | out['images'] += data['images'] 23 | for j in range(len(data['annotations'])): 24 | data['annotations'][j]['id'] += tot_anns 25 | out['annotations'] += data['annotations'] 26 | print(file_name, 'images', len(data['images'])) 27 | print(file_name, 'annotations', len(data['annotations'])) 28 | tot_anns = len(out['annotations']) 29 | print('tot', len(out['annotations'])) 30 | json.dump(out, open(OUT_PATH + OUTPUT_FILE, 'w')) 31 | -------------------------------------------------------------------------------- /src/tools/reval.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # -------------------------------------------------------- 4 | # Fast R-CNN 5 | # Copyright (c) 2015 Microsoft 6 | # Licensed under The MIT License [see LICENSE for details] 7 | # Written by Ross Girshick 8 | # Modified by Xingyi Zhou 9 | # -------------------------------------------------------- 10 | 11 | # Reval = re-eval. Re-evaluate saved detections. 12 | from __future__ import absolute_import 13 | from __future__ import division 14 | from __future__ import print_function 15 | 16 | import sys 17 | import os.path as osp 18 | sys.path.insert(0, osp.join(osp.dirname(__file__), 'voc_eval_lib')) 19 | 20 | from model.test import apply_nms 21 | from datasets.pascal_voc import pascal_voc 22 | import pickle 23 | import os, argparse 24 | import numpy as np 25 | import json 26 | 27 | def parse_args(): 28 | """ 29 | Parse input arguments 30 | """ 31 | parser = argparse.ArgumentParser(description='Re-evaluate results') 32 | parser.add_argument('detection_file', type=str) 33 | parser.add_argument('--output_dir', help='results directory', type=str) 34 | parser.add_argument('--imdb', dest='imdb_name', 35 | help='dataset to re-evaluate', 36 | default='voc_2007_test', type=str) 37 | parser.add_argument('--matlab', dest='matlab_eval', 38 | help='use matlab for evaluation', 39 | action='store_true') 40 | parser.add_argument('--comp', dest='comp_mode', help='competition mode', 41 | action='store_true') 42 | parser.add_argument('--nms', dest='apply_nms', help='apply nms', 43 | action='store_true') 44 | 45 | if len(sys.argv) == 1: 46 | parser.print_help() 47 | sys.exit(1) 48 | 49 | args = parser.parse_args() 50 | return args 51 | 52 | 53 | def from_dets(imdb_name, detection_file, args): 54 | imdb = pascal_voc('test', '2007') 55 | imdb.competition_mode(args.comp_mode) 56 | imdb.config['matlab_eval'] = args.matlab_eval 57 | with open(os.path.join(detection_file), 'rb') as f: 58 | if 'json' in detection_file: 59 | dets = json.load(f) 60 | else: 61 | dets = pickle.load(f, encoding='latin1') 62 | # import pdb; pdb.set_trace() 63 | if args.apply_nms: 64 | print('Applying NMS to all detections') 65 | test_nms = 0.3 66 | nms_dets = apply_nms(dets, test_nms) 67 | else: 68 | nms_dets = dets 69 | 70 | print('Evaluating detections') 71 | imdb.evaluate_detections(nms_dets) 72 | 73 | 74 | if __name__ == '__main__': 75 | args = parse_args() 76 | 77 | imdb_name = args.imdb_name 78 | from_dets(imdb_name, args.detection_file, args) 79 | -------------------------------------------------------------------------------- /src/tools/vis_pred.py: -------------------------------------------------------------------------------- 1 | import pycocotools.coco as coco 2 | from pycocotools.cocoeval import COCOeval 3 | import sys 4 | import cv2 5 | import numpy as np 6 | import pickle 7 | IMG_PATH = '../../data/coco/val2017/' 8 | ANN_PATH = '../../data/coco/annotations/instances_val2017.json' 9 | DEBUG = True 10 | 11 | def _coco_box_to_bbox(box): 12 | bbox = np.array([box[0], box[1], box[0] + box[2], box[1] + box[3]], 13 | dtype=np.int32) 14 | return bbox 15 | 16 | _cat_ids = [ 17 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 18 | 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 19 | 24, 25, 27, 28, 31, 32, 33, 34, 35, 36, 20 | 37, 38, 39, 40, 41, 42, 43, 44, 46, 47, 21 | 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 22 | 58, 59, 60, 61, 62, 63, 64, 65, 67, 70, 23 | 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 24 | 82, 84, 85, 86, 87, 88, 89, 90 25 | ] 26 | num_classes = 80 27 | _classes = { 28 | ind + 1: cat_id for ind, cat_id in enumerate(_cat_ids) 29 | } 30 | _to_order = {cat_id: ind for ind, cat_id in enumerate(_cat_ids)} 31 | coco = coco.COCO(ANN_PATH) 32 | CAT_NAMES = [coco.loadCats([_classes[i + 1]])[0]['name'] \ 33 | for i in range(num_classes)] 34 | COLORS = [((np.random.random((3, )) * 0.6 + 0.4)*255).astype(np.uint8) \ 35 | for _ in range(num_classes)] 36 | 37 | 38 | def add_box(image, bbox, sc, cat_id): 39 | cat_id = _to_order[cat_id] 40 | cat_name = CAT_NAMES[cat_id] 41 | cat_size = cv2.getTextSize(cat_name + '0', cv2.FONT_HERSHEY_SIMPLEX, 0.5, 2)[0] 42 | color = np.array(COLORS[cat_id]).astype(np.int32).tolist() 43 | txt = '{}{:.0f}'.format(cat_name, sc * 10) 44 | if bbox[1] - cat_size[1] - 2 < 0: 45 | cv2.rectangle(image, 46 | (bbox[0], bbox[1] + 2), 47 | (bbox[0] + cat_size[0], bbox[1] + cat_size[1] + 2), 48 | color, -1) 49 | cv2.putText(image, txt, 50 | (bbox[0], bbox[1] + cat_size[1] + 2), 51 | cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), thickness=1) 52 | else: 53 | cv2.rectangle(image, 54 | (bbox[0], bbox[1] - cat_size[1] - 2), 55 | (bbox[0] + cat_size[0], bbox[1] - 2), 56 | color, -1) 57 | cv2.putText(image, txt, 58 | (bbox[0], bbox[1] - 2), 59 | cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), thickness=1) 60 | cv2.rectangle(image, 61 | (bbox[0], bbox[1]), 62 | (bbox[2], bbox[3]), 63 | color, 2) 64 | return image 65 | 66 | if __name__ == '__main__': 67 | dets = [] 68 | img_ids = coco.getImgIds() 69 | num_images = len(img_ids) 70 | for k in range(1, len(sys.argv)): 71 | pred_path = sys.argv[k] 72 | dets.append(coco.loadRes(pred_path)) 73 | # import pdb; pdb.set_trace() 74 | for i, img_id in enumerate(img_ids): 75 | img_info = coco.loadImgs(ids=[img_id])[0] 76 | img_path = IMG_PATH + img_info['file_name'] 77 | img = cv2.imread(img_path) 78 | gt_ids = coco.getAnnIds(imgIds=[img_id]) 79 | gts = coco.loadAnns(gt_ids) 80 | gt_img = img.copy() 81 | for j, pred in enumerate(gts): 82 | bbox = _coco_box_to_bbox(pred['bbox']) 83 | cat_id = pred['category_id'] 84 | gt_img = add_box(gt_img, bbox, 0, cat_id) 85 | for k in range(len(dets)): 86 | pred_ids = dets[k].getAnnIds(imgIds=[img_id]) 87 | preds = dets[k].loadAnns(pred_ids) 88 | pred_img = img.copy() 89 | for j, pred in enumerate(preds): 90 | bbox = _coco_box_to_bbox(pred['bbox']) 91 | sc = pred['score'] 92 | cat_id = pred['category_id'] 93 | if sc > 0.2: 94 | pred_img = add_box(pred_img, bbox, sc, cat_id) 95 | cv2.imshow('pred{}'.format(k), pred_img) 96 | # cv2.imwrite('vis/{}_pred{}.png'.format(i, k), pred_img) 97 | cv2.imshow('gt', gt_img) 98 | # cv2.imwrite('vis/{}_gt.png'.format(i), gt_img) 99 | cv2.waitKey() 100 | # coco_eval.evaluate() 101 | # coco_eval.accumulate() 102 | # coco_eval.summarize() 103 | 104 | 105 | -------------------------------------------------------------------------------- /src/tools/voc_eval_lib/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Xinlei Chen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/tools/voc_eval_lib/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | python setup.py build_ext --inplace 3 | rm -rf build 4 | clean: 5 | rm -rf */*.pyc 6 | rm -rf */*.so 7 | -------------------------------------------------------------------------------- /src/tools/voc_eval_lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/tools/voc_eval_lib/__init__.py -------------------------------------------------------------------------------- /src/tools/voc_eval_lib/datasets/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/tools/voc_eval_lib/datasets/__init__.py -------------------------------------------------------------------------------- /src/tools/voc_eval_lib/datasets/bbox.pyx: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------- 2 | # Fast R-CNN 3 | # Copyright (c) 2015 Microsoft 4 | # Licensed under The MIT License [see LICENSE for details] 5 | # Written by Sergey Karayev 6 | # -------------------------------------------------------- 7 | 8 | cimport cython 9 | import numpy as np 10 | cimport numpy as np 11 | 12 | DTYPE = np.float 13 | ctypedef np.float_t DTYPE_t 14 | 15 | def bbox_overlaps( 16 | np.ndarray[DTYPE_t, ndim=2] boxes, 17 | np.ndarray[DTYPE_t, ndim=2] query_boxes): 18 | """ 19 | Parameters 20 | ---------- 21 | boxes: (N, 4) ndarray of float 22 | query_boxes: (K, 4) ndarray of float 23 | Returns 24 | ------- 25 | overlaps: (N, K) ndarray of overlap between boxes and query_boxes 26 | """ 27 | cdef unsigned int N = boxes.shape[0] 28 | cdef unsigned int K = query_boxes.shape[0] 29 | cdef np.ndarray[DTYPE_t, ndim=2] overlaps = np.zeros((N, K), dtype=DTYPE) 30 | cdef DTYPE_t iw, ih, box_area 31 | cdef DTYPE_t ua 32 | cdef unsigned int k, n 33 | for k in range(K): 34 | box_area = ( 35 | (query_boxes[k, 2] - query_boxes[k, 0] + 1) * 36 | (query_boxes[k, 3] - query_boxes[k, 1] + 1) 37 | ) 38 | for n in range(N): 39 | iw = ( 40 | min(boxes[n, 2], query_boxes[k, 2]) - 41 | max(boxes[n, 0], query_boxes[k, 0]) + 1 42 | ) 43 | if iw > 0: 44 | ih = ( 45 | min(boxes[n, 3], query_boxes[k, 3]) - 46 | max(boxes[n, 1], query_boxes[k, 1]) + 1 47 | ) 48 | if ih > 0: 49 | ua = float( 50 | (boxes[n, 2] - boxes[n, 0] + 1) * 51 | (boxes[n, 3] - boxes[n, 1] + 1) + 52 | box_area - iw * ih 53 | ) 54 | overlaps[n, k] = iw * ih / ua 55 | return overlaps 56 | 57 | -------------------------------------------------------------------------------- /src/tools/voc_eval_lib/datasets/ds_utils.py: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------- 2 | # Fast/er R-CNN 3 | # Licensed under The MIT License [see LICENSE for details] 4 | # Written by Ross Girshick 5 | # -------------------------------------------------------- 6 | from __future__ import absolute_import 7 | from __future__ import division 8 | from __future__ import print_function 9 | 10 | import numpy as np 11 | 12 | 13 | def unique_boxes(boxes, scale=1.0): 14 | """Return indices of unique boxes.""" 15 | v = np.array([1, 1e3, 1e6, 1e9]) 16 | hashes = np.round(boxes * scale).dot(v) 17 | _, index = np.unique(hashes, return_index=True) 18 | return np.sort(index) 19 | 20 | 21 | def xywh_to_xyxy(boxes): 22 | """Convert [x y w h] box format to [x1 y1 x2 y2] format.""" 23 | return np.hstack((boxes[:, 0:2], boxes[:, 0:2] + boxes[:, 2:4] - 1)) 24 | 25 | 26 | def xyxy_to_xywh(boxes): 27 | """Convert [x1 y1 x2 y2] box format to [x y w h] format.""" 28 | return np.hstack((boxes[:, 0:2], boxes[:, 2:4] - boxes[:, 0:2] + 1)) 29 | 30 | 31 | def validate_boxes(boxes, width=0, height=0): 32 | """Check that a set of boxes are valid.""" 33 | x1 = boxes[:, 0] 34 | y1 = boxes[:, 1] 35 | x2 = boxes[:, 2] 36 | y2 = boxes[:, 3] 37 | assert (x1 >= 0).all() 38 | assert (y1 >= 0).all() 39 | assert (x2 >= x1).all() 40 | assert (y2 >= y1).all() 41 | assert (x2 < width).all() 42 | assert (y2 < height).all() 43 | 44 | 45 | def filter_small_boxes(boxes, min_size): 46 | w = boxes[:, 2] - boxes[:, 0] 47 | h = boxes[:, 3] - boxes[:, 1] 48 | keep = np.where((w >= min_size) & (h > min_size))[0] 49 | return keep 50 | -------------------------------------------------------------------------------- /src/tools/voc_eval_lib/model/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/tools/voc_eval_lib/model/__init__.py -------------------------------------------------------------------------------- /src/tools/voc_eval_lib/model/bbox_transform.py: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------- 2 | # Fast R-CNN 3 | # Copyright (c) 2015 Microsoft 4 | # Licensed under The MIT License [see LICENSE for details] 5 | # Written by Ross Girshick 6 | # -------------------------------------------------------- 7 | from __future__ import absolute_import 8 | from __future__ import division 9 | from __future__ import print_function 10 | 11 | import numpy as np 12 | 13 | def bbox_transform(ex_rois, gt_rois): 14 | ex_widths = ex_rois[:, 2] - ex_rois[:, 0] + 1.0 15 | ex_heights = ex_rois[:, 3] - ex_rois[:, 1] + 1.0 16 | ex_ctr_x = ex_rois[:, 0] + 0.5 * ex_widths 17 | ex_ctr_y = ex_rois[:, 1] + 0.5 * ex_heights 18 | 19 | gt_widths = gt_rois[:, 2] - gt_rois[:, 0] + 1.0 20 | gt_heights = gt_rois[:, 3] - gt_rois[:, 1] + 1.0 21 | gt_ctr_x = gt_rois[:, 0] + 0.5 * gt_widths 22 | gt_ctr_y = gt_rois[:, 1] + 0.5 * gt_heights 23 | 24 | targets_dx = (gt_ctr_x - ex_ctr_x) / ex_widths 25 | targets_dy = (gt_ctr_y - ex_ctr_y) / ex_heights 26 | targets_dw = np.log(gt_widths / ex_widths) 27 | targets_dh = np.log(gt_heights / ex_heights) 28 | 29 | targets = np.vstack( 30 | (targets_dx, targets_dy, targets_dw, targets_dh)).transpose() 31 | return targets 32 | 33 | 34 | def bbox_transform_inv(boxes, deltas): 35 | if boxes.shape[0] == 0: 36 | return np.zeros((0, deltas.shape[1]), dtype=deltas.dtype) 37 | 38 | boxes = boxes.astype(deltas.dtype, copy=False) 39 | widths = boxes[:, 2] - boxes[:, 0] + 1.0 40 | heights = boxes[:, 3] - boxes[:, 1] + 1.0 41 | ctr_x = boxes[:, 0] + 0.5 * widths 42 | ctr_y = boxes[:, 1] + 0.5 * heights 43 | 44 | dx = deltas[:, 0::4] 45 | dy = deltas[:, 1::4] 46 | dw = deltas[:, 2::4] 47 | dh = deltas[:, 3::4] 48 | 49 | pred_ctr_x = dx * widths[:, np.newaxis] + ctr_x[:, np.newaxis] 50 | pred_ctr_y = dy * heights[:, np.newaxis] + ctr_y[:, np.newaxis] 51 | pred_w = np.exp(dw) * widths[:, np.newaxis] 52 | pred_h = np.exp(dh) * heights[:, np.newaxis] 53 | 54 | pred_boxes = np.zeros(deltas.shape, dtype=deltas.dtype) 55 | # x1 56 | pred_boxes[:, 0::4] = pred_ctr_x - 0.5 * pred_w 57 | # y1 58 | pred_boxes[:, 1::4] = pred_ctr_y - 0.5 * pred_h 59 | # x2 60 | pred_boxes[:, 2::4] = pred_ctr_x + 0.5 * pred_w 61 | # y2 62 | pred_boxes[:, 3::4] = pred_ctr_y + 0.5 * pred_h 63 | 64 | return pred_boxes 65 | 66 | 67 | def clip_boxes(boxes, im_shape): 68 | """ 69 | Clip boxes to image boundaries. 70 | """ 71 | 72 | # x1 >= 0 73 | boxes[:, 0::4] = np.maximum(np.minimum(boxes[:, 0::4], im_shape[1] - 1), 0) 74 | # y1 >= 0 75 | boxes[:, 1::4] = np.maximum(np.minimum(boxes[:, 1::4], im_shape[0] - 1), 0) 76 | # x2 < im_shape[1] 77 | boxes[:, 2::4] = np.maximum(np.minimum(boxes[:, 2::4], im_shape[1] - 1), 0) 78 | # y2 < im_shape[0] 79 | boxes[:, 3::4] = np.maximum(np.minimum(boxes[:, 3::4], im_shape[0] - 1), 0) 80 | return boxes 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /src/tools/voc_eval_lib/model/nms_wrapper.py: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------- 2 | # Fast R-CNN 3 | # Copyright (c) 2015 Microsoft 4 | # Licensed under The MIT License [see LICENSE for details] 5 | # Written by Ross Girshick 6 | # -------------------------------------------------------- 7 | from __future__ import absolute_import 8 | from __future__ import division 9 | from __future__ import print_function 10 | 11 | from model.config import cfg 12 | from nms.gpu_nms import gpu_nms 13 | from nms.cpu_nms import cpu_nms 14 | 15 | def nms(dets, thresh, force_cpu=False): 16 | """Dispatch to either CPU or GPU NMS implementations.""" 17 | 18 | if dets.shape[0] == 0: 19 | return [] 20 | if cfg.USE_GPU_NMS and not force_cpu: 21 | return gpu_nms(dets, thresh, device_id=0) 22 | else: 23 | return cpu_nms(dets, thresh) 24 | -------------------------------------------------------------------------------- /src/tools/voc_eval_lib/nms/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/tools/voc_eval_lib/nms/.gitignore -------------------------------------------------------------------------------- /src/tools/voc_eval_lib/nms/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanglaotou/centernet_ncnn/31f82063215ef8391a90a0f6901e4787d71871f7/src/tools/voc_eval_lib/nms/__init__.py -------------------------------------------------------------------------------- /src/tools/voc_eval_lib/nms/cpu_nms.pyx: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------- 2 | # Fast R-CNN 3 | # Copyright (c) 2015 Microsoft 4 | # Licensed under The MIT License [see LICENSE for details] 5 | # Written by Ross Girshick 6 | # -------------------------------------------------------- 7 | 8 | import numpy as np 9 | cimport numpy as np 10 | 11 | cdef inline np.float32_t max(np.float32_t a, np.float32_t b): 12 | return a if a >= b else b 13 | 14 | cdef inline np.float32_t min(np.float32_t a, np.float32_t b): 15 | return a if a <= b else b 16 | 17 | def cpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh): 18 | cdef np.ndarray[np.float32_t, ndim=1] x1 = dets[:, 0] 19 | cdef np.ndarray[np.float32_t, ndim=1] y1 = dets[:, 1] 20 | cdef np.ndarray[np.float32_t, ndim=1] x2 = dets[:, 2] 21 | cdef np.ndarray[np.float32_t, ndim=1] y2 = dets[:, 3] 22 | cdef np.ndarray[np.float32_t, ndim=1] scores = dets[:, 4] 23 | 24 | cdef np.ndarray[np.float32_t, ndim=1] areas = (x2 - x1 + 1) * (y2 - y1 + 1) 25 | cdef np.ndarray[np.int_t, ndim=1] order = scores.argsort()[::-1] 26 | 27 | cdef int ndets = dets.shape[0] 28 | cdef np.ndarray[np.int_t, ndim=1] suppressed = \ 29 | np.zeros((ndets), dtype=np.int) 30 | 31 | # nominal indices 32 | cdef int _i, _j 33 | # sorted indices 34 | cdef int i, j 35 | # temp variables for box i's (the box currently under consideration) 36 | cdef np.float32_t ix1, iy1, ix2, iy2, iarea 37 | # variables for computing overlap with box j (lower scoring box) 38 | cdef np.float32_t xx1, yy1, xx2, yy2 39 | cdef np.float32_t w, h 40 | cdef np.float32_t inter, ovr 41 | 42 | keep = [] 43 | for _i in range(ndets): 44 | i = order[_i] 45 | if suppressed[i] == 1: 46 | continue 47 | keep.append(i) 48 | ix1 = x1[i] 49 | iy1 = y1[i] 50 | ix2 = x2[i] 51 | iy2 = y2[i] 52 | iarea = areas[i] 53 | for _j in range(_i + 1, ndets): 54 | j = order[_j] 55 | if suppressed[j] == 1: 56 | continue 57 | xx1 = max(ix1, x1[j]) 58 | yy1 = max(iy1, y1[j]) 59 | xx2 = min(ix2, x2[j]) 60 | yy2 = min(iy2, y2[j]) 61 | w = max(0.0, xx2 - xx1 + 1) 62 | h = max(0.0, yy2 - yy1 + 1) 63 | inter = w * h 64 | ovr = inter / (iarea + areas[j] - inter) 65 | if ovr >= thresh: 66 | suppressed[j] = 1 67 | 68 | return keep 69 | -------------------------------------------------------------------------------- /src/tools/voc_eval_lib/nms/gpu_nms.hpp: -------------------------------------------------------------------------------- 1 | void _nms(int* keep_out, int* num_out, const float* boxes_host, int boxes_num, 2 | int boxes_dim, float nms_overlap_thresh, int device_id); 3 | -------------------------------------------------------------------------------- /src/tools/voc_eval_lib/nms/gpu_nms.pyx: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------- 2 | # Faster R-CNN 3 | # Copyright (c) 2015 Microsoft 4 | # Licensed under The MIT License [see LICENSE for details] 5 | # Written by Ross Girshick 6 | # -------------------------------------------------------- 7 | 8 | import numpy as np 9 | cimport numpy as np 10 | 11 | assert sizeof(int) == sizeof(np.int32_t) 12 | 13 | cdef extern from "gpu_nms.hpp": 14 | void _nms(np.int32_t*, int*, np.float32_t*, int, int, float, int) 15 | 16 | def gpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh, 17 | np.int32_t device_id=0): 18 | cdef int boxes_num = dets.shape[0] 19 | cdef int boxes_dim = dets.shape[1] 20 | cdef int num_out 21 | cdef np.ndarray[np.int32_t, ndim=1] \ 22 | keep = np.zeros(boxes_num, dtype=np.int32) 23 | cdef np.ndarray[np.float32_t, ndim=1] \ 24 | scores = dets[:, 4] 25 | cdef np.ndarray[np.int_t, ndim=1] \ 26 | order = scores.argsort()[::-1] 27 | cdef np.ndarray[np.float32_t, ndim=2] \ 28 | sorted_dets = dets[order, :] 29 | _nms(&keep[0], &num_out, &sorted_dets[0, 0], boxes_num, boxes_dim, thresh, device_id) 30 | keep = keep[:num_out] 31 | return list(order[keep]) 32 | -------------------------------------------------------------------------------- /src/tools/voc_eval_lib/nms/py_cpu_nms.py: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------- 2 | # Fast R-CNN 3 | # Copyright (c) 2015 Microsoft 4 | # Licensed under The MIT License [see LICENSE for details] 5 | # Written by Ross Girshick 6 | # -------------------------------------------------------- 7 | 8 | import numpy as np 9 | 10 | def py_cpu_nms(dets, thresh): 11 | """Pure Python NMS baseline.""" 12 | x1 = dets[:, 0] 13 | y1 = dets[:, 1] 14 | x2 = dets[:, 2] 15 | y2 = dets[:, 3] 16 | scores = dets[:, 4] 17 | 18 | areas = (x2 - x1 + 1) * (y2 - y1 + 1) 19 | order = scores.argsort()[::-1] 20 | 21 | keep = [] 22 | while order.size > 0: 23 | i = order[0] 24 | keep.append(i) 25 | xx1 = np.maximum(x1[i], x1[order[1:]]) 26 | yy1 = np.maximum(y1[i], y1[order[1:]]) 27 | xx2 = np.minimum(x2[i], x2[order[1:]]) 28 | yy2 = np.minimum(y2[i], y2[order[1:]]) 29 | 30 | w = np.maximum(0.0, xx2 - xx1 + 1) 31 | h = np.maximum(0.0, yy2 - yy1 + 1) 32 | inter = w * h 33 | ovr = inter / (areas[i] + areas[order[1:]] - inter) 34 | 35 | inds = np.where(ovr <= thresh)[0] 36 | order = order[inds + 1] 37 | 38 | return keep 39 | -------------------------------------------------------------------------------- /src/tools/voc_eval_lib/utils/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | *.cpp 3 | *.h 4 | *.hpp 5 | -------------------------------------------------------------------------------- /src/tools/voc_eval_lib/utils/__init__.py: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------- 2 | # Fast R-CNN 3 | # Copyright (c) 2015 Microsoft 4 | # Licensed under The MIT License [see LICENSE for details] 5 | # Written by Ross Girshick 6 | # -------------------------------------------------------- 7 | -------------------------------------------------------------------------------- /src/tools/voc_eval_lib/utils/bbox.pyx: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------- 2 | # Fast R-CNN 3 | # Copyright (c) 2015 Microsoft 4 | # Licensed under The MIT License [see LICENSE for details] 5 | # Written by Sergey Karayev 6 | # -------------------------------------------------------- 7 | 8 | cimport cython 9 | import numpy as np 10 | cimport numpy as np 11 | 12 | DTYPE = np.float 13 | ctypedef np.float_t DTYPE_t 14 | 15 | def bbox_overlaps( 16 | np.ndarray[DTYPE_t, ndim=2] boxes, 17 | np.ndarray[DTYPE_t, ndim=2] query_boxes): 18 | """ 19 | Parameters 20 | ---------- 21 | boxes: (N, 4) ndarray of float 22 | query_boxes: (K, 4) ndarray of float 23 | Returns 24 | ------- 25 | overlaps: (N, K) ndarray of overlap between boxes and query_boxes 26 | """ 27 | cdef unsigned int N = boxes.shape[0] 28 | cdef unsigned int K = query_boxes.shape[0] 29 | cdef np.ndarray[DTYPE_t, ndim=2] overlaps = np.zeros((N, K), dtype=DTYPE) 30 | cdef DTYPE_t iw, ih, box_area 31 | cdef DTYPE_t ua 32 | cdef unsigned int k, n 33 | for k in range(K): 34 | box_area = ( 35 | (query_boxes[k, 2] - query_boxes[k, 0] + 1) * 36 | (query_boxes[k, 3] - query_boxes[k, 1] + 1) 37 | ) 38 | for n in range(N): 39 | iw = ( 40 | min(boxes[n, 2], query_boxes[k, 2]) - 41 | max(boxes[n, 0], query_boxes[k, 0]) + 1 42 | ) 43 | if iw > 0: 44 | ih = ( 45 | min(boxes[n, 3], query_boxes[k, 3]) - 46 | max(boxes[n, 1], query_boxes[k, 1]) + 1 47 | ) 48 | if ih > 0: 49 | ua = float( 50 | (boxes[n, 2] - boxes[n, 0] + 1) * 51 | (boxes[n, 3] - boxes[n, 1] + 1) + 52 | box_area - iw * ih 53 | ) 54 | overlaps[n, k] = iw * ih / ua 55 | return overlaps 56 | 57 | -------------------------------------------------------------------------------- /src/tools/voc_eval_lib/utils/blob.py: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------- 2 | # Fast R-CNN 3 | # Copyright (c) 2015 Microsoft 4 | # Licensed under The MIT License [see LICENSE for details] 5 | # Written by Ross Girshick 6 | # -------------------------------------------------------- 7 | 8 | """Blob helper functions.""" 9 | from __future__ import absolute_import 10 | from __future__ import division 11 | from __future__ import print_function 12 | 13 | import numpy as np 14 | import cv2 15 | 16 | 17 | def im_list_to_blob(ims): 18 | """Convert a list of images into a network input. 19 | 20 | Assumes images are already prepared (means subtracted, BGR order, ...). 21 | """ 22 | max_shape = np.array([im.shape for im in ims]).max(axis=0) 23 | num_images = len(ims) 24 | blob = np.zeros((num_images, max_shape[0], max_shape[1], 3), 25 | dtype=np.float32) 26 | for i in range(num_images): 27 | im = ims[i] 28 | blob[i, 0:im.shape[0], 0:im.shape[1], :] = im 29 | 30 | return blob 31 | 32 | 33 | def prep_im_for_blob(im, pixel_means, target_size, max_size): 34 | """Mean subtract and scale an image for use in a blob.""" 35 | im = im.astype(np.float32, copy=False) 36 | im -= pixel_means 37 | im_shape = im.shape 38 | im_size_min = np.min(im_shape[0:2]) 39 | im_size_max = np.max(im_shape[0:2]) 40 | im_scale = float(target_size) / float(im_size_min) 41 | # Prevent the biggest axis from being more than MAX_SIZE 42 | if np.round(im_scale * im_size_max) > max_size: 43 | im_scale = float(max_size) / float(im_size_max) 44 | im = cv2.resize(im, None, None, fx=im_scale, fy=im_scale, 45 | interpolation=cv2.INTER_LINEAR) 46 | 47 | return im, im_scale 48 | -------------------------------------------------------------------------------- /src/tools/voc_eval_lib/utils/timer.py: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------- 2 | # Fast R-CNN 3 | # Copyright (c) 2015 Microsoft 4 | # Licensed under The MIT License [see LICENSE for details] 5 | # Written by Ross Girshick 6 | # -------------------------------------------------------- 7 | 8 | import time 9 | 10 | class Timer(object): 11 | """A simple timer.""" 12 | def __init__(self): 13 | self.total_time = 0. 14 | self.calls = 0 15 | self.start_time = 0. 16 | self.diff = 0. 17 | self.average_time = 0. 18 | 19 | def tic(self): 20 | # using time.time instead of time.clock because time time.clock 21 | # does not normalize for multithreading 22 | self.start_time = time.time() 23 | 24 | def toc(self, average=True): 25 | self.diff = time.time() - self.start_time 26 | self.total_time += self.diff 27 | self.calls += 1 28 | self.average_time = self.total_time / self.calls 29 | if average: 30 | return self.average_time 31 | else: 32 | return self.diff 33 | -------------------------------------------------------------------------------- /src/tools/voc_eval_lib/utils/visualization.py: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------- 2 | # Tensorflow Faster R-CNN 3 | # Licensed under The MIT License [see LICENSE for details] 4 | # Written by Xinlei Chen 5 | # -------------------------------------------------------- 6 | from __future__ import absolute_import 7 | from __future__ import division 8 | from __future__ import print_function 9 | 10 | import numpy as np 11 | from six.moves import range 12 | import PIL.Image as Image 13 | import PIL.ImageColor as ImageColor 14 | import PIL.ImageDraw as ImageDraw 15 | import PIL.ImageFont as ImageFont 16 | 17 | STANDARD_COLORS = [ 18 | 'AliceBlue', 'Chartreuse', 'Aqua', 'Aquamarine', 'Azure', 'Beige', 'Bisque', 19 | 'BlanchedAlmond', 'BlueViolet', 'BurlyWood', 'CadetBlue', 'AntiqueWhite', 20 | 'Chocolate', 'Coral', 'CornflowerBlue', 'Cornsilk', 'Crimson', 'Cyan', 21 | 'DarkCyan', 'DarkGoldenRod', 'DarkGrey', 'DarkKhaki', 'DarkOrange', 22 | 'DarkOrchid', 'DarkSalmon', 'DarkSeaGreen', 'DarkTurquoise', 'DarkViolet', 23 | 'DeepPink', 'DeepSkyBlue', 'DodgerBlue', 'FireBrick', 'FloralWhite', 24 | 'ForestGreen', 'Fuchsia', 'Gainsboro', 'GhostWhite', 'Gold', 'GoldenRod', 25 | 'Salmon', 'Tan', 'HoneyDew', 'HotPink', 'IndianRed', 'Ivory', 'Khaki', 26 | 'Lavender', 'LavenderBlush', 'LawnGreen', 'LemonChiffon', 'LightBlue', 27 | 'LightCoral', 'LightCyan', 'LightGoldenRodYellow', 'LightGray', 'LightGrey', 28 | 'LightGreen', 'LightPink', 'LightSalmon', 'LightSeaGreen', 'LightSkyBlue', 29 | 'LightSlateGray', 'LightSlateGrey', 'LightSteelBlue', 'LightYellow', 'Lime', 30 | 'LimeGreen', 'Linen', 'Magenta', 'MediumAquaMarine', 'MediumOrchid', 31 | 'MediumPurple', 'MediumSeaGreen', 'MediumSlateBlue', 'MediumSpringGreen', 32 | 'MediumTurquoise', 'MediumVioletRed', 'MintCream', 'MistyRose', 'Moccasin', 33 | 'NavajoWhite', 'OldLace', 'Olive', 'OliveDrab', 'Orange', 'OrangeRed', 34 | 'Orchid', 'PaleGoldenRod', 'PaleGreen', 'PaleTurquoise', 'PaleVioletRed', 35 | 'PapayaWhip', 'PeachPuff', 'Peru', 'Pink', 'Plum', 'PowderBlue', 'Purple', 36 | 'Red', 'RosyBrown', 'RoyalBlue', 'SaddleBrown', 'Green', 'SandyBrown', 37 | 'SeaGreen', 'SeaShell', 'Sienna', 'Silver', 'SkyBlue', 'SlateBlue', 38 | 'SlateGray', 'SlateGrey', 'Snow', 'SpringGreen', 'SteelBlue', 'GreenYellow', 39 | 'Teal', 'Thistle', 'Tomato', 'Turquoise', 'Violet', 'Wheat', 'White', 40 | 'WhiteSmoke', 'Yellow', 'YellowGreen' 41 | ] 42 | 43 | NUM_COLORS = len(STANDARD_COLORS) 44 | 45 | try: 46 | FONT = ImageFont.truetype('arial.ttf', 24) 47 | except IOError: 48 | FONT = ImageFont.load_default() 49 | 50 | def _draw_single_box(image, xmin, ymin, xmax, ymax, display_str, font, color='black', thickness=4): 51 | draw = ImageDraw.Draw(image) 52 | (left, right, top, bottom) = (xmin, xmax, ymin, ymax) 53 | draw.line([(left, top), (left, bottom), (right, bottom), 54 | (right, top), (left, top)], width=thickness, fill=color) 55 | text_bottom = bottom 56 | # Reverse list and print from bottom to top. 57 | text_width, text_height = font.getsize(display_str) 58 | margin = np.ceil(0.05 * text_height) 59 | draw.rectangle( 60 | [(left, text_bottom - text_height - 2 * margin), (left + text_width, 61 | text_bottom)], 62 | fill=color) 63 | draw.text( 64 | (left + margin, text_bottom - text_height - margin), 65 | display_str, 66 | fill='black', 67 | font=font) 68 | 69 | return image 70 | 71 | def draw_bounding_boxes(image, gt_boxes, im_info): 72 | num_boxes = gt_boxes.shape[0] 73 | gt_boxes_new = gt_boxes.copy() 74 | gt_boxes_new[:,:4] = np.round(gt_boxes_new[:,:4].copy() / im_info[2]) 75 | disp_image = Image.fromarray(np.uint8(image[0])) 76 | 77 | for i in range(num_boxes): 78 | this_class = int(gt_boxes_new[i, 4]) 79 | disp_image = _draw_single_box(disp_image, 80 | gt_boxes_new[i, 0], 81 | gt_boxes_new[i, 1], 82 | gt_boxes_new[i, 2], 83 | gt_boxes_new[i, 3], 84 | 'N%02d-C%02d' % (i, this_class), 85 | FONT, 86 | color=STANDARD_COLORS[this_class % NUM_COLORS]) 87 | 88 | image[0, :] = np.array(disp_image) 89 | return image 90 | --------------------------------------------------------------------------------