深度学习笔记之使用Faster-Rcnn进行目标检测 (实践篇)

简介:

实验

  我使用的代码是Python版本的Faster Rcnn,官方也有Matlab版本的,链接如下:

py-faster-rcnn(python)

faster-rcnn(matlab)

 

 

环境配置

  按照官方的README进行配置就好,不过在这之前大家还是看下硬件要求吧

  • For training smaller networks (ZF, VGG_CNN_M_1024) a good GPU (e.g., Titan, K20, K40, …) with at least 3G of memory suffices

  • For training Fast R-CNN with VGG16, you’ll need a K40 (~11G of memory)

  • For training the end-to-end version of Faster R-CNN with VGG16, 3G of GPU memory is sufficient (using CUDNN)

 

 

我的是环境是Ubuntu 14.04 + Titan X(12GB) + cuda 7.0 + cudnn V3。

 

 

Caffe环境配置

  Caffe环境需要python layer的支持,在你的Caffe的Makefile.config中去掉以下的注释

  • WITH_PYTHON_LAYER := 1
  • USE_CUDNN := 1

 

2 安装python库依赖

cython,python-OpenCVeasydict

pip install cython
pip install python-opencv
pip install easydict

 

3 克隆py-faster-rcnn源代码

git clone --recursive https://github.com/rbgirshick/py-faster-rcnn.git

 

4 编译cython模块

cd $FRCN_ROOT/lib
make 

 

 

5 编译Caffepycaffe

cd $FRCN_ROOT/caffe-fast-rcnn
make -j8 && make pycaffe

-j8的选项是进行多核编译,可以加速编译过程,推荐使用

 

 

数据集

  参考VOC2007的数据集格式,主要包括三个部分:

  • JPEGImages

  • Annotations

  • ImageSets/Main

  JPEGImages —> 存放你用来训练的原始图像

  Annotations —> 存放原始图像中的Object的坐标信息,XML格式

  ImageSets/Main —> 指定用来train,trainval,val和test的图片的编号

  这部分非常重要,数据集做不好直接导致代码出现异常,无法运行,或者出现奇怪的错误,我也是掉进了很多坑,爬上来之后才写的这篇博客,希望大家不要趟我趟过的浑水!每一个部分我都会细说的!

 

 

 

 

JPEGImages

  这个没什么,直接把你的图片放入就可以了,但是有三点注意:

  • 编号要以6为数字命名,例如000034.jpg

  • 图片要是JPEG/JPG格式的,PNG之类的需要自己转换下

  • 图片的长宽比(width/height)要在0.462-6.828之间,就是太过瘦长的图片不要

  

  0.462-6.828是我自己实验得出来的,就我的数据集而言是这个比例,总之长宽比太大或者太小的,你要注意将其剔除,否则可能会出现下面我实验时候出的错:

Traceback (most recent call last): 
File “/usr/lib/python2.7/multiprocessing/process.py”, line 258, in _bootstrap 
self.run() 
File “/usr/lib/python2.7/multiprocessing/process.py”, line 114, in run 
self._target(*self._args, **self._kwargs) 
File “./tools/train_faster_rcnn_alt_opt.py”, line 130, in train_rpn 
max_iters=max_iters) 
File “/home/work-station/zx/py-faster-rcnn/tools/../lib/fast_rcnn/train.py”, line 160, in train_net 
model_paths = sw.train_model(max_iters) 
File “/home/work-station/zx/py-faster-rcnn/tools/../lib/fast_rcnn/train.py”, line 101, in train_model 
self.solver.step(1) 
File “/home/work-station/zx/py-faster-rcnn/tools/../lib/rpn/anchor_target_layer.py”, line 137, in forward 
gt_argmax_overlaps = overlaps.argmax(axis=0) 
ValueError: attempt to get argmax of an empty sequence

  Google给出的原因是 Because the ratio of images width and heights is too small or large,这个非常重要。

 

 

 

Annotations

  faster rcnn训练需要图像的bounding box信息作为监督(ground truth),所以你需要将你的所有可能的object使用框标注,并写上坐标,最终是一个XML格式的文件,一个训练图片对应Annotations下的一个同名的XML文件

  参考官方VOC的Annotations的格式:

复制代码
<annotation>
    <folder>VOC2007</folder> #数据集文件夹
    <filename>000105.jpg</filename> #图片的name
    <source> #注释信息,无所谓有无
        <database>The VOC2007 Database</database>
        <annotation>PASCAL VOC2007</annotation>
        <image>flickr</image>
        <flickrid>321862192</flickrid>
    </source>
    <owner> #注释信息,无所谓有无
        <flickrid>Eric T. Johnson</flickrid>
        <name>?</name>
    </owner>
    <size> #图片大小
        <width>500</width>
        <height>333</height>
        <depth>3</depth>
    </size>
    <segmented>0</segmented>
    <object> #多少个框就有多少个object标签
        <name>boat</name> #bounding box中的object的class name
        <pose>Frontal</pose>
        <truncated>1</truncated>
        <difficult>0</difficult>
        <bndbox>
            <xmin>22</xmin> #框的坐标
            <ymin>1</ymin>
            <xmax>320</xmax>
            <ymax>314</ymax>
        </bndbox>
    </object>
    <object>
        <name>person</name>
        <pose>Frontal</pose>
        <truncated>1</truncated>
        <difficult>0</difficult>
        <bndbox>
            <xmin>202</xmin>
            <ymin>71</ymin>
            <xmax>295</xmax>
            <ymax>215</ymax>
        </bndbox>
    </object>
    <object>
        <name>person</name>
        <pose>Frontal</pose>
        <truncated>1</truncated>
        <difficult>0</difficult>
        <bndbox>
            <xmin>170</xmin>
            <ymin>107</ymin>
            <xmax>239</xmax>
            <ymax>206</ymax>
        </bndbox>
    </object>
</annotation>
复制代码

  这里有一个非常好用的工具VOC框图工具,可以自动帮你生成需要的XML格式,实际中发现格式基本无误,只有小的地方需要改动下,大家对比下就知道怎么改了,我是在Linux下借助sed修改的,这个不难

 

Imagesets/Main

  因为VOC的数据集可以做很多的CV任务,比如Object detection, Semantic segementation, Edge detection等,所以Imageset下有几个子文件夹(Layout, Main, Segementation),我们只要修改下Main下的文件就可以了(train.txttrainval.txtval.txttest.txt),里面写上你想要进行任务的图片的编号

  将上述你的数据集放在py-faster-rcnn/data/VOCdevkit2007/VOC2007下面,替换原始VOC2007的JPEGIMages,Imagesets,Annotations

原始VOC2007下载地址: VOC20007数据集

 

 

 

 

代码修改

  工程目录介绍

  • caffe-fast-rcnn —> caffe框架

  • data —> 存放数据,以及读取文件的cache

  • experiments —>存放配置文件以及运行的log文件,配置文件

  • lib —> python接口

  • models —> 三种模型, ZF(S)/VGG1024(M)/VGG16(L)

  • output —> 输出的model存放的位置,不训练此文件夹没有

  • tools —> 训练和测试的python文件

 

 

修改源文件

faster rcnn有两种各种训练方式:

  • Alternative training(alt-opt)

  • Approximate joint training(end-to-end)

 

 

  推荐使用第二种,因为第二种使用的显存更小,而且训练会更快,同时准确率差不多,两种方式需要修改的代码是不一样的,同时faster rcnn提供了三种训练模型,小型的ZFmodel,中型的VGG_CNN_M_1024和大型的VGG16,论文中说VGG16效果比其他两个好,但是同时占用更大的GPU显存(~11GB)

  我使用的是VGG model + alternative training,需要检测的类别只有一类,加上背景所以总共是两类(background + captcha)

  py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt/stage1_fast_rcnn_train.pt

复制代码
layer {  
  name: 'data'  
  type: 'Python'  
  top: 'data'  
  top: 'rois'  
  top: 'labels'  
  top: 'bbox_targets'  
  top: 'bbox_inside_weights'  
  top: 'bbox_outside_weights'  
  python_param {  
    module: 'roi_data_layer.layer'  
    layer: 'RoIDataLayer'  
    param_str: "'num_classes': 2" #按训练集类别改,该值为类别数+1  
  }  
}  
复制代码

 

 

复制代码
layer {  
  name: "cls_score"  
  type: "InnerProduct"  
  bottom: "fc7"  
  top: "cls_score"  
  param { 
  lr_mult: 1.0
  }  
  param {
  lr_mult: 2.0 
  }  
  inner_product_param {  
    num_output: 2 #按训练集类别改,该值为类别数+1  
    weight_filler {  
      type: "gaussian"  
      std: 0.01  
    }  
    bias_filler {  
      type: "constant"  
      value: 0  
    }  
  }  
}  
复制代码

 

复制代码
layer {  
  name: "bbox_pred"  
  type: "InnerProduct"  
  bottom: "fc7"  
  top: "bbox_pred"  
  param { 
  lr_mult: 1.0 
  }  
  param { 
  lr_mult: 2.0 
  }  
  inner_product_param {  
    num_output: 8 #按训练集类别改,该值为(类别数+1)*4,四个顶点坐标  
    weight_filler {  
      type: "gaussian"  
      std: 0.001  
    }  
    bias_filler {  
      type: "constant"  
      value: 0  
    }  
  }  
}  
复制代码

 

 

 

  py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt/stage1_rpn_train.pt

复制代码
layer {  
  name: 'input-data'  
  type: 'Python'  
  top: 'data'  
  top: 'im_info'  
  top: 'gt_boxes'  
  python_param {  
    module: 'roi_data_layer.layer'  
    layer: 'RoIDataLayer'  
    param_str: "'num_classes': 2" #按训练集类别改,该值为类别数+1  
  }  
}  
复制代码

 

 

 

  py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt/stage2_fast_rcnn_train.pt

复制代码
layer {  
  name: 'data'  
  type: 'Python'  
  top: 'data'  
  top: 'rois'  
  top: 'labels'  
  top: 'bbox_targets'  
  top: 'bbox_inside_weights'  
  top: 'bbox_outside_weights'  
  python_param {  
    module: 'roi_data_layer.layer'  
    layer: 'RoIDataLayer'  
    param_str: "'num_classes': 2" #按训练集类别改,该值为类别数+1  
  }  
}  
复制代码

 

 

复制代码
layer {  
  name: "cls_score"  
  type: "InnerProduct"  
  bottom: "fc7"  
  top: "cls_score"  
  param { 
  lr_mult: 1.0 
  }  
  param { 
  lr_mult: 2.0 
  }  
  inner_product_param {  
    num_output: 2 #按训练集类别改,该值为类别数+1  
    weight_filler {  
      type: "gaussian"  
      std: 0.01  
    }  
    bias_filler {  
      type: "constant"  
      value: 0  
    }  
  }  
}  
复制代码

 

复制代码
layer {  
  name: "bbox_pred"  
  type: "InnerProduct"  
  bottom: "fc7"  
  top: "bbox_pred"  
  param { 
  lr_mult: 1.0
  }  
  param { 
  lr_mult: 2.0 
  }  
  inner_product_param {  
    num_output: 8 #按训练集类别改,该值为(类别数+1)*4,四个顶点坐标  
    weight_filler {  
      type: "gaussian"  
      std: 0.001  
    }  
    bias_filler {  
      type: "constant"  
      value: 0  
    }  
  }  
}  
复制代码

 

 

 

  py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt/stage2_rpn_train.pt

复制代码
layer {  
  name: 'input-data'  
  type: 'Python'  
  top: 'data'  
  top: 'im_info'  
  top: 'gt_boxes'  
  python_param {  
    module: 'roi_data_layer.layer'  
    layer: 'RoIDataLayer'  
    param_str: "'num_classes': 2" #按训练集类别改,该值为类别数+1  
  }  
}  
复制代码

 

 

  py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt/faster_rcnn_test.pt

复制代码
layer {  
  name: "cls_score"  
  type: "InnerProduct"  
  bottom: "fc7"  
  top: "cls_score"  
  inner_product_param {  
    num_output: 2 #按训练集类别改,该值为类别数+1  
  }  
}  
复制代码

 

 

  py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt/faster_rcnn_test.pt

复制代码
layer {  
  name: "cls_score"  
  type: "InnerProduct"  
  bottom: "fc7"  
  top: "cls_score"  
  inner_product_param {  
    num_output: 2 #按训练集类别改,该值为类别数+1  
  }  
}  
复制代码

 

 

 

  py-faster-rcnn/lib/datasets/pascal_voc.py

