论文:https://arxiv.org/abs/1904.07850
代码:https://github.com/xingyizhou/CenterNet
1. 环境配置
官方配置文档:CenterNet/readme/INSTALL.md
官方在 这里 给的环境配置是 PyTorch 0.4.1 + CUDA 9.0 + CUDNN 7.1,但是我按照这个配出来的环境在跑训练时报了这个错:
RuntimeError: cuda runtime error (11) : invalid argument at /opt/conda/conda-bld/pytorch_1535491974311/work/aten/src/THC/THCGeneral.cpp:663
(不得不说这个错误非常气人!!)最开始找到的原因说 cuda 和 pytorch 版本有问题,要升级到 cuda 10.0 以上,但是 cuda 10.0 支持的 PyTorch 版本必须在 1.3.0 以上,这又导致代码无法支持 PyTorch 1.3.0,绕了一圈又绕回来了!最后终于找到了相关解决方案:参考1 和 参考 2。也就是需要 CUDA 9.2 而不是 9.0!所以我的环境配置和官方这点不太一样,仅供参考。
- NVIDIA GeForce RTX 2080 Ti
- Ubuntu 16.04
- Python 3.6
- PyTorch 0.4.1
- CUDA 9.2
- CUDNN 7.5.1
- Numpy 1.16.1
环境配置过程:
# 创建并激活 conda 环境
conda create --name CenterNet python=3.6
conda activate CenterNet
# 安装PyTorch
conda install pytorch=0.4.1 torchvision cudatoolkit=9.2 -c pytorch
# 禁用 cudnn batch normalization(作者说这里如果不禁用会导致训练时出问题)
PYTORCH=/data1/zyy/usr/local/anaconda/envs/CenterNet/lib/python3.6/site-packages/ # 这里根据自己的路径修改
# for pytorch v0.4.0
sed -i "1194s/torch\.backends\.cudnn\.enabled/False/g" ${PYTORCH}/torch/nn/functional.py
# for pytorch v0.4.1(上面安装的是 pytorch 0.4.1,所以这一步输入下面这句代码)
sed -i "1254s/torch\.backends\.cudnn\.enabled/False/g" ${PYTORCH}/torch/nn/functional.py
# 对于其他 pytoch 版本,可以直接修改 torch/nn/functional.py 文件中的 torch.backends.cudnn.enabled,将其置为 False 即可
# 安装 COCO API
COCOAPI=/data1/zyy/code/centernet/cocoapi # 自己修改想要存放的路径
git clone https://github.com/cocodataset/cocoapi.git $COCOAPI
cd $COCOAPI/PythonAPI
make # 报错记录1
python setup.py install --user # 报错记录2
# clone CenterNet repo
CenterNet_ROOT=/data1/zyy/code/centernet/CenterNet # 自己修改想要存放的路径
git clone https://github.com/xingyizhou/CenterNet $CenterNet_ROOT # 报错记录3
# 安装依赖
cd CenterNet
pip install -r requirements.txt
# 编译可变形卷积(DCNv2)
cd $CenterNet_ROOT/src/lib/models/networks/DCNv2
./make.sh # 报错记录4
# [可选] 只有使用extremenet或多尺度测试时才需要编译NMS
cd $CenterNet_ROOT/src/lib/external
make
【报错记录1】 安装 COCO API 时,执行 make 报错
gcc: error: pycocotools/_mask.c: 没有那个文件或目录
解决方法:安装 Cython。编译 COCO API 需要依赖库 Cython,安装完成后重新 make 即可。编译完成后,执行 import pycocotools
,不报错即成功。
pip3 install cython
【报错记录2】 执行 setup.py 报错
error: Setup script exited with
Beginning with Matplotlib 3.4, Python 3.7 or above is required.
You are using Python 3.6.13.
解决方法:原因是自动安装时安装的都是最新版本,自动安装的是 Matplotlib 3.4,需要 Python 至少在 3.7 以上,但我们的 Python 是 3.6 的,而不想升级 Python 版本,只需要降低 Matplotlib 版本即可。查看 setup.py,要求 Matplotlib >=2.1.0,因此我们手动安装 Matplotlib 即可。完成后重新执行 setup.py。
conda install matplotlib=2.1.0
【报错记录3】 git clone 代码超时
fatal: unable to access 'https://github.com/xingyizhou/CenterNet/': Failed to connect to github.com port 443: 连接超时
解决方法:输入下面两条命令
git config --global http.proxy
git config --global --unset http.proxy
【报错记录4】 编译 DCNv2 报错
./make.sh: 行 5: nvcc: 未找到命令 # 问题1
bash: ./make.sh: 权限不够 # 问题2
解决方法:1)问题1,是因为没有安装 nvcc,在管理员权限下执行 apt-get install nvidia-cuda-toolkit
;2)问题2,加个执行权限,执行 chmod +x ./make.sh
。
# 问题3
dcn_v2_im2col_cuda_double.cu(248): error: no instance of overloaded function "atomicAdd" matches the argument list
argument types are: (double *, double)
1 error detected in the compilation of "/tmp/tmpxft_00001e56_00000000-5_dcn_v2_im2col_cuda_double.cpp4.ii".
dcn_v2_psroi_pooling_cuda_double.cu(247): error: no instance of overloaded function "atomicAdd" matches the argument list
argument types are: (double *, double)
dcn_v2_psroi_pooling_cuda_double.cu(248): error: no instance of overloaded function "atomicAdd" matches the argument list
argument types are: (double *, double)
dcn_v2_psroi_pooling_cuda_double.cu(249): error: no instance of overloaded function "atomicAdd" matches the argument list
argument types are: (double *, double)
dcn_v2_psroi_pooling_cuda_double.cu(250): error: no instance of overloaded function "atomicAdd" matches the argument list
argument types are: (double *, double)
dcn_v2_psroi_pooling_cuda_double.cu(265): error: no instance of overloaded function "atomicAdd" matches the argument list
argument types are: (double *, double)
dcn_v2_psroi_pooling_cuda_double.cu(266): error: no instance of overloaded function "atomicAdd" matches the argument list
argument types are: (double *, double)
6 errors detected in the compilation of "/tmp/tmpxft_00001e9d_00000000-5_dcn_v2_psroi_pooling_cuda_double.cpp4.ii".
gcc: error: /data1/zyy/code/centernet/CenterNet/src/lib/models/networks/DCNv2/src/cuda/dcn_v2_im2col_cuda_double.cu.o: 没有那个文件或目录
gcc: error: /data1/zyy/code/centernet/CenterNet/src/lib/models/networks/DCNv2/src/cuda/dcn_v2_psroi_pooling_cuda_double.cu.o: 没有那个文件或目录
解决方法:还是 CUDA 版本问题,这是之前环境没配好的时候出现的问题,如果按照前面的 CUDA 9.2 + PyTorch 0.4.1 应该不会遇到。
2. 执行 demo
在 model zoo 下载训练好的检测模型 ctdet_coco_dla_2x
,放在 CenterNet/models/
文件夹下。执行 demo.py
可以测试一下检测效果:
cd path/to/CenterNet/src
python demo.py ctdet --demo ../images/17790319373_bd19b24cfc_k.jpg --load_model ../models/ctdet_coco_dla_2x.pth
上面选取了 repo 里自带的一张图片,检测效果如下:
执行 demo.py 时可能遇到 RuntimeError: CUDA error: out of memory
这个问题,查看了相关 issues70,没找到根本原因,但一个可行的解决方法是将 CenterNet/src/lib/opts.py
的第 338 行 [512,512]
改成 [480,480]
或者 [640,640]
,都可以解决 out of memory 这个问题。
在命令中加上 --debug 2
,可以看到中央点的 heatmap:
python demo.py ctdet --debug 2 --demo ../images/17790319373_bd19b24cfc_k.jpg --load_model ../models/ctdet_coco_dla_2x.pth
3. 数据准备 & 训练 & 测试
3.1 数据集
官方文档:[1] DATA.md;[2] DEVELOP.md
- 第一步:首先将自己的数据标注处理为 COCO 数据集的格式,标注细节参考:COCO数据集标注&代码
- 第二步:在 CenterNet 代码
src/lib/datasets/dataset
目录下添加数据集的处理文件,可以直接把src/lib/datasets/dataset/coco.py
的内容复制过来,修改一下数据集的名称、类别等信息即可。 - 第三步:将你的数据集注册到
src/lib/datasets/dataset_factory
。比如新增from .dataset.refuge import Refuge
和dataset_factory = {'refuge': Refuge}
。 - 第四步:在
src/lib/utils/debugger.py
文件中注册你的数据集,比如在 Debugger 中添加elif dataset == 'refuge': self.names = refuge_class_name
,和refuge_class_name = ['disc', 'cup']
。
数据集组织如下:
CenterNet_ROOT
|-- data
`-- |-- refuge
`-- |-- annotations
| |-- train.json
| |-- val.json
| |-- test.json
|-- images
| |-- train
| |-- val
`-- |-- test
3.2 训练
官方文档:GETTING_STARTED.md
执行训练命令:
python main.py ctdet --dataset refuge --exp_id refuge_090109 --num_epochs 140 --batch_size 16 --master_batch 8 --lr 1.25e-4 --gpus 0,1
exp_id:实验 id 号,可以自行设定,在训练意外中断时,可以利用同样的 exp_id 并在上面的命令行加入 --resume
继续训练。master_size:对于多 GPU 训练,默认情况下 batch size 会平均分配在每个 GPU 上;否则,可以通过 master_batch 来设置放在主 GPU 上的 batch 大小,且 master_batch 必须小于 batch_size。训练更详细的设定可以在 opts.py
中查看。
执行训练报错:
[1] ValueError: numpy.ufunc size changed, may indicate binary incompatibility. Expected 216 from C header, got 192 from PyObject
解决方法:numpy 版本低了,目前是 1.15.1,执行 conda install numpy=1.16.1
更换到 1.16.1。
[2] RuntimeError: cuda runtime error (11) : invalid argument at /opt/conda/conda-bld/pytorch_1535491974311/work/aten/src/THC/THCGeneral.cpp:663
解决方法:就是在记录开头提到的问题,环境更换为 CUDA 9.2 + PyTorch 0.4.1 + CUDNN 7.5.1。
成功执行训练以后,显示如下:
train: [1][24/25]|Tot: 0:00:25 |ETA: 0:00:01 |loss 17.4448 |hm_loss 15.6720 |wh_loss 14.7425 |off_loss 0.2985 |Data 0.003s(0.066s) |Net 1.015s
参数含义:第一个位置表示该阶段是 train 还是 validation,这里显示为 train。接着 [1]
表示当前执行到第几个 epoch,[24/25]
表示 [当前在第24个iteration / 共25个iteration],[Tot]
表示一个 epoch 的训练时常,[ETA]
表示当前 epoch 的剩余训练时间。后面的 [loss]
均表示损失值。
训练的模型就存放在 CenterNet/exp/ctdet/refuge_090109
目录下。
3.3 测试
执行测试命令:
python test.py ctdet --dataset refuge --exp_id refuge_090109_test --load_model ../exp/ctdet/refuge_090109/model_best.pth --K 2 --gpus 0,1
# K 规定了测试时能够预测的最大目标个数
【2021/9/1】
- 修改
test.py
、base_detector.py
、detectors/ctdet.py
代码逻辑,令测试过程可以直接保存检测结果。 - 修改了测试结果保存路径的指定问题,根据 --load_model 将可视化检测结果保存在相应的文件夹下。
python test.py ctdet --debug 0 --dataset refuge --load_model ../exp/ctdet/refuge_090109/model_best.pth --K 2 --gpus 0,1 --trainval
# trainval用于区分使用验证集还是测试集来做测试,这里意味着在测试集上
执行测试报错:
RuntimeError: CUDA error: out of memory
解决方法:和执行 demo.py
的 bug 一摸一样,这里把 CenterNet/src/lib/datasets/dataset/coco.py
的第 15 行 default_resolution = [512, 512]
改为 [640, 640]
或者 [480, 480]
即可。
测试结果: