win10 caffe python Faster-RCNN训练自己数据集(转)

根据自己的数据集修改文件

1.模型配置文件

我用end2end的方式训练,这里我用vgg_cnn_m_1024为例说明。所以我们先打开models\pascal_voc\VGG_CNN_M_1024\faster_rcnn_end2end\train.prototxt,有4处需要修改

[plain]  view plain  copy
print ?
  1. <span style="font-size:14px;">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': 3" #这里改为你训练类别数+1  
  11.   }  
  12. }</span>  
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': 3" #这里改为你训练类别数+1
  }
}

[plain]  view plain  copy print ?
  1. <span style="font-size:14px;">layer {  
  2.   name: 'roi-data'  
  3.   type: 'Python'  
  4.   bottom: 'rpn_rois'  
  5.   bottom: 'gt_boxes'  
  6.   top: 'rois'  
  7.   top: 'labels'  
  8.   top: 'bbox_targets'  
  9.   top: 'bbox_inside_weights'  
  10.   top: 'bbox_outside_weights'  
  11.   python_param {  
  12.     module: 'rpn.proposal_target_layer'  
  13.     layer: 'ProposalTargetLayer'  
  14.     param_str: "'num_classes': 3" #这里改为你训练类别数+1  
  15.   }  
  16. }</span>  
layer {
  name: 'roi-data'
  type: 'Python'
  bottom: 'rpn_rois'
  bottom: 'gt_boxes'
  top: 'rois'
  top: 'labels'
  top: 'bbox_targets'
  top: 'bbox_inside_weights'
  top: 'bbox_outside_weights'
  python_param {
    module: 'rpn.proposal_target_layer'
    layer: 'ProposalTargetLayer'
    param_str: "'num_classes': 3" #这里改为你训练类别数+1
  }
}
[plain]  view plain  copy print ?
  1. <span style="font-size:14px;">layer {  
  2.   name: "cls_score"  
  3.   type: "InnerProduct"  
  4.   bottom: "fc7"  
  5.   top: "cls_score"  
  6.   param {  
  7.     lr_mult: 1  
  8.   }  
  9.   param {  
  10.     lr_mult: 2  
  11.   }  
  12.   inner_product_param {  
  13.     num_output: 3  #这里改为你训练类别数+1  
  14.     weight_filler {  
  15.       type: "gaussian"  
  16.       std: 0.01  
  17.     }  
  18.     bias_filler {  
  19.       type: "constant"  
  20.       value: 0  
  21.     }  
  22.   }  
  23. }  
  24. layer {  
  25.   name: "bbox_pred"  
  26.   type: "InnerProduct"  
  27.   bottom: "fc7"  
  28.   top: "bbox_pred"  
  29.   param {  
  30.     lr_mult: 1  
  31.   }  
  32.   param {  
  33.     lr_mult: 2  
  34.   }  
  35.   inner_product_param {  
  36.     num_output: 12  #这里改为你的(类别数+1)*4  
  37.     weight_filler {  
  38.       type: "gaussian"  
  39.       std: 0.001  
  40.     }  
  41.     bias_filler {  
  42.       type: "constant"  
  43.       value: 0  
  44.     }  
  45.   }  
  46. }</span>  
