使用深度学习网络SSD识别自己定义的物体

来源:互联网 发布:闲鱼在淘宝哪里进去 编辑:程序博客网 时间:2024/06/05 00:27

最近在做一些使用深度学习网络SSD(single shot multibox detector)的Caffe版本进行物体识别的工作。具体的实现效果如下图所示:
这里写图片描述
解释一下其中的代号:
(1)poc(pocky,百奇饼干)
(2)sti(stick,棉签)
(3)pie(派)
(4)cla(clamp,塑料夹子)
(5)bit(biscuit,饼干)
(6)cup(水杯)
(7)lit(light,手电筒)
(8)hap(happy,开心巴旦木。。。)
(9)in(instantnoodles,方便面)
一共是9种物体,图片中名字后面的数字是识别的置信度。可以看出识别的准确度是很高的,识别的速度达到了FPS58.2,已经满足了实时性的要求。下面就来说一下如何实现吧。

主要内容:
-建立数据集
-配置Caffe
-训练并检验SSD网络
-使用摄像头识别物体


1. 建立数据集

如果要网络识别自己定义的物体,首先要建立自己的物体数据集。建立数据集时要注意数据的多样性,如果要网络有很好的泛化性能,数据就要尽量包括所遇到的情况。比如说我们的数据集如下图所示:
这里写图片描述
我将物体放于一个盒子中,并将其作为训练集背景。这和我应用的场景有关,因为我测试的情况就是识别盒子中的物体,所以我将其背景固定下来。另外要注意数据的多样性,我设置的变量有盒子的位置和角度变化,盒子内物体的位置和姿态的变化,最后还有不同方向的光照。一共记录了300张图片。
下一步就是要标注图片了,这一步中要注意标注的质量和生成的标注文件格式。我使用的标注软件是labelme,但这个软件生成的标注文件XML和SSD使用的常用数据集VOC2007的标注文件XML有着格式上的不同。所以,我后来在github上找到了一个可以将labelme标注文件转换为VOC标注文件的项目labelme2VOC2007mat。git地址:https://github.com/LBAWMY/labelme2VOC2007mat
这里写图片描述
但是我发现还有其他的一些标注软件可以直接生成VOC格式的标注文件,比如:Label-Annotation-VOC-Pascal。git地址:https://github.com/manhcuogntin4/Label-Annotation-VOC-Pascal
标注是一个劳动密集型工作,需要一段时间的艰苦劳动。所以我和几个实验室的小伙伴一起花了一个小时完成了300张图片的标注。标注的时候要注意每个物体的名称和id号。
当我们获得了图片和对应的标注文件后,我们就要开始整理数据了。按照VOC2007的格式来整理最好,因为SSD源码中的示例程序用的就是VOC2007的数据库。所以,数据的格式是这样的:
这里写图片描述
先在根目录下建立自己的数据集文件夹:

cd mkdir datacd datamkdir VOCdevkitcd VOCdevkitmkdir mydataset

然后在mydataset下面建立三个子文件夹:Annotations,imageSets和JPEGImages。第一个是标注文件夹,其中放置标注文件XML。第二个是分类文件夹,其中还有一个文件夹Main,这个文件夹下放置训练集和测试集的文件名文档,如test.txt和trainval.txt。第三个文件夹是图片文件夹,放置训练集图片。如果使用我之前说的labelme2VOC2007mat,它里面包含了自动生成这些文件,更加方便。

2.配置Caffe

这部分开始就和深度学习框架Caffe有关系了。Caffe的输入数据必须为LMDB格式,一方面可以将各种数据转换为统一格式,另一方面还可以提高磁盘的IO利用率。我们上一步所做的数据集还要转换格式。所以,我们先来看一下SSD在Caffe构架下的配置过程。
安装Caffe依赖项:

sudo apt-get install libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libhdf5-serial-dev protobuf-compilersudo apt-get install --no-install-recommends libboost-all-devsudo apt-get install libopenblas-dev liblapack-dev libatlas-base-devsudo apt-get install libgflags-dev libgoogle-glog-dev liblmdb-devsudo apt-get install git cmake build-essential

先从github上下载ssd源码

git clone https://github.com/weiliu89/caffe.gitcd caffegit checkout ssd

后面要开始编译源码。这里可能会报一些细节的错误,以后再补充。
先拷贝Makefile.config

cp Makefile.config.example Makefile.config

再打开Makefile.config,需要根据自己的需要调整一些使用Caffe时的选项。比如我选了:

USE_CUDNN := 1

将 INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include 改为

INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include /usr/lib/x86_64-linux-gnu/hdf5/serial/include

将 LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib 改为

LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib /usr/lib/x86_64-linux-gnu/hdf5/serial

完成这些后,我使用cmake进行编译。在caffe根目录下建立build,然后编译。

