faster-rcnn实现目标检测

写在前面

首先,我是复现的GitHub上jwyang大神的实现,看我这个帖子的时候建议同时参考其网址,网址如下:https://github.com/jwyang/faster-rcnn.pytorch/tree/pytorch-1.0。

以下的实现过程本人踩了无数的坑才踩过来的,首先说明一下为什么会有坑:这个repository的原作者,无疑,是一个高手,而高手,其电脑上肯定早已配过了一系列的环境,安装过了一系列的包。但对于本菜鸡用的服务器而言,很多包肯定没装过而且装的不一样,高手虽然在这个repository中给出了所需的依赖包,但对于我来说,也许并不全,所以如果您的情况与我相似,也是可以参考下我的配置过程的哈!另外,我写这篇文章的另一个意义在于,是对这个repository进行一个整合,因为如果单单对照README.md的话,免不了会有很多网页链接要跳转,这样会很乱,所以我这里把所有要做的步骤都整合在一篇文章中。另外:我估计这个repository以后还会更新,更新之后的情况就未必适合于我在当下时间所写的配置过程,所以也请注意我的写作时间,酌情参考(不过大体思路总是一样的)。

准备虚拟环境、git clone

先在一个虚拟环境里安装好pytorch0.4.1(我知道这个repository的README里写了这个repository是支持pytorch1.0的,但是经过我实际验证,还是要用0.4.1版本。python版本要选2.7,因为之后有一步编译是需要python2.7的)。另外,依据我的个人经历,不同的工程所依赖的环境一般会有不同,为了避免环境不好配,我一怒之下决定给每一个工程创建一个专属虚拟环境。注意:如果用conda装,按照官网指令执行:conda install pytorch torchvision -c pytorch,则由于pytorch服务器在国外,则下载速度很慢,很可能会中断。所以采用pip(python install packages)从国内的清华的源来安装,这个源每5分钟同步一次,所以可以认为是最新的

conda create -n jwyang-fasterrcnn-pytorch041-py27 python=2.7
conda activate jwyang-fasterrcnn-pytorch041-py27
pip install pip -U
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
pip install torch==0.4.1 torchvision

然后,把clone代码到本地,并创建个data文件夹。

mkdir Projects/ObjectDetection
cd Projects/ObjectDetection
git clone https://github.com/jwyang/faster-rcnn.pytorch.git 
#git clone如果没有指定路径就会clone到当前工作目录
cd faster-rcnn.pytorch && mkdir data

准备数据集

准备voc数据集

下载训练集、验证集、测试集和VOCdevkit:

mkdir -p ~/Projects/Data/VOC2007 #创建个存放数据的文件夹
cd ~/Projects/Data/VOC2007
wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtrainval_06-Nov-2007.tar
wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtest_06-Nov-2007.tar
wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCdevkit_08-Jun-2007.tar
#wget没有指定下载到哪里的话就会下载到当前工作目录,也可以用-P参数来指定。

wget是linux自带的一个命令行工具,用于下载网站/批量文件,支持HTTP和FTP。

把这些tar包里的内容都提取到一个叫VOCdevkit的文件夹下:

tar xvf VOCtrainval_06-Nov-2007.tar
tar xvf VOCtest_06-Nov-2007.tar
tar xvf VOCdevkit_08-Jun-2007.tar

tar xvf FileName.tar是解包命令,tar cvf FileName.tar DirName是打包命令。tar xvf默认是解包到当前目录(新建一个文件夹,把tar包的文件都放到这个文件夹里),但实际上执行完以上三条命令,三个tar包的所有内容都在当前工作目录的VOCdevkit文件夹下,我猜想是VOCdevkit_08-Jun-2007.tar的特殊作用。

VOCdevkit文件夹下的结构应该是这样的:

$VOCdevkit/                           # development kit
$VOCdevkit/VOCcode/                   # VOC utility code
$VOCdevkit/VOC2007                    # image sets, annotations, etc.
# ... and several other directories ...