layer {
  name: "cls_score"
  type: "InnerProduct"
  bottom: "fc7"
  top: "cls_score"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 3  #这里改为你训练类别数+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
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 12  #这里改为你的(类别数+1)*4
    weight_filler {
      type: "gaussian"
      std: 0.001
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}
然后我们修改models\pascal_voc\VGG_CNN_M_1024\faster_rcnn_end2end\test.prototxt。

[plain]  view plain  copy print ?
  1. <span style="font-size:14px;">layer {  
  2.   name: "relu7"  
  3.   type: "ReLU"  
  4.   bottom: "fc7"  
  5.   top: "fc7"  
  6. }  
  7. layer {  
  8.   name: "cls_score"  
  9.   type: "InnerProduct"  
  10.   bottom: "fc7"  
  11.   top: "cls_score"  
  12.   param {  
  13.     lr_mult: 1  
  14.     decay_mult: 1  
  15.   }  
  16.   param {  
  17.     lr_mult: 2  
  18.     decay_mult: 0  
  19.   }  
  20.   inner_product_param {  
  21.     num_output: 3 </span><span style="font-size:14px;"> #这里改为你训练类别数+1</span><span style="font-size:14px;">  
  22. </span><span style="font-size:14px;"></span>  
layer {
  name: "relu7"
  type: "ReLU"
  bottom: "fc7"
  top: "fc7"
}
layer {
  name: "cls_score"
  type: "InnerProduct"
  bottom: "fc7"
  top: "cls_score"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  inner_product_param {
    num_output: 3  #这里改为你训练类别数+1
[plain]  view plain  copy print ?
  1. <span style="font-size:14px;">    weight_filler {  
  2.       type: "gaussian"  
  3.       std: 0.01  
  4.     }  
  5.     bias_filler {  
  6.       type: "constant"  
  7.       value: 0  
  8.     }  
  9.   }  
  10. }  
  11. layer {  
  12.   name: "bbox_pred"  
  13.   type: "InnerProduct"  
  14.   bottom: "fc7"  
  15.   top: "bbox_pred"  
  16.   param {  
  17.     lr_mult: 1  
  18.     decay_mult: 1  
  19.   }  
  20.   param {  
  21.     lr_mult: 2  
  22.     decay_mult: 0  
  23.   }  
  24.   inner_product_param {  
  25.     num_output: 12 </span><span style="font-size:14px;"> #这里改为你的(类别数+1)*4</span><span style="font-size:14px;">  
  26. </span>  
    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
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  inner_product_param {
    num_output: 12  #这里改为你的(类别数+1)*4
[plain]  view plain  copy print ?
  1. <span style="font-size:14px;">    weight_filler {  
  2.       type: "gaussian"  
  3.       std: 0.001  
  4.     }  
  5.     bias_filler {  
  6.       type: "constant"  
  7.       value: 0  
  8.     }  
  9.   }  
  10. }</span>  
    weight_filler {
      type: "gaussian"
      std: 0.001
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}
 

另外在 solver里可以调训练的学习率等参数,在这篇文章里不做说明

==================以下修改lib中的文件==================

2.修改imdb.py

[python]  view plain  copy print ?
  1. <span style="font-size:14px;">    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.             boxes[:, 2] = widths[i] - oldx1 - 1  
  11.             for b in range(len(boxes)):  
  12.                 if boxes[b][2]< boxes[b][0]:  
  13.                     boxes[b][0] = 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 </span>  
    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  
            boxes[:, 2] = widths[i] - oldx1 - 1
            for b in range(len(boxes)):
                if boxes[b][2]< boxes[b][0]:
                    boxes[b][0] = 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 
找到这个函数,并修改为如上

3、修改rpn层的5个文件

在如下目录下,将文件中param_str_全部改为param_str

4、修改config.py

将训练和测试的proposals改为gt

[plain]  view plain  copy print ?
  1. <span style="font-size:14px;"># Train using these proposals  
  2. __C.TRAIN.PROPOSAL_METHOD = 'gt'  
  3. # Test using these proposals  
  4. __C.TEST.PROPOSAL_METHOD = 'gt</span>  
# Train using these proposals
__C.TRAIN.PROPOSAL_METHOD = 'gt'
# Test using these proposals
__C.TEST.PROPOSAL_METHOD = 'gt

5、修改pascal_voc.py

因为我们使用VOC来训练,所以这个是我们主要修改的训练的文件。

[plain]  view plain  copy print ?
  1. <span style="font-size:14px;"> def __init__(self, image_set, year, devkit_path=None):  
  2.         imdb.__init__(self, 'voc_' + year + '_' + image_set)  
  3.         self._year = year  
  4.         self._image_set = image_set  
  5.         self._devkit_path = self._get_default_path() if devkit_path is None \  
  6.                             else devkit_path  
  7.         self._data_path = os.path.join(self._devkit_path, 'VOC' + self._year)  
  8.         self._classes = ('__background__', # always index 0  
  9.                             'cn-character','seal')  
  10.         self._class_to_ind = dict(zip(self.classes, xrange(self.num_classes)))  
  11.         self._image_ext = '.jpg'  
  12.         self._image_index = self._load_image_set_index()  
  13.         # Default to roidb handler  
  14.         self._roidb_handler = self.selective_search_roidb  
  15.         self._salt = str(uuid.uuid4())  
  16.         self._comp_id = 'comp4'</span>  
 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
                            'cn-character','seal')
        self._class_to_ind = dict(zip(self.classes, xrange(self.num_classes)))
        self._image_ext = '.jpg'
        self._image_index = self._load_image_set_index()
        # Default to roidb handler
        self._roidb_handler = self.selective_search_roidb
        self._salt = str(uuid.uuid4())
        self._comp_id = 'comp4'

在self.classes这里,'__background__'使我们的背景类,不要动他。下面的改为你自己标签的内容。

修改以下2段内容。否则你的test部分一定会出问题。

[python]  view plain  copy print ?
  1. def _get_voc_results_file_template(self):  
  2.        # VOCdevkit/results/VOC2007/Main/<comp_id>_det_test_aeroplane.txt  
  3.        filename = self._get_comp_id() + '_det_' + self._image_set + '_{:s}.txt'  
  4.        path = os.path.join(  
  5.            self._devkit_path,  
  6.            'VOC' + self._year,  
  7.         ImageSets,  
  8.            'Main',  
  9.            '{}' + '_test.txt')  
  10.        return path  
 def _get_voc_results_file_template(self):
        # VOCdevkit/results/VOC2007/Main/<comp_id>_det_test_aeroplane.txt
        filename = self._get_comp_id() + '_det_' + self._image_set + '_{:s}.txt'
        path = os.path.join(
            self._devkit_path,
            'VOC' + self._year,
			ImageSets,
            'Main',
            '{}' + '_test.txt')
        return path
[python]  view plain  copy print ?
  1. def _write_voc_results_file(self, all_boxes):  
  2.        for cls_ind, cls in enumerate(self.classes):  
  3.            if cls == '__background__':  
  4.                continue  
  5.            print 'Writing {} VOC results file'.format(cls)  
  6.            filename = self._get_voc_results_file_template().format(cls)  
  7.            with open(filename, 'w+') as f:  
  8.                for im_ind, index in enumerate(self.image_index):  
  9.                    dets = all_boxes[cls_ind][im_ind]  
  10.                    if dets == []:  
  11.                        continue  
  12.                    # the VOCdevkit expects 1-based indices  
  13.                    for k in xrange(dets.shape[0]):  
  14.                        f.write('{:s} {:.3f} {:.1f} {:.1f} {:.1f} {:.1f}\n'.  
  15.                                format(index, dets[k, -1],  
  16.                                       dets[k, 0] + 1, dets[k, 1] + 1,  
  17.                                       dets[k, 2] + 1, dets[k, 3] + 1))  
 def _write_voc_results_file(self, all_boxes):
        for cls_ind, cls in enumerate(self.classes):
            if cls == '__background__':
                continue
            print 'Writing {} VOC results file'.format(cls)
            filename = self._get_voc_results_file_template().format(cls)
            with open(filename, 'w+') as f:
                for im_ind, index in enumerate(self.image_index):
                    dets = all_boxes[cls_ind][im_ind]
                    if dets == []:
                        continue
                    # the VOCdevkit expects 1-based indices
                    for k in xrange(dets.shape[0]):
                        f.write('{:s} {:.3f} {:.1f} {:.1f} {:.1f} {:.1f}\n'.
                                format(index, dets[k, -1],
                                       dets[k, 0] + 1, dets[k, 1] + 1,
                                       dets[k, 2] + 1, dets[k, 3] + 1))

三、end2end训练

1、删除缓存文件

每次训练前将data\cache 和 data\VOCdevkit2007\annotations_cache中的文件删除。

2、开始训练

在py-faster-rcnn的根目录下打开git bash输入

[plain]  view plain  copy print ?
  1. <span style="font-size:18px;">./experiments/scripts/faster_rcnn_end2end.sh 0 VGG_CNN_M_1024 pascal_voc</span>  
./experiments/scripts/faster_rcnn_end2end.sh 0 VGG_CNN_M_1024 pascal_voc

当然你可以去experiments\scripts\faster_rcnn_end2end.sh中调自己的训练的一些参数,也可以中VGG16、ZF模型去训练。我这里就用默认给的参数说明。

出现了这种东西的话,那就是训练成功了。用vgg1024的话还是很快的,还是要看你的配置,我用1080ti的话也就85min左右。我就没有让他训练结束了。

四、测试

训练完成之后,将output中的最终模型拷贝到data/faster_rcnn_models,修改tools下的demo.py,我是使用VGG_CNN_M_1024这个中型网络,不是默认的ZF,所以要改的地方挺多
1. 修改class

1
2
3
4
5
6
7
8
9
10
11
12
CLASSES = ('__background__',
           'Blouse', 'Sweatpants', 'Cardigan', 'Button-Down',
                         'Cutoffs', 'Chinos', 'Top', 'Anorak', 'Kimono',
                         'Tank', 'Robe', 'Parka', 'Jodhpurs',
                         'Halter', 'Shorts', 'Caftan','Turtleneck',
                         'Leggings', 'Joggers', 'Hoodie', 'Culottes',
                            'Sweater', 'Flannel', 'Jeggings', 'Blazer',
                             'Onesie', 'Coat', 'Henley', 'Jacket',
                             'Trunks', 'Gauchos', 'Sweatshorts', 'Romper',
                             'Jersey', 'Bomber', 'Sarong', 'Dress','Jeans',
                             'Tee', 'Coverup', 'Capris', 'Kaftan','Peacoat',
                             'Poncho', 'Skirt', 'Jumpsuit')

2. 增加你自己训练的模型

1
2
3
4
5
NETS = {'vgg16': ('VGG16',
                  'VGG16_faster_rcnn_final.caffemodel'),
        'zf': ('ZF',
                  'ZF_faster_rcnn_final.caffemodel'),
        'myvgg1024':('VGG_CNN_M_1024','vgg_cnn_m_1024_faster_rcnn_iter_70000.caffemodel')}

3. 修改prototxt,如果你用的是ZF,就不用改了

1
2
prototxt = os.path.join(cfg.MODELS_DIR, NETS[args.demo_net][0],
                            'faster_rcnn_end2end', 'test.prototxt')

复制代码

if __name__ == '__main__':
    cfg.TEST.HAS_RPN = True  # Use RPN for proposals

    args = parse_args()

    prototxt = os.path.join(cfg.MODELS_DIR, NETS[args.demo_net][0],
                            'faster_rcnn_end2end', 'test.prototxt')
    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()
    else:
        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)

    # Warmup on a dummy image
    im = 128 * np.ones((300, 500, 3), dtype=np.uint8)
    for i in xrange(2):
        _, _= im_detect(net, im)

    im_names = ['f1.jpg','f8.jpg','f7.jpg','f6.jpg','f5.jpg','f4.jpg','f3.jpg','f2.jpg',]
    for im_name in im_names:
        print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
        print 'Demo for data/demo/{}'.format(im_name)
        demo(net, im_name)

    plt.show()

复制代码

在这个部分,将你要测试的图片写在im_names里,并把图片放在data\demo这个文件夹下。

4. 开始检测
执行 ./tools/demo.py –net myvgg1024
假如不想那么麻烦输入参数,可以在demo的parse_args()里修改默认参数
parser.add_argument(‘–net’, dest=’demo_net’, help=’Network to use [myvgg1024]’,
choices=NETS.keys(), default=’myvgg1024’)
这样只需要输入 ./tools/demo.py 就可以了

猜你喜欢

转载自blog.csdn.net/qq_37124237/article/details/81071082
今日推荐