复制代码
class pascal_voc(imdb):  
    def __init__(self, image_set, year, devkit_path=None):  
        imdb.__init__(self, 'voc_' + year + '_' + image_set)  
        self._year = year  
        self._image_set = image_set  
        self._devkit_path = self._get_default_path() if devkit_path is None \  
                            else devkit_path  
        self._data_path = os.path.join(self._devkit_path, 'VOC' + self._year)  
        self._classes = ('__background__', # always index 0  
                         captcha' # 有几个类别此处就写几个,我是两个
                      )  
复制代码

  line 212

cls = self._class_to_ind[obj.find('name').text.lower().strip()]  

 

  如果你的标签含有大写字母,可能会出现KeyError的错误,所以建议全部使用小写字母

  py-faster-rcnn/lib/datasets/imdb.py

  将append_flipped_images函数改为如下形式:

复制代码
def append_flipped_images(self):  
        num_images = self.num_images  
        widths = [PIL.Image.open(self.image_path_at(i)).size[0]  
                  for i in xrange(num_images)]  
        for i in xrange(num_images):  
            boxes = self.roidb[i]['boxes'].copy()  
            oldx1 = boxes[:, 0].copy()  
            oldx2 = boxes[:, 2].copy()  
            boxes[:, 0] = widths[i] - oldx2 - 1  
            print boxes[:, 0]  
            boxes[:, 2] = widths[i] - oldx1 - 1  
            print boxes[:, 0]  
            assert (boxes[:, 2] >= boxes[:, 0]).all()  
            entry = {'boxes' : boxes,  
                     'gt_overlaps' : self.roidb[i]['gt_overlaps'],  
                     'gt_classes' : self.roidb[i]['gt_classes'],  
                     'flipped' : True}  
            self.roidb.append(entry)  
        self._image_index = self._image_index * 2  
复制代码

  到此代码修改就搞定了

 

 

 

训练

  训练前还需要注意几个地方

1 cache问题

  假如你之前训练了官方的VOC2007的数据集或其他的数据集,是会产生cache的问题的,建议在重新训练新的数据之前将其删除

(1) py-faster-rcnn/output 
(2) py-faster-rcnn/data/cache

 

 

2 训练参数

  py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt/stage_fast_rcnn_solver*.pt

base_lr: 0.001
lr_policy: 'step'
step_size: 30000
display: 20
....

  迭代次数在文件py-faster-rcnn/tools/train_faster_rcnn_alt_opt.py中进行修改

 

line 80

max_iters = [80000, 40000, 80000, 40000]

 

 

  分别对应rpn第1阶段,fast rcnn第1阶段,rpn第2阶段,fast rcnn第2阶段的迭代次数,自己修改即可,不过注意这里的值不要小于上面的solver里面的step_size的大小,大家自己修改吧。

 

开始训练:

cd py-faster-rcnn
./experiments/scripts/faster_rcnn_alt_opt.sh 0 VGG16 pascal_voc 

  指明使用第一块GPU(0),模型是VGG16,训练数据是pascal_voc(voc2007),没问题的话应该可以迭代训练了

 

 

 

结果

训练完毕,得到我们的训练模型,我们就可以使用它来进行我们的object detection了,具体是: 
1 将py-faster-rcnn/output/faster_rcnn_alt_opt/voc_2007_trainval/VGG16_faster_rcnn_final.caffemodel,拷贝到py-faster-rcnn/data/faster_rcnn_models

2 将你需要进行test的images放在py-faster-rcnn/data/demo

3 修改py-faster-rcnn/tools/demo.py文件


CLASSES = ('_background_', 'captcha') #参考你自己的类别写 


NETS = {'vgg16': ('VGG16', 
'VGG16_faster_rcnn_final.caffemodel'), #改成你训练得到的model的name 
'zf': ('ZF', 
'ZF_faster_rcnn_final.caffemodel') 
}

im_names = ['1559.jpg','1564.jpg']  # 改成自己的test image的name

 

 

 

 

上几张我的检测结果吧

1

 

2

3



