【目标检测】SSD目标检测

原创
2018/03/21 19:30
阅读数 93

导语

PaddlePaddle提供了丰富的运算单元,帮助大家以模块化的方式构建起千变万化的深度学习模型来解决不同的应用问题。这里,我们针对常见的机器学习任务,提供了不同的神经网络模型供大家学习和使用。本周推文目录如下:


3.19:【图像分类】

如何转化模型文件

3.20:【图像分类】

使用经典模型进行图像分类

3.21:【目标检测】

SSD目标检测

3.22:【场景文字识别】

场景文字识别



目标检测任务的目标是给定一张图像或是视频帧,让计算机找出其中所有目标的位置,并给出每个目标的具体类别。对于人类来说,目标检测是一个非常简单的任务。然而,计算机能够“看到”的仅有一些值为0 ~ 255的矩阵,很难解图像或是视频帧中出现了人或是物体这样的高层语义概念,也就更加难以定位目标出现在图像中哪个区域。与此同时,由于目标会出现在图像或是视频帧中的任何位置,目标的形态千变万化,图像或是视频帧的背景千差万别,诸多因素都使得目标检测对计算机来说是一个具有挑战性的问题。



 【目标检测】 

SSD目标检测


|1. 概述


SSD全称:Single Shot MultiBox Detector,是目标检测领域较新且效果较好的检测算法之一[1],有着检测速度快且检测精度高的特点。PaddlePaddle已集成SSD算法,本示例旨在介绍如何使用PaddlePaddle中的SSD模型进行目标检测。下文首先简要介绍SSD原理,然后介绍示例包含文件及如何使用,接着介绍如何在PASCAL VOC数据集上训练、评估及检测,最后简要介绍如何在自有数据集上使用SSD。



|2. SSD原理


SSD使用一个卷积神经网络实现“端到端”的检测:输入为原始图像,输出为检测结果,无需借助外部工具或流程进行特征提取、候选框生成等。论文中SSD使用VGG16[2]作为基础网络进行图像特征提取。但SSD对原始VGG16网络做了一些改变:


  1. 将最后的fc6、fc7全连接层变为卷积层,卷积层参数通过对原始fc6、fc7参数采样得到。

  2. 将pool5层的参数由2x2-s2(kernel大小为2x2,stride size为2)更改为3x3-s1-p1(kernel大小为3x3,stride size为1,padding size为1)。

  3. 在conv4_3、conv7、conv8_2、conv9_2、conv10_2及pool11层后面接了priorbox层,priorbox层的主要目的是根据输入的特征图(feature map)生成一系列的矩形候选框。更详细的介绍可参考[1]。


下图为模型(输入图像尺寸:300x300)的总体结构:

640?wx_fmt=png 640?wx_fmt=png


图1. SSD 网络结构

图中每个矩形盒子代表一个卷积层,最后两个矩形框分别表示汇总各卷积层输出结果和后处理阶段。在预测阶段,网络会输出一组候选矩形框,每个矩形包含:位置和类别得分。图中倒数第二个矩形框即表示网络的检测结果的汇总处理。由于候选矩形框数量较多且很多矩形框重叠严重,这时需要经过后处理来筛选出质量较高的少数矩形框,主要方法有非极大值抑制(Non-maximum Suppression)。


从SSD的网络结构可以看出,候选矩形框在多个特征图(feature map)上生成,不同的feature map具有的感受野不同,这样可以在不同尺度扫描图像,相对于其他检测方法可以生成更丰富的候选框,从而提高检测精度;另一方面SSD对VGG16的扩展部分以较小的代价实现对候选框的位置和类别得分的计算,整个过程只需要一个卷积神经网络完成,所以速度较快。



|3.示例总览


本示例共包含如下文件:

640?wx_fmt=png 640?wx_fmt=png


表1. 示例文件

训练阶段需要对数据做预处理,包括裁剪、采样等,这部分操作在image_util.pydata_provider.py中完成。


需要注意:config/vgg_config.py是参数配置文件,含有训练参数、神经网络参数等。配置文件中的参数针对PASCAL VOC数据集而配置,当训练自有数据时,需要进行针对性的修改。


data/prepare_voc_data.py脚本用来生成文件列表,包括切分训练集和测试集,使用时需要事先下载并解压数据,默认采用VOC2007和VOC2012。



|4. PASCAL VOC数据集


[1]数据准备


请首先下载数据集:VOC2007[3]和VOC2012[4]。VOC2007包含训练集和测试集,VOC2012只包含训练集,将下载好的数据解压,目录结构为data/VOCdevkit/VOC2007data/VOCdevkit/VOC2012

进入data目录,运行python prepare_voc_data.py即可生成trainval.txttest.txt。核心函数为:

def prepare_filelist(devkit_dir, years, output_dir):

    trainval_list = []

    test_list = []

    for year in years:

        trainval, test = walk_dir(devkit_dir, year)

        trainval_list.extend(trainval)

        test_list.extend(test)

    random.shuffle(trainval_list)

    with open(osp.join(output_dir, 'trainval.txt'), 'w') as ftrainval:

        for item in trainval_list:

            ftrainval.write(item[0] + ' ' + item[1] + '\n')


    with open(osp.join(output_dir, 'test.txt'), 'w') as ftest:

        for item in test_list:

            ftest.write(item[0] + ' ' + item[1] + '\n')


该函数首先对每一年(year)数据进行处理,然后将训练图像的文件路径列表进行随机乱序,最后保存训练文件列表和测试文件列表。默认prepare_voc_data.pyVOCdevkit在相同目录下,且生成的文件列表也在该目录次数。


需注意trainval.txt既包含VOC2007的训练数据,也包含VOC2012的训练数据,test.txt只包含VOC2007的测试数据。


下面是trainval.txt前几行输入示例:

```text

VOCdevkit/VOC2007/JPEGImages/000005.jpg VOCdevkit/VOC2007/Annotations/000005.xml

VOCdevkit/VOC2007/JPEGImages/000007.jpg VOCdevkit/VOC2007/Annotations/000007.xml

VOCdevkit/VOC2007/JPEGImages/000009.jpg VOCdevkit/VOC2007/Annotations/000009.xml

```

文件共两个字段,第一个字段为图像文件的相对路径,第二个字段为对应标注文件的相对路径。


[2]预训练模型准备


下载预训练的VGG-16模型,我们提供了一个转换好的模型,下载模型http://paddlepaddle.bj.bcebos.com/model_zoo/detection/ssd_model/vgg_model.tar.gz,并将其放置路径为vgg/vgg_model.tar.gz


[3]模型训练


直接执行python train.py即可进行训练。需要注意本示例仅支持CUDA GPU环境,无法在CPU上训练,主要因为使用CPU训练速度很慢,实践中一般使用GPU来处理图像任务,这里实现采用硬编码方式使用cuDNN,不提供CPU版本。train.py的一些关键执行逻辑:

paddle.init(use_gpu=True, trainer_count=4)

data_args = data_provider.Settings(

                data_dir='./data',

                label_file='label_list',

                resize_h=cfg.IMG_HEIGHT,

                resize_w=cfg.IMG_WIDTH,

                mean_value=[104,117,124])

train(train_file_list='./data/trainval.txt',

      dev_file_list='./data/test.txt',

      data_args=data_args,

   init_model_path='./vgg/vgg_model.tar.gz')


主要包括:


  1. 调用paddle.init指定使用4卡GPU训练。

  2. 调用data_provider.Settings配置数据预处理所需参数,其中cfg.IMG_HEIGHTcfg.IMG_WIDTH在配置文件config/vgg_config.py中设置,这里均为300,300x300是一个典型配置,兼顾效率和检测精度,也可以通过修改配置文件扩展到512x512。

  3. 调用train执行训练,其中train_file_list指定训练数据列表,dev_file_list指定评估数据列表,init_model_path指定预训练模型位置。

  4. 训练过程中会打印一些日志信息,每训练1个batch会输出当前的轮数、当前batch的cost及mAP(mean Average Precision,平均精度均值),每训练一个pass,会保存一次模型,默认保存在checkpoints目录下(注:需事先创建)。


下面给出SDD300x300在VOC数据集(train包括07+12,test为07)上的mAP曲线,迭代140轮mAP可达到71.52%。

640?wx_fmt=png 640?wx_fmt=png


图2. SSD300x300 mAP收敛曲线

[4]模型评估


执行python eval.py即可对模型进行评估,eval.py的关键执行逻辑如下:

paddle.init(use_gpu=True, trainer_count=4)  # use 4 gpus


data_args = data_provider.Settings(

    data_dir='./data',

    label_file='label_list',

    resize_h=cfg.IMG_HEIGHT,

    resize_w=cfg.IMG_WIDTH,

    mean_value=[104, 117, 124])


eval(

    eval_file_list='./data/test.txt',

    batch_size=4,

    data_args=data_args,

    model_path='models/pass-00000.tar.gz')


调用paddle.init指定使用4卡GPU评估;data_provider.Settings参见训练阶段的配置;调用eval执行评估,其中eval_file_list指定评估数据列表,batch_size指定评估时batch size的大小,model_path指定模型:位置。评估结束会输出loss信息和mAP信息。


[5]图像检测


执行python infer.py即可使用训练好的模型对图片实施检测,infer.py关键逻辑如下:

infer(

    eval_file_list='./data/infer.txt',

    save_path='infer.res',

    data_args=data_args,

    batch_size=4,

    model_path='models/pass-00000.tar.gz',

    threshold=0.3)


其中eval_file_list指定图像路径列表;save_path指定预测结果保存路径;data_args如上;batch_size为每多少样本预测一次;model_path指模型的位置;threshold为置信度阈值,只有得分大于或等于该值的才会输出。下面给出infer.res的一些输出样例:

VOCdevkit/VOC2007/JPEGImages/006936.jpg 12 0.997844 131.255611777 162.271582842 396.475315094 334.0

VOCdevkit/VOC2007/JPEGImages/006936.jpg 14 0.998557 229.160234332 49.5991278887 314.098775387 312.913876176

VOCdevkit/VOC2007/JPEGImages/006936.jpg 14 0.372522 187.543615699 133.727034628 345.647156239 327.448492289

...


共包含4个字段,以tab分割,第一个字段是检测图像路径,第二字段为检测矩形框内类别,第三个字段是置信度,第四个字段是4个坐标值(以空格分割)。


示例还提供了一个可视化脚本,直接运行python visual.py即可,须指定输出检测结果路径及输出目录,默认可视化后图像保存在./visual_res,下面是用训练好的模型infer部分图像并可视化的效果:

640?wx_fmt=png 640?wx_fmt=png


图3. SSD300x300 检测可视化示例



|5. 自有数据集


在自有数据上训练PaddlePaddle SSD需要完成两个关键准备,首先需要适配网络可以接受的输入格式,这里提供一个推荐的结构,以train.txt为例

image00000_file_path    image00000_annotation_file_path

image00001_file_path    image00001_annotation_file_path

image00002_file_path    image00002_annotation_file_path

...


文件共两列,以空白符分割,第一列为图像文件的路径,第二列为对应标注数据的文件路径。对图像文件的读取比较直接,略微复杂的是对标注数据的解析,本示例中标注数据使用xml文件存储,所以需要在data_provider.py中对xml解析,核心逻辑如下:

bbox_labels = []

root = xml.etree.ElementTree.parse(label_path).getroot()

for object in root.findall('object'):

    bbox_sample = []

    # start from 1

 bbox_sample.append(float(settings.label_list.index(

         object.find('name').text)))

    bbox = object.find('bndbox')

    difficult = float(object.find('difficult').text)

 bbox_sample.append(float(bbox.find('xmin').text)/img_width)

bbox_sample.append(float(bbox.find('ymin').text)/img_height)

bbox_sample.append(float(bbox.find('xmax').text)/img_width)

bbox_sample.append(float(bbox.find('ymax').text)/img_height)

    bbox_sample.append(difficult)

    bbox_labels.append(bbox_sample)


这里一条标注数据包括:label、xmin、ymin、xmax、ymax和is_difficult,is_difficult表示该object是否为难例,实际中如果不需要,只需把该字段置零即可。自有数据也需要提供对应的解析逻辑,假设标注数据(比如image00000_annotation_file_path)存储格式如下:

label1 xmin1 ymin1 xmax1 ymax1

label2 xmin2 ymin2 xmax2 ymax2

...


每行对应一个物体,共5个字段,第一个为label(注背景为0,需从1编号),剩余4个为坐标,对应的解析逻辑可更改为如下:

bbox_labels = []

with open(label_path) as flabel:

    for line in flabel:

        bbox_sample = []

        bbox = [float(i) for i in line.strip().split()]

        label = bbox[0]

        bbox_sample.append(label)

        bbox_sample.append(bbox[1]/float(img_width))

bbox_sample.append(bbox[2]/float(img_height))      bbox_sample.append(bbox[3]/float(img_width))  bbox_sample.append(bbox[4]/float(img_height))

        bbox_sample.append(0.0)

        bbox_labels.append(bbox_sample)



同时需要注意根据图像大小及检测物体的大小等更改网络结构相关的超参数,请仿照config/vgg_config.py创建自己的配置文件,参数设置经验请参考论文[1]。



【参考文献】


  • Wei Liu, Dragomir Anguelov, Dumitru Erhan, Christian Szegedy, Scott Reed, Cheng-Yang Fu, Alexander C. Berg. SSD: Single shot multibox detector. European conference on computer vision. Springer, Cham, 2016.

  • Simonyan, Karen, and Andrew Zisserman. Very deep convolutional networks for large-scale image recognition. arXiv preprint arXiv:1409.1556 (2014).

  • The PASCAL Visual Object Classes Challenge 2007

  • Visual Object Classes Challenge 2012 (VOC2012)



 end


*原创贴,版权所有,未经许可,禁止转载

*值班小Paddle:wangp

*欢迎在留言区分享您的观点


*为了方便大家问题的跟进解决,我们采用Github Issue来采集信息和追踪进度。大家遇到问题请搜索Github Issue,问题未解决请优先在Github Issue上提问,有助于问题的积累和沉淀


640?wx_fmt=png


点击“阅读原文”,访问Github Issue。

本文分享 CSDN - 飞桨PaddlePaddle。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部