在data文件夹下创建一个VOC数据集的软连接(softlink/symbolic link/symlink,相当于Windows的快捷方式):

cd ~/Projects/ObjectDetection/faster-rcnn.pytorch/data #进入到我们创建的data文件夹
ln -s ~/Projects/Data/VOC2007/VOCdevkit VOCdevkit2007

ln是链接(link)命令,ln -s 表示创建软连接。具体用法是:ln -s 源文件 目标文件

准备COCO数据集

大致说下COCO数据集:COCO官网,在主页上也可以下载一篇描述COCO数据集的论文,我也写过一篇《论文学习:Microsoft COCO Common Objects in Context》的博文整理出了这篇论文的要点,链接在此:https://blog.csdn.net/The_heart_of_robort/article/details/85039868。

COCO数据集我个人不需要下载,因为我师姐之前已经下载过放到服务器上了,我所要做的只是在data文件夹下创建一个软连接到师姐存放数据集的目录。

#为了避免权限不够,先给师姐存放COCO数据集的文件夹及其子目录、里面的文件777权限,路径这里是我瞎编的
sudo chmod 777 -R ~shijie/Projects/Data/mscoco
#创建软连接
ln -s  ~shijie/Projects/Data/mscoco coco

准备Visual Genome数据集

Visual Genome数据集是由斯坦福大学人工智能实验室主任李飞飞与几位同事合作开发的。到Visual Genome数据集官网下载1.4版本的数据集,通过官网上的各种Readme可以充分了解这个数据集每个文件夹的意义。我是下载到了/home/jlxy/Projects/Data/VisualGenome-v1.4/下。

然后我们把所有(11个).zip文件都解压到VGdata文件夹下。

cd /home/jlxy/Projects/Data/VisualGenome-v1.4
unzip '*.zip' -d VGdata

其中*是通配符,代表0到多个任意字符。’'也要有,否则会认为其它.zip文件是在第一个.zip文件里面的。VGdata这个文件夹是自动创建的。然后,

cd ~/Projects/ObjectDetection/faster-rcnn.pytorch/data
ln -s ~/Projects/Data/Data/VisualGenome-v1.4/VGdata vg

准备预训练模型

下一步是下载pretrained models,两个pretrained model分别是VGG16和ResNet101。要把它们放在data/pretrained_model/下。

mkdir pretrained_model

点击两个预训练模型的下载链接,把它们下载到pretrained_model/下。(下载的模型的Caffe的,因为发现Caffe的模型要比PyTorch的好一些)

编译

接下来是编译步骤,用pip安装所有的python依赖:pip install -r requirements.txt,但是我第一反应是不想用pip,我想用conda在虚拟环境中安装,因为我觉得这样便于管理。但我忽然转念一想,在用conda**了不同的虚拟环境的时候,所使用的python是不同的,那么在不同的虚拟环境中,所用的pip是否也不同呢?

我使用which指令来验证我的想法,which用于查找并显示给定命令的绝对路径,环境变量PATH中保存了查找命令时需要遍历的目录。which指令会在环境变量PATH设置的目录里查找符合条件的文件。也就是说,使用which命令,就可以看到某个系统命令是否存在,以及执行的到底是哪一个位置的命令。执行:

#此时是在jwyang-fasterrcnn-pytorch041-py27虚拟环境下
which pip
#输出为:/home/jlxy/anaconda3/envs/jwyang-fasterrcnn-pytorch041-py27/bin/pip
conda deactivate
#此时是在base环境下
which pip
#输出为:/home/jlxy/anaconda3/bin/pip

可见:我的猜想是正确的!在不同的环境下使用的pip的确不同,那么pip安装的包存放的位置是否也不同呢?如果在jwyang-fasterrcnn-pytorch041-py27虚拟环境下用pip安装的包都是在envs/jwyang-fasterrcnn-pytorch041-py27/目录下的,这样不就好管理了吗?我们可以先用pip list指令列出pip安装过的包:

#在base环境下
pip list
#输出了一大堆包的名称,随便挑出一个叫zict的包,执行:
pip show zict
#输出信息中会出现zict存放的位置:/home/jlxy/anaconda3/lib/python3.7/site-packages
conda activate jwyang-fasterrcnn-pytorch041-py27
pip list
#输出的包的名称和之前不一样了
pip show torch
#存放位置:/home/jlxy/anaconda3/envs/jwyang-fasterrcnn-pytorch041-py27/lib/python2.7/site-packages
#存放位置也和之前不一样了,且在jwyang-fasterrcnn-pytorch041-py27/下

说明,我的猜想再次正确。于是,基于以上两个结论,我在jwyang-fasterrcnn-pytorch041-py27里直接执行:

cd ../
pip install -r requirements.txt

这种安装方式是从requirments file安装,用pip install -h调出帮助文档就可以看到其用法。

安装这个过程中遇到了报错,说是matplotlib3.0以上已经不支持python3.5以下的版本了,所以matplotlib安装失败。要解决这个报错,我们需要安装支持python2.7的matplotlib版本,尝试:

pip install matplotlib==2.9 #指定安装2.9版本,说不定就支持python2.7了

运行指令后会报错,说matplotlib没有2.9这个版本,但是报错也提示出了一大堆matplotlib的版本号,我选了一个3.0版本的前一个版本——2.2.3进行安装:

pip install matplotlib==2.2.3

这次安装成功了!但是由于之前matplotlib安装的失败,导致requirements.txt中其它的包也没能安装,于是重新执行:

pip install -r requirements.txt

至此所有的依赖安装成功!用pip list可以进行查看。

然后编译cuda的依赖,注意这里是用python2.7来进行编译的!(这就是为什么我们要用python2.7的环境)利用setup.py来安装,setup.py是python的一种安装第三方模块的方式,一般是先python setup.py build,再python setup.py install,而python setup.py develop是你安装完这个包后还需要修改的时候用的。执行:

cd lib
python setup.py build develop

报错:error:invalid command ‘develop’。我:??官方README上的指令还会有这种错误,我也是醉了。于是转而:

python setup.py build
#build之后会发现lib/下多了个build文件夹
python setup.py install

没报错,但这并不是最终的胜利,还要看到实际效果才算数。

下载预训练模型运行Demo

尝试执行测试命令:

python test_net.py --dataset pascal_voc --net vgg16  --checksession 1 --checkepoch 6 --checkpoint 416  --cuda

报错:ImportError: No module named PIL。尝试:

pip install PIL

报错:No matching distribution found for PIL。这个原因是所想安装的包的名字不叫这个,百度了下(其实pip应该也能search),叫Pillow,于是:

pip install Pillow

成功,再次尝试:

python test_net.py --dataset pascal_voc --net vgg16  --checksession 1 --checkepoch 6 --checkpoint 416  --cuda

报错:ImportError: No module named _nms。在这个repository的评论区看到这个错误是要进入到lib,并sh make.sh,于是:

cd lib
sh make.sh

报错:nvcc:not found。在评论区看到一个解决方法是:在make.sh里面加上两句话,于是:

vim make.sh

打开后,如图添加:

faster-rcnn实现目标检测

保存退出,再尝试:

cd ../
python test_net.py --dataset pascal_voc --net vgg16  --checksession 1 --checkepoch 6 --checkpoint 416  --cuda

报错:报什么错我没细看,因为我突然感觉不对劲,想看效果好不好使应该是要运行demo.py吧?于是改而尝试:

python demo.py --net vgg16  --checksession 1 --checkepoch 6 --checkpoint 416 --cuda --load_dir ~/Projects/ObjectDetection/faster-rcnn.pytorch/data/pretrained_model

