[深度学习] RCNNs系列(1) Ubuntu下Faster RCNN配置及训练和测试自己的数据方法
最近用到Faster RCNN进行目标检测,前前后后两周把RCNN,SPPNet,Fast RCNN和Faster RCNN大体调查了一遍,准备写一个RCNNs系列,后面还要加上今年最新的Mask RCNN。
要想开个头,知道RCNNs在目标检测方向的优势,那就先用用作者的代码,跑跑自己的代码,下面就是在Ubuntu下进行Faster RCNN配置的方法。
一、Faster RCNN环境配置及demo运行
- git clone --recursive https://github.com/rbgirshick/py-faster-rcnn.git
(2)安装cpython和python-opencv
- pip install cpython
- apt-get install python-opencv
(3)下载Faster RCNN并安装好cpython以后,进入py-faster-rcnn/lib中使用命令编译一下
- make
- 把Caffe中的include/caffe/layers/cudnn_relu_layer.hpp,/include/caffe/layers/cudnn_sigmoid_layer.hpp,/include/caffe/layers/cudnn_tanh_layer.hpp和/include/caffe/util/cudnn.hpp替换py-faster-rcnn/caffe-fast-rcnn中对应的文件;
- 把Caffe中的src/caffe/layers/cudnn_relu_layer.cpp,src/caffe/layers/cudnn_relu_layer.cu,src/caffe/layers/cudnn_sigmoid_layer.cpp,src/caffe/layers/cudnn_sigmoid_layer.cu,src/caffe/layer/cudnn_tanh_layer.cpp,src/caffe/layers/cudnn_tanh_layer.cu替换掉py-faster-rcnn/caffe-fast-rcnn中对应的文件;
- 把py-faster-rcnn/caffe-fast-rcnn中src/caffe/layers/cudnn_conv_layer.cu文件中的cudnnConvolutionBackwardData_v3全部换为cudnnConvolutionBackwardData,把cudnnConvolutionBackwardFilter_v3全部换为cudnnConvolutionBackwardFilter。
如果自己的显卡配置足够的话,强烈建议开启cudnn,cudnn不仅可以起到加速的作用,而且我跑实验的时候发现加入cudnn以后可以明显的降低显存的使用。如下图所示:
- make -j8 && make pycaffe
(6)这个时候,基本上faster RCNN也就配置好了,让我们看一下是否真的能够运行。首先我们下载几个作者已经训练好的caffemodel,如果现在直接运行demo.py的话会提示你没有caffemodel文件,然后询问是否运行过py-faster-rcnn/data/scripts/fetch_faster_rcnn_models.sh文件,我们可以找到该文件中的下载链接,用迅雷一会就可以下载好,如果直接运行该文件可能要不少时间。把下载好的文件中VGG16_faster_rcnn_final.caffemodel文件复制到py-faster-rcnn/data/faster_rcnn_models中
- import google.protobuf.text_format
再次运行demo.py文件,这次应该可以运行成功!
二、Faster RCNN训练自己的数据
2.1 建立数据集
- Train_IMG\000001.jpg 97 6 174 202 305
- Train_IMG\000001.jpg 8 56 198 282 162
- ......省略若干行
- Train_IMG\000001.jpg 90 537 194 699 314
其中每个图像对应一个bounding box文件,每个文件中的每一行表示一个目标的bounding box,每一行由6列数据组成,第1列数据为图像的路径,第2列为该目标的分类,第3列为bounding box的左上角的x(对应图像的列,即mincol),第4列为bounding box的左上角的y(对应图像的行,即minrow),第5列为bounding box的右下角的x(对应图像的列,即maxcol),第6列为bounding box右下角的y(对应图像的行,即maxrow)。
- # -*- coding:utf-8 -*-
- __author__ = "peic"
- import xml.dom
- import xml.dom.minidom
- import os
- from PIL import Image
- '''''
- 根据下面的路径和文件,将output.txt制作成xml的标注
- '''
- # xml文件规范定义
- _INDENT = ' ' * 4
- _NEW_LINE = '\n'
- _FOLDER_NODE = 'VOC2007'
- _ROOT_NODE = 'annotation'
- _DATABASE_NAME = 'CROHME offline ME Dataset'
- _CLASS = 'person'
- _ANNOTATION = 'PASCAL VOC2007'
- _AUTHOR = 'hanchao'
- _SEGMENTED = '0'
- _DIFFICULT = '0'
- _TRUNCATED = '0'
- _POSE = 'Unspecified'
- #需要注意,这一项是存放bounding box对应图像的目录
- _IMAGE_PATH = 'Train_IMG'
- #这一项是保存生成xml文件的目录
- _ANNOTATION_SAVE_PATH = 'Annotations'
- _IMAGE_CHANNEL = 3
- # 封装创建节点的过程
- def createElementNode(doc, tag, attr):
- # 创建一个元素节点
- element_node = doc.createElement(tag)
- # 创建一个文本节点
- text_node = doc.createTextNode(attr)
- # 将文本节点作为元素节点的子节点
- element_node.appendChild(text_node)
- return element_node
- # 封装添加一个子节点的过程
- def createChildNode(doc, tag, attr, parent_node):
- child_node = createElementNode(doc, tag, attr)
- parent_node.appendChild(child_node)
- # object节点比较特殊
- def createObjectNode(doc, attrs):
- object_node = doc.createElement('object')
- createChildNode(doc, 'name', attrs['classification'], object_node)
- createChildNode(doc, 'pose', _POSE, object_node)
- createChildNode(doc, 'truncated', _TRUNCATED, object_node)
- createChildNode(doc, 'difficult', _DIFFICULT, object_node)
- bndbox_node = doc.createElement('bndbox')
- createChildNode(doc, 'xmin', attrs['xmin'], bndbox_node)
- createChildNode(doc, 'ymin', attrs['ymin'], bndbox_node)
- createChildNode(doc, 'xmax', attrs['xmax'], bndbox_node)
- createChildNode(doc, 'ymax', attrs['ymax'], bndbox_node)
- object_node.appendChild(bndbox_node)
- return object_node
- # 将documentElement写入XML文件中
- def writeXMLFile(doc, filename):
- tmpfile = open('tmp.xml', 'w')
- doc.writexml(tmpfile, addindent=' '*4, newl='\n', encoding='utf-8')
- tmpfile.close()
- # 删除第一行默认添加的标记
- fin = open('tmp.xml')
- fout = open(filename, 'w')
- lines = fin.readlines()
- for line in lines[1:]:
- if line.split():
- fout.writelines(line)
- #new_lines = ''.join(lines[1:])
- #fout.write(new_lines)
- fin.close()
- fout.close()
- # 创建XML文档并写入节点信息
- def createXMLFile(attrs, width, height, filename):
- # 创建文档对象, 文档对象用于创建各种节点
- my_dom = xml.dom.getDOMImplementation()
- doc = my_dom.createDocument(None, _ROOT_NODE, None)
- # 获得根节点
- root_node = doc.documentElement
- # folder节点
- createChildNode(doc, 'folder', _FOLDER_NODE, root_node)
- # filename节点
- createChildNode(doc, 'filename', attrs['name'], root_node)
- # source节点
- source_node = doc.createElement('source')
- # source的子节点
- createChildNode(doc, 'database', _DATABASE_NAME, source_node)
- createChildNode(doc, 'annotation', _ANNOTATION, source_node)
- createChildNode(doc, 'image', 'flickr', source_node)
- createChildNode(doc, 'flickrid', 'NULL', source_node)
- root_node.appendChild(source_node)
- # owner节点
- owner_node = doc.createElement('owner')
- # owner的子节点
- createChildNode(doc, 'flickrid', 'NULL', owner_node)
- createChildNode(doc, 'name', _AUTHOR, owner_node)
- root_node.appendChild(owner_node)
- # size节点
- size_node = doc.createElement('size')
- createChildNode(doc, 'width', str(width), size_node)
- createChildNode(doc, 'height', str(height), size_node)
- createChildNode(doc, 'depth', str(_IMAGE_CHANNEL), size_node)
- root_node.appendChild(size_node)
- # segmented节点
- createChildNode(doc, 'segmented', _SEGMENTED, root_node)
- # object节点
- object_node = createObjectNode(doc, attrs)
- root_node.appendChild(object_node)
- # 写入文件
- writeXMLFile(doc, filename)
- def generate_xml(txt_filename):
- #注意,这里的txt_filename文件是待转换的bounding box文件
- ouput_file = open(txt_filename)
- current_dirpath = os.path.dirname(os.path.abspath('__file__'))
- if not os.path.exists(_ANNOTATION_SAVE_PATH):
- os.mkdir(_ANNOTATION_SAVE_PATH)
- lines = ouput_file.readlines()
- for line in lines:
- s = line.rstrip()
- array = s.split(' ')
- #print len(array)
- attrs = dict()
- attrs['name'] = array[0].split('\\')[1]
- attrs['classification'] = array[1]
- attrs['xmin'] = array[2]
- attrs['ymin'] = array[3]
- attrs['xmax'] = array[4]
- attrs['ymax'] = array[5]
- # 构建XML文件名称
- xml_file_name = os.path.join(_ANNOTATION_SAVE_PATH, (attrs['name'].split('.'))[0] + '.xml')
- #print xml_file_name
- if os.path.exists( xml_file_name):
- # print('do exists')
- existed_doc = xml.dom.minidom.parse(xml_file_name)
- root_node = existed_doc.documentElement
- # 如果XML存在了, 添加object节点信息即可
- object_node = createObjectNode(existed_doc, attrs)
- root_node.appendChild(object_node)
- # 写入文件
- writeXMLFile(existed_doc, xml_file_name)
- else:
- # print('not exists')
- # 如果XML文件不存在, 创建文件并写入节点信息
- img_name = attrs['name']
- img_path = os.path.join(current_dirpath, _IMAGE_PATH, img_name)
- # 获取图片信息
- img = Image.open(img_path)
- width, height = img.size
- img.close()
- # 创建XML文件
- createXMLFile(attrs, width, height, xml_file_name)
执行的Main程序如下:
- #coding=utf-8
- '''''
- Created on 2017年4月18日
- @author: hanchao
- '''
- import generate_xml
- import os.path
- import cv2
- #
- if __name__ == "__main__":
- for dir,path,filenames in os.walk('Train_BB'):#Train_BB是存放bounding box文件的目录
- for filename in filenames:
- print dir + '/' + filename
- generate_xml.generate_xml(dir + '/' + filename)
最终生成的xml文件会保存在Annotations目录中。
2.2 训练自己的数据
- time /home/hanchao/py-faster-rcnn/tools/train_net.py --gpu ${GPU_ID} \
- --solver /home/hanchao/py-faster-rcnn/models/${PT_DIR}/${NET}/faster_rcnn_end2end/solver.prototxt \
- --weights /home/hanchao/py-faster-rcnn/data/imagenet_models/${NET}.v2.caffemodel \
- --imdb ${TRAIN_IMDB} \
- --iters ${ITERS} \
- --cfg /home/hanchao/py-faster-rcnn/experiments/cfgs/faster_rcnn_end2end.yml \
- ${EXTRA_ARGS}
(2)更改py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_end2end目录中的train,test和solver文件(我采用的是VGG16网络,如果使用ZF网络,去修改对应目录下文件即可)。把train和test中所有的21和84改成你的分类类型数+1和(你的分类类型数+1)×4即可。在solver文件中加入绝对路径;
- self._classes = ('__background__', # always index 0
- '你的标签1', '你的标签2', '你的标签3')
注意这里的标签不要有大写符号。
- def append_flipped_images(self):
- # num_images = self.num_images
- # widths = self._get_widths()
- # 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
- # boxes[:, 2] = widths[i] - oldx1 - 1
- # 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
- self._image_index = self._image_index
如果你的数据比较多的话同样也可以去掉这个函数,该函数也可能会引发一些问题,具体更改和解决方法参见Faster-RCNN+ZF用自己的数据集训练模型(Python版本)——小咸鱼_的博客
- faster_rcnn_end2end.sh 0 VGG16 pascal_voc
其中0表示你训练时使用的gpu标号,VGG16是模型类型,具体的内容可以去读faster_rcnn_end2end.sh的源码。
附录
[深度学习] RCNNs系列(1) Ubuntu下Faster RCNN配置及训练和测试自己的数据方法相关推荐
- OCR:深度学习-目标检测-超详细图解Faster R-CNN
版权声明:本文为博主原创文章,转载请标明原始博文地址: https://blog.csdn.net/yuanlulu/article/details/86769589 本文动机 说实话,介绍Faste ...
- Windows下Faster R-CNN 配置/Matlab版本编译
配置环境: Windows10x64 Matlab2015Ra VS2013 Opencv2.4.11 CUDA7.5 GTX950M CUDA7.5安装 因为Cuda7.5做了很大的优化改进,而且对 ...
- 深度学习(六十四)Faster R-CNN物体检测
- Keras搭建深度学习模型,指定使用GPU来进行模型的训练和测试
https://blog.csdn.net/Together_CZ/article/details/79886982?utm_medium=distribute.pc_aggpage_search_r ...
- 深度学习入门系列21:项目:用LSTM+CNN对电影评论分类
大家好,我技术人Howzit,这是深度学习入门系列第二十一篇,欢迎大家一起交流! 深度学习入门系列1:多层感知器概述 深度学习入门系列2:用TensorFlow构建你的第一个神经网络 深度学习入门系列 ...
- 深度学习入门系列1:多层感知器概述
本人正在学习<deep learning with python>–Jason Brownlee,有兴趣的可以一起学习. 仅供学习参考,不做商用! 大家好,我技术人Howzit,这是深度学 ...
- 深度学习入门系列23:项目:用爱丽丝梦游仙境生成文本
大家好,我技术人Howzit,这是深度学习入门系列第二十三篇,欢迎大家一起交流! 深度学习入门系列1:多层感知器概述 深度学习入门系列2:用TensorFlow构建你的第一个神经网络 深度学习入门系列 ...
- 深度学习入门系列6项目实战:声纳回声识别
大家好,我技术人Howzit,这是深度学习入门系列第六篇,欢迎大家一起交流! 深度学习入门系列1:多层感知器概述 深度学习入门系列2:用TensorFlow构建你的第一个神经网络 深度学习入门系列3: ...
- 深度学习模型轻量化(下)
深度学习模型轻量化(下) 2.4 蒸馏 2.4.1 蒸馏流程 蒸馏本质是student对teacher的拟合,从teacher中汲取养分,学到知识,不仅仅可以用到模型压缩和加速中.蒸馏常见流程如下图所 ...
最新文章
- Spring Boot + Vue 如此强大?竟然可以开发基于 C/S 架构的应用
- 引子 我想大家应该都很熟悉DNS了,这回在DNS前面加了一个D又变成了什么呢?这个D就是Dynamic(动态),也就是说,按照传统,一个域名所对应的IP地址应该是定死的,而使用了DDNS后,域名所对应
- Sql Server 2005 服务器性能监视[转]
- cpout引脚是干什么的_电源IC欠压保护(Brown-out)功能介绍
- VC中Error spawning cl.exe错误的解决方法.
- 内网穿透工具 FRP Linux 环境搭建安装
- 【Spark调优】内存模型与参数调优
- 高通driver模块编译方法
- JavaScript原型、函数伪装(apply,call)、继承
- LCL三相pwm整流器(逆变器)
- Word——论文排版技巧总结
- 简述FAT32、exFAT、NTFS的区别
- Python自动化办公练习——合并工作簿
- 计算机积木游戏,A*算法分析(积木块游戏)
- java软件官网下载汇总——JDK,eclipse,mysql,maven,idea,Git,oracle
- IT 如何把骨干留住
- K8S部署DevOps
- 华为OD机试 - 最短耗时(C++) | 附带编码思路 【2023】
- 关于王小云破解MD5之我见
- 【入门数据分析】淘宝用户行为分析
热门文章
- boost::range_mutable_iterator相关的测试程序
- Boost.MultiIndex 使用 Boost.Interprocess 分配器的示例
- boost::overloaded_function用法的测试程序
- boost::bad_function_call用法的测试程序
- boost::fibers::launch::dispatch的测试程序
- GDCM:解析XPATH文件的测试程序
- GDCM:检测SIEMENS JPEG无损压缩图像的测试程序
- VTK:可视化之AlphaFrequency
- VTK:Filtering之ConnectivityFilter
- OpenGL 距离场美化实例