Faster-RCNN+ZF用自己的数据集训练模型(Python版本)

来源:互联网 发布:java数据类型和运算符 编辑:程序博客网 时间:2024/06/05 17:37

一,做自己的数据集


0.文件夹名


可以使用Total Commander来批量重命名文件夹的名字,非常方便,推荐使用这个工具。
下载地址:Total Commander破解版

已经下载在D:\candy\Faster-RCNN+ZF用自己的数据集训练模型(Python版本)\Total_Commander
也可以到百度,云盘链接:https://pan.baidu.com/s/1o7FIjrG 密码:hh8h 和移动硬盘小7里面找

先用Total_Commander工具将文件夹名修改,数字前要有0,不然matlab读取顺序会发生变化,后续重命名图像的时候类标签不会发生变化,与数据库中的数据会对应起来

类外面的文件夹命名不重要,例如我的叫153(或者和voc2007一样的名字:VOC2007),其他的都可以


1.图片命名

虽然说图片名对训练没什么影响,但建议还是按VOC2007那样,如“000005.jpg”这种形式。至于图片格式,png和jpg都行,当时在训练或者测试的时候一定要注意改相应的代码。原始代码里是写的jpg。
批量修改图片名字为VOC2007格式可以参考以下Matlab代码:
[plain] view plain copy
  1. %%  
  2. %图片保存路径为:  
  3. %E:\image\car  和  E:\image\person 。。。  
  4. %car和person是保存不同类的文件夹,这样的文件还可有多个,只要读到\image这一级目录就好了  
  5. %该代码的作用是将图片名字改成000123.jpg这种形式  
  6. %%  
  7. clc;  
  8. clear;  
  9.   
  10. maindir='E:\image\';  
  11. save_path='E:\image\result\'
  12. name_long=6; %图片名字的长度,如000123.jpg为6,最多9位,可修改  
  13. num_begin=1; %图像命名开始的数字如000123.jpg开始的话就是123  
  14.   
  15. subdir = dir(maindir);  %读取maindir下面所有的子文件和所有的文件
  16. n=1;  
  17.   
  18. for i = 1:length(subdir)  
  19.   if ~strcmp(subdir(i).name ,'.') && ~strcmp(subdir(i).name,'..')  
  20.      subsubdir = dir(strcat(maindir,subdir(i).name));  
  21.     for j=1:length(subsubdir)  
  22.          if ~strcmp(subsubdir(j).name ,'.') && ~strcmp(subsubdir(j).name,'..')  
  23.             img=imread([maindir,subdir(i).name,'\',subsubdir(j).name]);  
  24.             imshow(img);  
  25.             str=num2str(num_begin,'%09d');  
  26.             newname=strcat(str,'.jpg');  
  27.             newname=newname(end-(name_long+3):end);  
  28.             %imwrite(img,strcat(save_path,newname));%改名后保存到另一文件夹,原图片不变
  29.             system(['rename ' [maindir,subdir(i).name,'\',subsubdir(j).name] ' ' newname]);  
  30.             num_begin=num_begin+1;  
  31.             fprintf('当前处理文件夹%s',subdir(i).name);  
  32.             fprintf('已经处理%d张图片\n',n);  
  33.             n=n+1;  
  34.            %pause(0.1);%可以将暂停去掉  
  35.          end  
  36.     end  
  37.   end  
  38. end  
图片名如果比较特殊或者像1(1).jpg等这类可能无法重命名,可以使用imwrite,如:
上面的程序已经改为imwrite(img,strcat(save_path,newname));可以另存为,不会破坏原数据集

[html] view plain copy
  1. imwrite(img,strcat(save_path,newname));%改名后保存到另一文件夹,原图片不变  
system(['rename ' [maindir,subdir(i).name,'\',subsubdir(j).name] ' ' newname]);可修改不同文件夹下面的图像,可重命名在不同的文件夹下,这样方便打标签。

imwrite(img,strcat(save_path,newname));%改名后保存到另一文件夹,原图片不变,可将不同类的图像依顺序保存在另一文件夹中,这样方便训练



2.自己的数据BoundingBox

(1)生成/Annotations下的xml文件:参照我的另一篇博客BoundingBox工具及其使用方法
(2)生成\imageset\Main\中的的文件,代码如下:
   
    %%      %该代码根据已生成的xml文件,制作/VOC2007/imageset/Main/数据集中的trainval.txt;train.txt;test.txt和val.txt      %trainval占总数据集的50%,test占总数据集的50%;train占trainval的50%,val占trainval的50%;      %上面所占百分比可根据自己的数据集修改,如果数据集比较少,test和val可少一些      %%      %注意修改下面四个值      xmlfilepath='D:\candy\VOC2007\VOC2007\Annotations';  %xml的源文件夹所在位置    txtsavepath='D:\candy\VOC2007\VOC2007\imageset\Main\';  %trainval.txt;train.txt;test.txt和val.txt的保存位置    trainval_percent=0.8;%trainval占整个数据集的百分比,剩下部分就是test所占百分比      train_percent=0.7;%train占trainval的百分比,剩下部分就是val所占百分比                  %%      xmlfile=dir(xmlfilepath);      numOfxml=length(xmlfile)-2;%减去.和..  总的数据集大小                  trainval=sort(randperm(numOfxml,floor(numOfxml*trainval_percent)));      test=sort(setdiff(1:numOfxml,trainval));                  trainvalsize=length(trainval);%trainval的大小      train=sort(trainval(randperm(trainvalsize,floor(trainvalsize*train_percent))));      val=sort(setdiff(trainval,train));                  ftrainval=fopen([txtsavepath 'trainval.txt'],'wt');      ftest=fopen([txtsavepath 'test.txt'],'wt');      ftrain=fopen([txtsavepath 'train.txt'],'wt');      fval=fopen([txtsavepath 'val.txt'],'wt');                  for i=1:numOfxml          if ismember(i,trainval)              fprintf(ftrainval,'%s\n',xmlfile(i+2).name(1:end-4));              if ismember(i,train)                  fprintf(ftrain,'%s\n',xmlfile(i+2).name(1:end-4));              else                  fprintf(fval,'%s\n',xmlfile(i+2).name(1:end-4));              end          else              fprintf(ftest,'%s\n',xmlfile(i+2).name(1:end-4));          end      end      fclose(ftrainval);      fclose(ftrain);      fclose(fval);      fclose(ftest);  

(3)/VOC2007/JPEGImages/下的JPG图像:
imwrite(img,strcat(save_path,newname));%改名后保存到另一文件夹,原图片不变,可将不同类的图像依顺序保存在另一文件夹中,这样方便训练,就存放在/VOC2007/JPEGImages/ 中,作为训练数据集,跟原先放在不同类中的图像是一致的。

经过以上三部,自己的数据集所需的/Annotations下的xml文件,生成\imageset\Main\中的

trainval.txt;train.txt;test.txt和val.txt文件以及/VOC2007/JPEGImages/下的JPG图像都已经准备完毕


3,训练

(1)修改相应参数

 A.py-faster-rcnn/models/pascal_voc/ZF/faster_rcnn_alt_opt/stage1_fast_rcnn_train.pt修改

[plain] view plain copy
  1. layer {  
  2.   name: 'data'  
  3.   type: 'Python'  
  4.   top: 'data'  
  5.   top: 'rois'  
  6.   top: 'labels'  
  7.   top: 'bbox_targets'  
  8.   top: 'bbox_inside_weights'  
  9.   top: 'bbox_outside_weights'  
  10.   python_param {  
  11.     module: 'roi_data_layer.layer'  
  12.     layer: 'RoIDataLayer'  
  13.     param_str: "'num_classes': 16" #按训练集类别改,该值为类别数+1  
  14.   }  
  15. }  

[plain] view plain copy
  1. layer {  
  2.   name: "cls_score"  
  3.   type: "InnerProduct"  
  4.   bottom: "fc7"  
  5.   top: "cls_score"  
  6.   param { lr_mult: 1.0 }  
  7.   param { lr_mult: 2.0 }  
  8.   inner_product_param {  
  9.     num_output: 16 #按训练集类别改,该值为类别数+1  
  10.     weight_filler {  
  11.       type: "gaussian"  
  12.       std: 0.01  
  13.     }  
  14.     bias_filler {  
  15.       type: "constant"  
  16.       value: 0  
  17.     }  
  18.   }  
  19. }  

[plain] view plain copy
  1. layer {  
  2.   name: "bbox_pred"  
  3.   type: "InnerProduct"  
  4.   bottom: "fc7"  
  5.   top: "bbox_pred"  
  6.   param { lr_mult: 1.0 }  
  7.   param { lr_mult: 2.0 }  
  8.   inner_product_param {  
  9.     num_output: 64 #按训练集类别改,该值为(类别数+1)*4  
  10.     weight_filler {  
  11.       type: "gaussian"  
  12.       std: 0.001  
  13.     }  
  14.     bias_filler {  
  15.       type: "constant"  
  16.       value: 0  
  17.     }  
  18.   }  
  19. }  


B.py-faster-rcnn/models/pascal_voc/ZF/faster_rcnn_alt_opt/stage1_rpn_train.pt修改

[plain] view plain copy
  1. layer {  
  2.   name: 'input-data'  
  3.   type: 'Python'  
  4.   top: 'data'  
  5.   top: 'im_info'  
  6.   top: 'gt_boxes'  
  7.   python_param {  
  8.     module: 'roi_data_layer.layer'  
  9.     layer: 'RoIDataLayer'  
  10.     param_str: "'num_classes': 16" #按训练集类别改,该值为类别数+1  
  11.   }  
  12. }  


C.py-faster-rcnn/models/pascal_voc/ZF/faster_rcnn_alt_opt/stage2_fast_rcnn_train.pt修改

[plain] view plain copy
  1. layer {  
  2.   name: 'data'  
  3.   type: 'Python'  
  4.   top: 'data'  
  5.   top: 'rois'  
  6.   top: 'labels'  
  7.   top: 'bbox_targets'  
  8.   top: 'bbox_inside_weights'  
  9.   top: 'bbox_outside_weights'  
  10.   python_param {  
  11.     module: 'roi_data_layer.layer'  
  12.     layer: 'RoIDataLayer'  
  13.     param_str: "'num_classes': 16" #按训练集类别改,该值为类别数+1  
  14.   }  
  15. }  

[plain] view plain copy
  1. layer {  
  2.   name: "cls_score"  
  3.   type: "InnerProduct"  
  4.   bottom: "fc7"  
  5.   top: "cls_score"  
  6.   param { lr_mult: 1.0 }  
  7.   param { lr_mult: 2.0 }  
  8.   inner_product_param {  
  9.     num_output: 16 #按训练集类别改,该值为类别数+1  
  10.     weight_filler {  
  11.       type: "gaussian"  
  12.       std: 0.01  
  13.     }  
  14.     bias_filler {  
  15.       type: "constant"  
  16.       value: 0  
  17.     }  
  18.   }  
  19. }  

[plain] view plain copy
  1. layer {  
  2.   name: "bbox_pred"  
  3.   type: "InnerProduct"  
  4.   bottom: "fc7"  
  5.   top: "bbox_pred"  
  6.   param { lr_mult: 1.0 }  
  7.   param { lr_mult: 2.0 }  
  8.   inner_product_param {  
  9.     num_output: 64 #按训练集类别改,该值为(类别数+1)*4  
  10.     weight_filler {  
  11.       type: "gaussian"  
  12.       std: 0.001  
  13.     }  
  14.     bias_filler {  
  15.       type: "constant"  
  16.       value: 0  
  17.     }  
  18.   }  
  19. }  

D.py-faster-rcnn/models/pascal_voc/ZF/faster_rcnn_alt_opt/stage2_rpn_train.pt修改

[plain] view plain copy
  1. layer {  
  2.   name: 'input-data'  
  3.   type: 'Python'  
  4.   top: 'data'  
  5.   top: 'im_info'  
  6.   top: 'gt_boxes'  
  7.   python_param {  
  8.     module: 'roi_data_layer.layer'  
  9.     layer: 'RoIDataLayer'  
  10.     param_str: "'num_classes': 16" #按训练集类别改,该值为类别数+1  
  11.   }  
  12. }  


E.py-faster-rcnn/models/pascal_voc/ZF/faster_rcnn_alt_opt/faster_rcnn_test.pt修改

[plain] view plain copy
  1. layer {  
  2.   name: "cls_score"  
  3.   type: "InnerProduct"  
  4.   bottom: "fc7"  
  5.   top: "cls_score"  
  6.   inner_product_param {  
  7.     num_output: 16 #按训练集类别改,该值为类别数+1  
  8.   }  
  9. }  

[plain] view plain copy
  1. layer {  
  2.   name: "bbox_pred"  
  3.   type: "InnerProduct"  
  4.   bottom: "fc7"  
  5.   top: "bbox_pred"  
  6.   inner_product_param {  
  7.     num_output: 64 #按训练集类别改,该值为(类别数+1)*4  
  8.   }  
  9. }  

F.py-faster-rcnn/lib/datasets/pascal_voc.py修改

[plain] view plain copy
  1. class pascal_voc(imdb):  
  2.     def __init__(self, image_set, year, devkit_path=None):  
  3.         imdb.__init__(self, 'voc_' + year + '_' + image_set)  
  4.         self._year = year  
  5.         self._image_set = image_set  
  6.         self._devkit_path = self._get_default_path() if devkit_path is None \  
  7.                             else devkit_path  
  8.         self._data_path = os.path.join(self._devkit_path, 'VOC' + self._year)  
  9.         self._classes = ('__background__', # always index 0  
  10.                          '你的标签1','你的标签2',你的标签3','你的标签4'  
  11.                       )  

上面要改的地方是

修改训练集文件夹:训练所需文件所在地方

[plain] view plain copy
  1. self._data_path = os.path.join(self._devkit_path, 'VOC'+self._year)  

用你的数据集直接替换原来VOC2007内的Annotations,ImageSets和JPEGImages即可,以免出现各种错误。


修改标签:

[plain] view plain copy
  1. self._classes = ('__background__', # always index 0  
  2.                          '你的标签1','你的标签2','你的标签3','你的标签4'  
  3.                       )  

修改成你的数据集的标签就行。


[html] view plain copy
  1. cls = self._class_to_ind[obj.find('name').text.lower().strip()]  
这里把标签转成小写,如果你的标签含有大写字母,可能会出现KeyError的错误,所以建议标签用小写字母。

(去掉lower应该也行)

建议训练的标签还是用小写的字母,如果最终需要用大写字母或中文显示标签,可参考:

http://blog.csdn.net/sinat_30071459/article/details/51694037


G.py-faster-rcnn/lib/datasets/imdb.py修改

该文件的append_flipped_images(self)函数修改为:

[plain] view plain copy
  1. def append_flipped_images(self):  
  2.         num_images = self.num_images  
  3.         widths = [PIL.Image.open(self.image_path_at(i)).size[0]  
  4.                   for i in xrange(num_images)]  
  5.         for i in xrange(num_images):  
  6.             boxes = self.roidb[i]['boxes'].copy()  
  7.             oldx1 = boxes[:, 0].copy()  
  8.             oldx2 = boxes[:, 2].copy()  
  9.             boxes[:, 0] = widths[i] - oldx2 - 1  
  10.             print boxes[:, 0]  
  11.             boxes[:, 2] = widths[i] - oldx1 - 1  
  12.             for b in range(len(boxes)):
                   if boxes[b][2]< boxes[b][0]:
                      boxes[b][0] = 0
  13.             print boxes[:, 0]  
  14.             assert (boxes[:, 2] >= boxes[:, 0]).all()  
  15.             entry = {'boxes' : boxes,  
  16.                      'gt_overlaps' : self.roidb[i]['gt_overlaps'],  
  17.                      'gt_classes' : self.roidb[i]['gt_classes'],  
  18.                      'flipped' : True}  
  19.             self.roidb.append(entry)  
  20.         self._image_index = self._image_index * 2  


这里assert (boxes[:, 2] >= boxes[:, 0]).all()可能出现AssertionError,具体解决办法参考:
http://blog.csdn.net/xzzppp/article/details/52036794

(2)删除相应上次训练文件

为防止与之前的模型搞混,训练前删除相应上次训练文件

A  把output文件夹删除或改个其他名

B  把py-faster-rcnn/data/cache中的文件删除

C  把py-faster-rcnn/data/VOCdevkit2007/annotations_cache中的文件删除(如果有的话)。


(3)设置训练参数

A  至于学习率等之类的设置,可在py-faster-rcnn/models/pascal_voc/ZF/faster_rcnn_alt_opt中的solve文件设置

B  迭代次数可在py-faster-rcnn\tools的train_faster_rcnn_alt_opt.py中修改:

[plain] view plain copy
  1. max_iters = [80000, 40000, 80000, 40000]  
分别为4个阶段(rpn第1阶段,fast rcnn第1阶段,rpn第2阶段,fast rcnn第2阶段)的迭代次数。可改成你希望的迭代次数。

如果改了这些数值,最好把py-faster-rcnn/models/pascal_voc/ZF/faster_rcnn_alt_opt里对应的solver文件(有4个)也修改,stepsize小于上面修改的数值。


(4).开始训练

进入py-faster-rcnn,执行:

[plain] view plain copy
  1. ./experiments/scripts/faster_rcnn_alt_opt.sh 0 ZF pascal_voc  

这样,就开始训练了。


4,测试


(1)拷贝训练好的模型
将训练得到的py-faster-rcnn\output\faster_rcnn_alt_opt\***_trainval中ZF的caffemodel拷贝至py-faster-rcnn\data\faster_rcnn_models(如果没有这个文件夹,就新建一个)

(2)修改相应参数

修改py-faster-rcnn\tools\demo.py

A   改成自己的数据集标签;

[plain] view plain copy
  1. CLASSES = ('__background__',  
  2.            '你的标签1', '你的标签2', '你的标签3', '你的标签4')  

B  上面ZF的caffemodel改成自己的caffemodel,拷贝过去一般不用变

[plain] view plain copy
  1. NETS = {'vgg16': ('VGG16',  
  2.                   'VGG16_faster_rcnn_final.caffemodel'),  
  3.         'zf': ('ZF',  
  4.                   'ZF_faster_rcnn_final.caffemodel')}  

C  改成你的测试图片,同时测试图片放在py-faster-rcnn\data\demo中

[plain] view plain copy
  1. im_names = ['1559.jpg','1564.jpg']  
(3)开始测试

在py-faster-rcnn下,执行:

[plain] view plain copy
  1. ./tools/demo.py --net zf  
测试结果会保存在py-faster-rcnn下面

阅读全文
0 0