报错:IOError: [Errno 2] No such file or directory: ‘/home/yiming_hao/Projects/ObjectDetection/faster-rcnn.pytorch/data/pretrained_model/vgg16/pascal_voc/faster_rcnn_1_6_416.pth’。从这个报错可以看出,这个程序会从pretrained_model/目录下去找预训练模型,而且要找的内容和我命令行传入的参数是相关的:比如net指定的是vgg16,那么接下来就去vgg16目录下去找,dataset没有传入,那么就是默认值pascal_voc,接下来去pascal_voc目录下去找,然后还传了1、6、416这3个参数,于是.pth文件的后缀里就包含了1_6_416。可见:如果想运行程序,就要在相应的路径下放相应的文件。相应的文件何处寻?就在这个repository的Benchmarking下面,如图:

faster-rcnn实现目标检测

那么我就点击第一个VGG-16下载,创建相应路径,使之下载到data/pretrained_model/vgg16/pascal_voc/下:

mkdir -p data/pretrained_model/vgg16/pascal_voc
#然后把下载到的faster_rcnn_1_6_10021.pth文件放到这个文件夹***意后缀的几个数字

然后再尝试运行demp.py文件:(注意传入的参数要根据预训练模型文件名修改)

python demo.py --net vgg16  --checksession 1 --checkepoch 6 --checkpoint 10021 --cuda --load_dir ~/Projects/ObjectDetection/faster-rcnn.pytorch/data/pretrained_model

报错:RuntimeError: Attempting to deserialize object on a CUDA device but torch.cuda.is_available() is False. If you are running on a CPU-only machine, please use torch.load with map_location=‘cpu’ to map your storages to the CPU.。希望再一次破灭,但我没有气馁,先nvidia-smi看一下,结果却显示:No devices were found。原来是服务器上突然找不到显卡了??问题不大,重启服务器,nvidia-smi,问题解决。

让我们先回到之前的虚拟环境和工作路径,再执行:

python demo.py --net vgg16  --checksession 1 --checkepoch 6 --checkpoint 10021 --cuda --load_dir ~/Projects/ObjectDetection/faster-rcnn.pytorch/data/pretrained_model

然后终于成功了!!!!可以把个人的图片放到faster-rcnn.pytorch/images/目录下,比如放一个hym.jpg,然后运行指令,会生成一个hym_det.jpg,这个图片上就框出了目标物体!接下来我就秀几张哈哈哈:

faster-rcnn实现目标检测
faster-rcnn实现目标检测

用pycharm运行trainval_net.py从而实现代码调试

现在我要分析trainval_net.py这份代码,此时可以用pycharm进入调试模式进行分析。

根据Readme,如果在命令行实施训练,则可以输入如下命令:

CUDA_VISIBLE_DEVICES=1,2,3,4 python trainval_net.py 
                   --dataset pascal_voc --net vgg16 
                   --bs 1 --nw 1 
                   --lr 0.01 --lr_decay_step 100 
                   --cuda

但是我们现在要在pycharm里实施训练,则可以通过如下方式来指定环境变量CUDA_VISIBLE_DEVICES和参数:

命令行运行如下命令用pycharm打开trainval_net.py

charm ./trainval_net.py

然后如图点击Edit Configurations:
faster-rcnn实现目标检测

然后在这里输入参数:
faster-rcnn实现目标检测
注意:这张截图里的batch size是64,这个64太大了,会导致显存不够用

然后在这里输入环境变量:
faster-rcnn实现目标检测
faster-rcnn实现目标检测

然后再运行,结果还是报错,不过这次报错是因为我安装的pytorch是0.4.1版本,结果竟然需要0.4.0版本才行。这里我想吐槽一句(如果不是我理解错了的话):真的是坑!说好的是pytorch1.0版本,搞得我先弄成0.4.1版本,结果还不行,又要降级成0.4.0版本,我虚拟环境的名称都已经起成了0.4.1了,烦!如果您是照着我这个步骤一点点来的,也起了同样的虚拟环境名字,我道歉。

用pip进行pytorch降级:

pip install torch==0.4.0

成功后再运行trainval_net.py,就能实施训练啦。然后我们就可以利用pycharm的调试模式分析代码。

作者:郝义铭

邮箱:[email protected]

写作时间:2018.12.19

参考文章

https://github.com/jwyang/faster-rcnn.pytorch/tree/pytorch-1.0