mkdir buildcd buildcmake ..make all -j8make install# (Optional)make runtest -j8

通过后就可以进行下一步了。如果报错,可能需要根据错误信息安装依赖,或者调整一些细节。
下面就要将我们做的数据集转换为LMDB格式了,这里我们使用了SSD一些自带的程序功能。首先,在caffe目录下的data文件夹中建立自己的数据文件夹/mydataset。这就是我们自己的数据分组文件和LMDB生成文件的所在地。然后将同样是数据文件夹VOC0712中的create_list.sh,create_data.sh和labelmap_voc.prototxt拷贝过来。并修改其中的一些地方:
create_list.sh中,改for name in 后面的为mydataset
create_data.sh中,改为:

dataset_name="mydataset"mapfile="$root_dir/data/$dataset_name/labelmap_voc.prototxt"

注意labelmap_voc.prototxt为标注映射文件,我们要把里面的内容改为自己设定的分类名称和id号。这里的id号要和标注时设定的物体id号相同。标注映射文件如下图所示:
这里写图片描述

现在可以使用

./data/mydataset/create_list.sh

对我们制作的数据集进行分组。分组完毕后,就可以开始转换数据为LMDB格式了。

./data/mydataset/create_data.sh

如果成功生成LMDB就可以开始训练了。

3.训练并检验SSD网络

到这一步就比较简单了,先改一下examples/ssd/ssd_pascal.py中的一些配置和地址。
1.改训练集和测试集的地址:

# The database file for training data. Created by data/VOC0712/create_data.shtrain_data = "examples/mydataset/mydataset_trainval_lmdb" #mzm# The database file for testing data. Created by data/VOC0712/create_data.shtest_data = "examples/mydataset/mydataset_test_lmdb" #mzm

2.改一些保存数据文件的地址

# Directory which stores the model .prototxt file.save_dir = "models/VGGNet/mydataset/{}".format(job_name) #mzm# Directory which stores the snapshot of models.snapshot_dir = "models/VGGNet/mydataset/{}".format(job_name) #mzm# Directory which stores the job script and log file.job_dir = "jobs/VGGNet/mydataset/{}".format(job_name) #mzm# Directory which stores the detection results.output_result_dir = "{}/data/VOCdevkit/results/mydataset/{}/Main".format(os.environ['HOME'], job_name) #mzm

3.改一些测试集大小文件和标注映射文件地址

# Stores the test image names and sizes. Created by data/VOC0712/create_list.shname_size_file = "data/mydataset/test_name_size.txt" #mzm# The pretrained model. We use the Fully convolutional reduced (atrous) VGGNet.pretrain_model = "models/VGGNet/VGG_ILSVRC_16_layers_fc_reduced.caffemodel"# Stores LabelMapItem.label_map_file = "data/mydataset/labelmap_mydataset.prototxt" #mzm

4.改写网络分类总数。这里注意我在标注时把背景的id设为了9,所以在这里把background_label_id也设定为9。

# MultiBoxLoss parameters.num_classes = 10 #mzmshare_location = Truebackground_label_id=9 #mzm

5.根据自己的设备情况,改gpu的使用数量。我只有一块gpu,所以改为:

# Defining which GPUs to use.gpus = "0"gpulist = gpus.split(",")num_gpus = len(gpulist)

完成以上改动后,就可以按照github上面的指导,使用

python examples/ssd/ssd_pascal.py

来训练ssd网络了,训练完毕后就是这样。
这里写图片描述

4.使用摄像头识别物体

这一步和上一步很相似,只要改动一下examples/ssd/ssd_pascal_webcam.py里面的类别,映射和保存地址就可以了。

num_classes = 10 #mzmshare_location = Truebackground_label_id=9 #mxm
# Stores LabelMapItem.label_map_file = "data/mydataset/labelmap_mydataset.prototxt" #mzm
# Directory which stores the model .prototxt file.save_dir = "models/VGGNet/mydataset1/{}_webcam".format(job_name) #mzm# Directory which stores the snapshot of trained models.snapshot_dir = "models/VGGNet/mydataset1/{}".format(job_name) #mzm# Directory which stores the job script and log file.job_dir = "jobs/VGGNet/mydataset1/{}_webcam".format(job_name) #mzm

然后执行

python examples/ssd/ssd_pascal_webcam.py

就可以看到摄像头拍摄的识别结果了,如下图所示:
这里写图片描述
大功告成!
当然,这只是实现了别人的算法,关于SSD的原理结构以后再说吧。如果有什么错误,还请大家指出。


参考:
[1]http://www.cnblogs.com/EstherLjy/p/6863890.html
[2]https://github.com/LBAWMY/labelme2VOC2007mat
[3]https://github.com/weiliu89/caffe/tree/ssd
[4]http://blog.csdn.net/yhaolpz/article/details/71375762

阅读全文
0 0
原创粉丝点击