如何将Caltech行人数据集转换为YOLO所需的格式?

Be the one to change the world! github: https://github.com/JacobKong
深度学习实践经验:用Faster R-CNN训练Caltech数据集——修改读写接口
这部分主要讲如何修改Faster R-CNN的代码,来训练自己的数据集,首先确保你已经编译安装了py-faster-rcnn,并且准备好了数据集,具体可参考我。
py-faster-rcnn文件结构
caffe-fast-rcnn
这里是caffe框架目录,用来进行caffe编译安装
用来存放pre trained模型,比如ImageNet上的,要训练的数据集以及读取文件的cache缓存。
experiments
存放配置文件,运行的log文件,另外这个目录下有scripts 用来获取imagenet的模型,以及作者训练好的fast rcnn模型,以及相应的pascal-voc数据集
用来存放一些python接口文件,如其下的datasets主要负责数据库读取,config负责cnn一些训练的配置选项
放置matlab与python的接口,用matlab来调用实现detection
里面存放了三个模型文件,小型网络的ZF,大型网络VGG16,中型网络VGG_CNN_M_1024
这里存放的是训练完成后的输出目录,默认会在default文件夹下
里面存放的是训练和测试的Python文件
修改训练代码
所要操作文件结构介绍
所有需要修改的训练代码都放到了py-faster-rcnn/lib文件夹下,我们进入文件夹,里面主要用到的文件夹有:
datasets:该目录下主要存放读写数据接口。
fast-rcnn:该目录下主要存放的是python的训练和测试脚本,以及训练的配置文件。
roi_data_layer:该目录下主要存放一些ROI处理操作文件。
utils:该目录下主要存放一些通用操作比如非极大值nms,以及计算bounding box的重叠率等常用功能。
读写数据接口都放在datasets/文件夹下,我们进入文件夹,里面主要文件有:
factory.py:这是个工厂类,用类生成imdb类并且返回数据库共网络训练和测试使用。
imdb.py:这是数据库读写类的基类,分装了许多db的操作,但是具体的一些文件读写需要继承继续读写
pascal_voc.py:这是imdb的子类,里面定义许多函数用来进行所有的数据读写操作。
从上面可以看出,我们主要对pascal_voc.py文件进行修改。
pascal_voc.py文件代码分析
我们主要是基于pasca_voc.py这个文件进行修改,里面有几个重要的函数需要介绍:
def __init__(self, image_set, devkit_path=None):
def image_path_at(self, i):
def image_path_from_index(self, index):
def _load_image_set_index(self):
def _get_default_path(self):
def gt_roidb(self):
def rpn_roidb(self):
def _load_rpn_roidb(self, gt_roidb):
def _load_pascal_annotation(self, index):
def _write_voc_results_file(self, all_boxes):
def _do_python_eval(self, output_dir = 'output'):
修改pascal_voc.py文件
要想对自己的数据集进行读取,我们主要是进行pascal_voc.py文件的修改,但是为了不破坏源文件,我们可以将pascal_voc.py进行拷贝复制,从而进行修改。这里我将pascal_voc.py文件拷贝成caltech.py文件:
cp pascal_voc.py caltech.py
下面我们对caltech.py文件进行修改,在这里我会一一列举每个我修改过的函数。这里按照文件中的顺序排列。。
init函数修改
这里是原始的pascal_voc的init函数,在这里,由于我们自己的数据集往往比voc的数据集要更简单的一些,在作者额代码里面用了很多的路径拼接,我们不用去迎合他的格式,将这些操作简单化即可。
原始的函数
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__',
'aeroplane', 'bicycle', 'bird', 'boat',
'bottle', 'bus', 'car', 'cat', 'chair',
'cow', 'diningtable', 'dog', 'horse',
'motorbike', 'person', 'pottedplant',
'sheep', 'sofa', 'train', 'tvmonitor')
self._class_to_ind = dict(zip(self.classes, xrange(self.num_classes)))
self._image_ext = '.jpg'
self._image_index = self._load_image_set_index()
self._roidb_handler = self.selective_search_roidb
self._salt = str(uuid.uuid4())
self._comp_id = 'comp4'
self.config = {'cleanup'
'use_salt'
'use_diff'
'matlab_eval' : False,
'rpn_file'
'min_size'
assert os.path.exists(self._devkit_path), \
'VOCdevkit path does not exist: {}'.format(self._devkit_path)
assert os.path.exists(self._data_path), \
'Path does not exist: {}'.format(self._data_path)
修改后的函数
def __init__(self, image_set, devkit_path=None):
imdb.__init__(self, image_set)
self._image_set = image_set
self._devkit_path = devkit_path
self._data_path = os.path.join(self._devkit_path, 'Caltech')
self._classes = ('__background__',
self._class_to_ind = dict(zip(self.classes, xrange(self.num_classes)))
self._image_ext = '.jpg'
self._image_index = self._load_image_set_index()
self._roidb_handler = self.selective_search_roidb
self._salt = str(uuid.uuid4())
self._comp_id = 'comp4'
self.config = {'cleanup'
'use_salt'
'use_diff'
'matlab_eval' : False,
'rpn_file'
'min_size'
assert os.path.exists(self._devkit_path), \
'VOCdevkit path does not exist: {}'.format(self._devkit_path)
assert os.path.exists(self._data_path), \
'Path does not exist: {}'.format(self._data_path)
_load_image_set_index函数修改
原始的函数
def _load_image_set_index(self):
Load the indexes listed in this dataset's image set file.
image_set_file = os.path.join(self._data_path, 'ImageSets', 'Main',
self._image_set + '.txt')
assert os.path.exists(image_set_file), \
'Path does not exist: {}'.format(image_set_file)
with open(image_set_file) as f:
image_index = [x.strip() for x in f.readlines()]
return image_index
修改后的函数
def _load_image_set_index(self):
Load the indexes listed in this dataset's image set file.
image_set_file = os.path.join(self._data_path, 'ImageSets', 'Main',
self._image_set + '.txt')
assert os.path.exists(image_set_file), \
'Path does not exist: {}'.format(image_set_file)
with open(image_set_file) as f:
image_index = [x.strip() for x in f.readlines()]
return image_index
其实没改,只是加了一行注释,从而更好理解路径问题。
_get_default_path函数修改
直接注释即可
_load_pascal_annotation函数修改
原始的函数
def _load_pascal_annotation(self, index):
Load image and bounding boxes info from XML file in the PASCAL VOC
filename = os.path.join(self._data_path, 'Annotations', index + '.xml')
tree = ET.parse(filename)
objs = tree.findall('object')
if not self.config['use_diff']:
non_diff_objs = [
obj for obj in objs if int(obj.find('difficult').text) == 0]
objs = non_diff_objs
num_objs = len(objs)
boxes = np.zeros((num_objs, 4), dtype=np.uint16)
gt_classes = np.zeros((num_objs), dtype=np.int32)
overlaps = np.zeros((num_objs, self.num_classes), dtype=np.float32)
seg_areas = np.zeros((num_objs), dtype=np.float32)
for ix, obj in enumerate(objs):
bbox = obj.find('bndbox')
x1 = float(bbox.find('xmin').text) - 1
y1 = float(bbox.find('ymin').text) - 1
x2 = float(bbox.find('xmax').text) - 1
y2 = float(bbox.find('ymax').text) - 1
cls = self._class_to_ind[obj.find('name').text.lower().strip()]
boxes[ix, :] = [x1, y1, x2, y2]
gt_classes[ix] = cls
overlaps[ix, cls] = 1.0
seg_areas[ix] = (x2 - x1 + 1) * (y2 - y1 + 1)
overlaps = scipy.sparse.csr_matrix(overlaps)
return {'boxes' : boxes,
'gt_classes': gt_classes,
'gt_overlaps' : overlaps,
'flipped' : False,
'seg_areas' : seg_areas}
修改后的函数
def _load_pascal_annotation(self, index):
Load image and bounding boxes info from XML file in the PASCAL VOC
filename = os.path.join(self._data_path, 'Annotations', index + '.xml')
tree = ET.parse(filename)
objs = tree.findall('object')
if not self.config['use_diff']:
non_diff_objs = [
obj for obj in objs if int(obj.find('difficult').text) == 0]
objs = non_diff_objs
num_objs = len(objs)
boxes = np.zeros((num_objs, 4), dtype=np.uint16)
gt_classes = np.zeros((num_objs), dtype=np.int32)
overlaps = np.zeros((num_objs, self.num_classes), dtype=np.float32)
seg_areas = np.zeros((num_objs), dtype=np.float32)
for ix, obj in enumerate(objs):
bbox = obj.find('bndbox')
x1 = float(bbox.find('xmin').text)
y1 = float(bbox.find('ymin').text)
x2 = float(bbox.find('xmax').text)
y2 = float(bbox.find('ymax').text)
cls = self._class_to_ind[obj.find('name').text.lower().strip()]
boxes[ix, :] = [x1, y1, x2, y2]
gt_classes[ix] = cls
overlaps[ix, cls] = 1.0
seg_areas[ix] = (x2 - x1 + 1) * (y2 - y1 + 1)
overlaps = scipy.sparse.csr_matrix(overlaps)
return {'boxes' : boxes,
'gt_classes': gt_classes,
'gt_overlaps' : overlaps,
'flipped' : False,
'seg_areas' : seg_areas}
main函数修改
原始的函数
if __name__ == '__main__':
from datasets.pascal_voc import pascal_voc
d = pascal_voc('trainval', '2007')
res = d.roidb
from IPython import embed()
修改后的函数
if __name__ == '__main__':
from datasets.caltech import caltech
d = caltech('train', '/home/jk/py-faster-rcnn/data/VOCdevkit')
res = d.roidb
from IPython import embed()
至此读取接口修改完毕,该文件中的其他函数并未修改。
修改factory.py文件
当网络训练时会调用factory里面的get方法获得相应的imdb,首先在文件头import 把pascal_voc改成caltech
在这个文件作者生成了多个数据库的路径,我们自己数据库只要给定根路径即可,修改主要有以下4个
函数之后有两个多级的for循环,也将其注释
直接定义devkit。
利用创建自己的训练和测试的imdb set,这里的name的格式为caltech_{}。
原始的代码
"""Factory method for easily getting imdbs by name."""
__sets = {}
from datasets.pascal_voc import pascal_voc
from datasets.coco import coco
import numpy as np
for year in ['2007', '2012']:
for split in ['train', 'val', 'trainval', 'test']:
name = 'voc_{}_{}'.format(year, split)
__sets[name] = (lambda split=split, year=year: pascal_voc(split, year))
for year in ['2014']:
for split in ['train', 'val', 'minival', 'valminusminival']:
name = 'coco_{}_{}'.format(year, split)
__sets[name] = (lambda split=split, year=year: coco(split, year))
for year in ['2015']:
for split in ['test', 'test-dev']:
name = 'coco_{}_{}'.format(year, split)
__sets[name] = (lambda split=split, year=year: coco(split, year))
def get_imdb(name):
"""Get an imdb (image database) by name."""
if not __sets.has_key(name):
raise KeyError('Unknown dataset: {}'.format(name))
return __sets[name]()
def list_imdbs():
"""List all registered imdbs."""
return __sets.keys()
修改后的文件
"""Factory method for easily getting imdbs by name."""
__sets = {}
from datasets.caltech import caltech
devkit = '/home/jk/py-faster-rcnn/data/VOCdevkit'
for split in ['train', 'test']:
name = 'caltech_{}'.format(split)
__sets[name] = (lambda imageset=split, devkit=devkit: caltech(imageset, devkit))
def get_imdb(name):
"""Get an imdb (image database) by name."""
if not __sets.has_key(name):
raise KeyError('Unknown dataset: {}'.format(name))
return __sets[name]()
def list_imdbs():
"""List all registered imdbs."""
return __sets.keys()
修改init.py文件
在行首添加上 from .caltech import caltech
坐标的顺序我再说一次,要左上右下,并且x1必须要小于x2,这个是基本,反了会在坐标水平变换的时候会出错,坐标从0开始,如果已经是0,则不需要再-1。
训练图像的大小不要太大,否则生成的OP也会太多,速度太慢,图像样本大小最好调整到500,600左右,然后再提取OP
如果读取并生成pkl文件之后,实际数据内容或者顺序还有问题,记得要把data/cache/下面的pkl文件给删掉。
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!半路出家,多多关照
训练YOLO模型
摘自https://github.com/AlexeyAB/darknet如何训练自己的数据模型1、创建自己的yolo-obj.cfg文件:在同一目录下,复制yolo-voc.2.cfg的内容到yolo-obj.cfg。更改如下内容:
batch = 64
subdivision = 8
,如果在训练过程中出现out of memory错误,将subdivision设置为更高,比如16\32
【region】下的classes = 类型的数量,根据实际需求
【region】的前一个filters = (classes+5)×52、在darknet/data目录下创建obj.names文件,文件每一行为每个类的类名称。3、在darknet/data目录下创建obj.data文件,内容为:classes= 类的数量
= data/train.txt
= data/test.txt
names = data/obj.names
backup = backup/其中,train.txt、valid.txt内的每一行,分别为训练集、验证集的每一张图片的路径+图片名,比如/home/ruwei/yolo_releated_data/库位data/yolo_data/train/TR.jpg4、新建文件夹存放训练集数据,放入图片的同时,为每个图片创建同名的.txt文件,内容为&class& &x& &y& &width& &height&class:该物体属于哪一类,数字形式,从0开始。剩下4个均为归一化的数值,从0.0-1.0x= absolute_x/image_width.
height = absolute_height/image_height0 0....1583335、下载pre_trained weights文件,放入darknet/下6、输入命令,开始训练。训练到何时停止1、随着训练的进行,avg(平均误差)不再降低。avg越小越好。2、选择最合适的weights文件。
训练会产生多个weights文件,为了防止overfitting(过拟合),要选取其中最合适的一个。
过拟合:对训练集的效果很好,对之外的输入预测结果很差。
为达到效果,需要做的有:
2-1、训练时要设置验证集(validation set),如果没有数据,就用练集代替。
2-2、对每一个weights文件进行对比
darknet.exe detector map data/obj.data yolo-obj.cfg backup\yolo-oby_7000.weights
darknet.exe detector map data/obj.data yolo-obj.cfg backup\yolo-oby_8000.weights
darknet.exe detector map data/obj.data yolo-obj.cfg backup\yolo-oby_9000.weights
比较最后一行的输出,选择IoU(intersect of union)和mAP(mean average precision)最大的那个。
如何提高目标检测效果训练前:1、设置配置文件(.cfg)中的 random =1(是否随机确定最后一个预测框),可以提高训练精度。2、提高配置文件中network resolution(分辨率),height = 608,width = 608或者任意32的倍数。3、确保数据集中每个类都带有标签。4、重新计算数据集中宽、高的anchors。5、保证训练数据足够多,每个类至少有200张图片。确保图片有多种角度、亮度、背景、比例等。6、确保训练数据中含有不带标签的不想被检测到的物体图片,即负样本。7、如果每张图片中检测的物体数量较多,设置.cfg文件中最后一层【region】中的参数max=200或更大。8、检测小物体时,设置【route】下layers =-1,11,【upsample】下stride =4。9、为了加速训练,做微调,而不是迁移学习。设置stopbackward=1。训练后:Increase network-resolution by set in your .cfg-file (height=608 and width=608) or (height=832 and width=832) or (any value multiple of 32) - this increases the precision and makes it possible to detect small objects: you do not need to train the network again, just use .weights-file already trained for 416x416 resolutionif error Out of memory occurs then in .cfg-file you should increase subdivisions=16, 32 or 64
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!Be the one to change the world! github: https://github.com/JacobKong
深度学习实践经验:用Faster R-CNN训练Caltech数据集——训练检测
前面已经介绍了如何准备数据集,以及如何修改数据集读写接口来操作数据集,接下来我来说明一下怎么来训练网络和之后的检测过程。
修改模型文件
faster rcnn有两种各种训练方式:
Alternative training(alt-opt)
Approximate joint training(end-to-end)
两种方法有什么不同,可以参考我,推荐使用第二种,因为第二种使用的显存更小,而且训练会更快,同时准确率差不多,两种方式需要修改的代码是不一样的,同时faster rcnn提供了三种训练模型,小型的ZF model,中型的VGG_CNN_M_1024和大型的VGG16,论文中说VGG16效果比其他两个好,但是同时占用更大的GPU显存(~11GB)
我使用的是VGG model + alternative training,需要检测的类别只有一类,加上背景所以总共是两类(background + person)。
下面修改模型文件:
py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt/stage1_fast_rcnn_train.pt
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
name: "cls_score"
type: "InnerProduct"
bottom: "fc7"
top: "cls_score"
lr_mult: 1.0
lr_mult: 2.0
num_output: 2 #按训练集类别改,该值为类别数+1
weight_filler {
type: "gaussian"
type: "constant"
name: "bbox_pred"
type: "InnerProduct"
bottom: "fc7"
top: "bbox_pred"
lr_mult: 1.0
lr_mult: 2.0
num_output: 8 #按训练集类别改,该值为(类别数+1)*4,四个顶点坐标
weight_filler {
type: "gaussian"
std: 0.001
type: "constant"
py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt/stage1_rpn_train.pt
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
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
name: "cls_score"
type: "InnerProduct"
bottom: "fc7"
top: "cls_score"
lr_mult: 1.0
lr_mult: 2.0
num_output: 2 #按训练集类别改,该值为类别数+1
weight_filler {
type: "gaussian"
type: "constant"
name: "bbox_pred"
type: "InnerProduct"
bottom: "fc7"
top: "bbox_pred"
lr_mult: 1.0
lr_mult: 2.0
num_output: 8 #按训练集类别改,该值为(类别数+1)*4,四个顶点坐标
weight_filler {
type: "gaussian"
std: 0.001
type: "constant"
py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt/stage2_rpn_train.pt
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
name: "cls_score"
type: "InnerProduct"
bottom: "fc7"
top: "cls_score"
inner_product_param {
num_output: 2 #按训练集类别改,该值为类别数+1
name: "bbox_pred"
type: "InnerProduct"
bottom: "fc7"
top: "bbox_pred"
inner_product_param {
num_output: 84 #按训练集类别改,该值为(类别数+1)*4,四个顶点坐标
训练前还需要注意几个地方:
cache问题:
假如你之前训练了官方的VOC2007的数据集或其他的数据集,是会产生cache的问题的,建议在重新训练新的数据之前将其删除。
py-faster-rcnn/output
py-faster-rcnn/data/cache
参数放在如下文件:
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中进行修改:
max_iters = [8, 8]
分别对应rpn第1阶段,fast rcnn第1阶段,rpn第2阶段,fast rcnn第2阶段的迭代次数,自己修改即可,不过注意这里的值不要小于上面的solver里面的step_size的大小,大家自己修改吧
首先修改experiments/scripts/faster_rcnn_alt_opt.sh成如下,修改地方已标注:
#!/bin/bash
export PYTHONUNBUFFERED="True"
NET_lc=${NET,,}
DATASET=$3
array=( $@ )
len=${#array[@]}
EXTRA_ARGS=${array[@]:3:$len}
EXTRA_ARGS_SLUG=${EXTRA_ARGS// /_}
case $DATASET in
TRAIN_IMDB="caltech_train"
TEST_IMDB="caltech_test"
PT_DIR="caltech"
ITERS=40000
echo "Not implemented: use experiments/scripts/faster_rcnn_end2end.sh for coco"
echo "No dataset given"
LOG="experiments/logs/faster_rcnn_alt_opt_${NET}_${EXTRA_ARGS_SLUG}.txt.`date +'%Y-%m-%d_%H-%M-%S'`"
exec && &(tee -a "$LOG")
echo Logging output to "$LOG"
time ./tools/train_faster_rcnn_alt_opt.py --gpu ${GPU_ID} \
--net_name ${NET} \
--weights data/imagenet_models/${NET}.v2.caffemodel \
--imdb ${TRAIN_IMDB} \
--cfg experiments/cfgs/faster_rcnn_alt_opt.yml \
${EXTRA_ARGS}
NET_FINAL=`grep "Final model:" ${LOG} | awk '{print $3}'`
time ./tools/test_net.py --gpu ${GPU_ID} \
--def models/${PT_DIR}/${NET}/faster_rcnn_alt_opt/faster_rcnn_test.pt \
--net ${NET_FINAL} \
--imdb ${TEST_IMDB} \
--cfg experiments/cfgs/faster_rcnn_alt_opt.yml \
${EXTRA_ARGS}
调用如下命令进行训练及测试,从上面代码可以看出,该shell文件在训练完后会接着进行测试,但是我的测试集没有标注,所以测试的时候会报错,但是由于Caltech数据集的测试结果有专门的评估代码,所以我不用faster r-cnn提供的代码进行测试,而是直接进行检测生成坐标,用专门的评估代码进行检测。
cd py-faster-rcnn
./experiments/scripts/faster_rcnn_alt_opt.sh 0 VGG16 caltech
参数1:指定gpu_id。
参数2:指定网络模型参数。
参数3:数据集名称,目前只能为pascal_voc。
在训练过程中,会调用py_faster_rcnn/tools/train_faster_rcnn_alt_opt.py文件开始训练网络。
可能会出现的Bugs
AssertionError: assert (boxes[:, 2] &= boxes[:, 0]).all()
在训练过程中可能会出现如下报错:
File "/py-faster-rcnn/tools/../lib/datasets/imdb.py", line 108, in
append_flipped_images
assert (boxes[:, 2] &= boxes[:, 0]).all()
AssertionError
检查自己数据发现,左上角坐标 (x, y) 可能为0,或标定区域溢出图片(即坐标为负数),而faster rcnn会对Xmin,Ymin,Xmax,Ymax进行减一操作,如果Xmin为0,减一后变为65535,从而在左右翻转图片时导致如上错误发生。
修改lib/datasets/imdb.py中的append_flipped_images()函数:
数据整理,在一行代码为 boxes[:, 2] = widths[i] - oldx1 - 1下加入代码:
for b in range(len(boxes)):
if boxes[b][2]& boxes[b][0]:
boxes[b][0] = 0
修改lib/datasets/caltech.py,_load_pascal_annotation()函数,将对Xmin,Ymin,Xmax,Ymax减一去掉,变为:
for ix, obj in enumerate(objs):
bbox = obj.find('bndbox')
x1 = float(bbox.find('xmin').text)
y1 = float(bbox.find('ymin').text)
x2 = float(bbox.find('xmax').text)
y2 = float(bbox.find('ymax').text)
cls = self._class_to_ind[obj.find('name').text.lower().strip()]
boxes[ix, :] = [x1, y1, x2, y2]
gt_classes[ix] = cls
overlaps[ix, cls] = 1.0
seg_areas[ix] = (x2 - x1 + 1) * (y2 - y1 + 1)
(可选)如果1和2可以解决问题,就没必要用方法3。修改lib/fast_rcnn/config.py,不使图片实现翻转,如下改为:
# Use horizontally-flipped images during training?
__C.TRAIN.USE_FLIPPED = False
如果如上三种方法都无法解决该问题,那么肯定是你的数据集坐标出现小于等于0的数,你应该一一排查。
训练fast rcnn时出现loss=nan的情况。
这是由于模型不收敛,导致loss迅速增长。
而我出现以上现象的原因主要是因为我在出现AssertionError的时候直接使用了第三种方法导致的。也就是禁用图片翻转。
启用图片翻转。
训练后的模型放在output/faster_rcnn_alt_opt/train/VGG16_faster_rcnn_final.caffemodel,该模型可以用于之后的检测。
经过以上训练后,就可以用得到的模型来进行检测了。检测所参考的代码是tools/demo.py,具体步骤如下:
将output/faster_rcnn_alt_opt/train/VGG16_faster_rcnn_final.caffemodel,拷贝到data/faster_rcnn_models下,命名为VGG16_Caltech_faster_rcnn__final.caffemodel
进入tools/文件夹中,拷贝demo.py为demo_caltech.py。
修改demo_caltech.py代码如下:
import matplotlib
matplotlib.use('Agg');
Demo script showing detections in sample images.
See README.md for installation instructions before running.
import _init_paths
from fast_rcnn.config import cfg
from fast_rcnn.test import im_detect
from fast_rcnn.nms_wrapper import nms
from utils.timer import Timer
import matplotlib.pyplot as plt
import numpy as np
import scipy.io as sio
import caffe, os, sys, cv2
import argparse
CLASSES = ('__background__',
NETS = {'vgg16': ('VGG16',
'VGG16_Caltech_faster_rcnn_final.caffemodel'),
'zf': ('ZF',
'ZF_Caltech_faster_rcnn_final.caffemodel')}
def vis_detections(im, image_name, class_name, dets, thresh=0.5):
"""Draw detected bounding boxes."""
inds = np.where(dets[:, -1] &= thresh)[0]
if len(inds) == 0:
im = im[:, :, (2, 1, 0)]
fig, ax = plt.subplots(figsize=(12, 12))
ax.imshow(im, aspect='equal')
for i in inds:
bbox = dets[i, :4]
score = dets[i, -1]
ax.add_patch(
plt.Rectangle((bbox[0], bbox[1]),
bbox[2] - bbox[0],
bbox[3] - bbox[1], fill=False,
edgecolor='red', linewidth=3.5)
ax.text(bbox[0], bbox[1] - 2,
'{:s} {:.3f}'.format(class_name, score),
bbox=dict(facecolor='blue', alpha=0.5),
fontsize=14, color='white')
ax.set_title(('{} detections with '
'p({} | box) &= {:.1f}').format(class_name, class_name,
fontsize=14)
plt.axis('off')
plt.tight_layout()
plt.draw()
plt.savefig('/home/jk/py-faster-rcnn/output/faster_rcnn_alt_opt/test/'+image_name)
def demo(net, image_name):
"""Detect object classes in an image using pre-computed object proposals."""
im_file = os.path.join(cfg.DATA_DIR, 'VOCdevkit/Caltech/JPEGImages', image_name)
im = cv2.imread(im_file)
timer = Timer()
timer.tic()
scores, boxes = im_detect(net, im)
timer.toc()
print ('Detection took {:.3f}s for '
'{:d} object proposals').format(timer.total_time, boxes.shape[0])
CONF_THRESH = 0.85
NMS_THRESH = 0.3
for cls_ind, cls in enumerate(CLASSES[1:]):
cls_ind += 1
cls_boxes = boxes[:, 4*cls_ind:4*(cls_ind + 1)]
cls_scores = scores[:, cls_ind]
dets = np.hstack((cls_boxes,
cls_scores[:, np.newaxis])).astype(np.float32)
keep = nms(dets, NMS_THRESH)
dets = dets[keep, :]
vis_detections(im, image_name, cls, dets, thresh=CONF_THRESH)
def parse_args():
"""Parse input arguments."""
parser = argparse.ArgumentParser(description='Faster R-CNN demo')
parser.add_argument('--gpu', dest='gpu_id', help='GPU device id to use [0]',
default=0, type=int)
parser.add_argument('--cpu', dest='cpu_mode',
help='Use CPU mode (overrides --gpu)',
action='store_true')
parser.add_argument('--net', dest='demo_net', help='Network to use [vgg16]',
choices=NETS.keys(), default='vgg16')
args = parser.parse_args()
return args
if __name__ == '__main__':
cfg.TEST.HAS_RPN = True
args = parse_args()
prototxt = os.path.join(cfg.MODELS_DIR, NETS[args.demo_net][0],
'faster_rcnn_alt_opt', 'faster_rcnn_test.pt')
caffemodel = os.path.join(cfg.DATA_DIR, 'faster_rcnn_models',
NETS[args.demo_net][1])
if not os.path.isfile(caffemodel):
raise IOError(('{:s} not found.\nDid you run ./data/script/'
'fetch_faster_rcnn_models.sh?').format(caffemodel))
if args.cpu_mode:
caffe.set_mode_cpu()
caffe.set_mode_gpu()
caffe.set_device(args.gpu_id)
cfg.GPU_ID = args.gpu_id
net = caffe.Net(prototxt, caffemodel, caffe.TEST)
print '\n\nLoaded network {:s}'.format(caffemodel)
im = 128 * np.ones((300, 500, 3), dtype=np.uint8)
for i in xrange(2):
_, _= im_detect(net, im)
testfile_path = '/home/jk/py-faster-rcnn/data/VOCdevkit/Caltech/ImageSets/Main/test.txt'
with open(testfile_path) as f:
im_names = [x.strip()+'.jpg' for x in f.readlines()]
for im_name in im_names:
print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
print 'Demo for data/demo/{}'.format(im_name)
demo(net, im_name)
plt.show()
在命令行中输入一下命令进行检测:
python tools/demo_caltech.py
放几张检测后的结果图,感觉检测效果并不是很好,很多把背景当成行人的错误:
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!}

我要回帖

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信