本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/6973242.html,如需转载请自行联系原作者

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
相关文章
|
1月前
|
机器学习/深度学习 传感器 数据采集
深度学习在故障检测中的应用:从理论到实践
深度学习在故障检测中的应用:从理论到实践
163 6
|
2月前
|
机器学习/深度学习 人工智能 TensorFlow
人工智能浪潮下的自我修养:从Python编程入门到深度学习实践
【10月更文挑战第39天】本文旨在为初学者提供一条清晰的道路,从Python基础语法的掌握到深度学习领域的探索。我们将通过简明扼要的语言和实际代码示例,引导读者逐步构建起对人工智能技术的理解和应用能力。文章不仅涵盖Python编程的基础,还将深入探讨深度学习的核心概念、工具和实战技巧,帮助读者在AI的浪潮中找到自己的位置。
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
揭秘人工智能:深度学习的奥秘与实践
在本文中,我们将深入浅出地探索深度学习的神秘面纱。从基础概念到实际应用,你将获得一份简明扼要的指南,助你理解并运用这一前沿技术。我们避开复杂的数学公式和冗长的论述,以直观的方式呈现深度学习的核心原理和应用实例。无论你是技术新手还是有经验的开发者,这篇文章都将为你打开一扇通往人工智能新世界的大门。
|
1月前
|
机器学习/深度学习 算法 TensorFlow
深度学习中的自编码器:从理论到实践
在这篇文章中,我们将深入探讨深度学习的一个重要分支——自编码器。自编码器是一种无监督学习算法,它可以学习数据的有效表示。我们将首先介绍自编码器的基本概念和工作原理,然后通过一个简单的Python代码示例来展示如何实现一个基本的自编码器。最后,我们将讨论自编码器的一些变体,如稀疏自编码器和降噪自编码器,以及它们在实际应用中的优势。
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
揭秘AI:深度学习的奥秘与实践
本文将深入浅出地探讨人工智能中的一个重要分支——深度学习。我们将从基础概念出发,逐步揭示深度学习的原理和工作机制。通过生动的比喻和实际代码示例,本文旨在帮助初学者理解并应用深度学习技术,开启AI之旅。
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
深入浅出深度学习:从理论到实践的探索之旅
在人工智能的璀璨星空中,深度学习如同一颗耀眼的新星,以其强大的数据处理能力引领着技术革新的浪潮。本文将带您走进深度学习的核心概念,揭示其背后的数学原理,并通过实际案例展示如何应用深度学习模型解决现实世界的问题。无论您是初学者还是有一定基础的开发者,这篇文章都将为您提供宝贵的知识和启发。
60 5
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习中的卷积神经网络(CNN): 从理论到实践
本文将深入浅出地介绍卷积神经网络(CNN)的工作原理,并带领读者通过一个简单的图像分类项目,实现从理论到代码的转变。我们将探索CNN如何识别和处理图像数据,并通过实例展示如何训练一个有效的CNN模型。无论你是深度学习领域的新手还是希望扩展你的技术栈,这篇文章都将为你提供宝贵的知识和技能。
397 7
|
2月前
|
机器学习/深度学习 自然语言处理 语音技术
深入探索深度学习中的兼容性函数:从原理到实践
深入探索深度学习中的兼容性函数:从原理到实践
45 3
|
2月前
|
机器学习/深度学习 自然语言处理 网络架构
深度学习中的正则化技术:从理论到实践
在深度学习的海洋中,正则化技术如同灯塔指引着模型训练的方向。本文将深入探讨正则化的核心概念、常见类型及其在防止过拟合中的应用。通过实例分析,我们将展示如何在实践中运用这些技术以提升模型的泛化能力。
|
3月前
|
机器学习/深度学习 调度 计算机视觉
深度学习中的学习率调度:循环学习率、SGDR、1cycle 等方法介绍及实践策略研究
本文探讨了多种学习率调度策略在神经网络训练中的应用,强调了选择合适学习率的重要性。文章介绍了阶梯式衰减、余弦退火、循环学习率等策略,并分析了它们在不同实验设置下的表现。研究表明,循环学习率和SGDR等策略在提高模型性能和加快训练速度方面表现出色,而REX调度则在不同预算条件下表现稳定。这些策略为深度学习实践者提供了实用的指导。
92 2
深度学习中的学习率调度:循环学习率、SGDR、1cycle 等方法介绍及实践策略研究

相关实验场景

更多