美文网首页CNN
Caffe学习笔记8:Faster R-CNN运行及实时性DEM

Caffe学习笔记8:Faster R-CNN运行及实时性DEM

作者: Zz鱼丸 | 来源:发表于2017-09-10 16:38 被阅读288次

    faster-rcnn:Fast Region-based Convolutional Neural Networks基于区域的卷积神经网络

    http://blog.csdn.net/column/details/ym-alanyannick.html
    

    先感谢敖川学长给我提供练手的电脑!
    前面都学习CNN在图像分类上的巨大优势和应用,但是要把CNN用作目标检测改怎么实现,困扰了我很久。学了几天先作个笔记。
    在Faster R-CNN之前还有R-CNN和Fast R-CNN。既然Faster R-CNN是前面的改进,我就先学Faster R-CNN。

    如有错误请指正!

    理论部分

    在学习目标检测之前,我就想象CNN怎么用作目标检测。第一想法是将图像切割送入网络中。RCNN就是类是滑动窗的东西进行操作:
    1.提取建议区域
    2.利用CNN对建议区域进行分类

    • 提取建议区域方法的发展:1.滑动窗口 2.select search/edge box 3.rpn(Region Proposal Network)
    • 其他深度学习检测策略,利用CNN强大表述能力直接对目标位置进行回归,例如YOLO

    R-CNN、Fast R-CNN、Faster R-CNN三者关系


    image.png
    SPP Net

    一般CNNs后解full-connect layer或者classifier,他们都需要固定的输入尺寸。因此不得不对输入数据进行crop(修剪)或warp(弯曲),这些预处理会造成数据丢失或几何学上的失真。SPP Net的第一个贡献是将空间金字塔的思想加入到CNNs中,实现了数据的多尺度输入。

    image.png

    如图,在卷积层和全连接层之间加入SPP layer。此时网络的输入可以是任意尺寸,在SPP layer中每一个pooling的filter会根据输入调整大小,而SPP的输出尺寸始终是固定的。
    在R-CNN中,每个proposed region先rescale成统一大小,然后分别作为CNNs的输入,这样是很低效的。
    在SPP Net中,只对原图进行一次卷积得到整张图的feature map,然后找到每个proposed region在feature map上的映射patch,将此patch作为每个proposed region的卷积特征输入到SPP layer和之后的层。节省了大量的计算时间,比R-CNN有一百倍左右的加速。

    Fast R-CNN整体结构
    image.png

    如图,Fast R-CNN的网络有两个输出层,一个softmax,一个bbox regressor(相对的R-CNN,SPP Net中分类和回归是两个部分,这里集成在了同一个网络中)。而且加入了一个RoI pooling layer(类似于一个尺度的SPP layer)。注意:Fast R-CNN提取建议区域的方法依然是select search。

    • RoI pooling layer
      这是SPP pooling的一个简化版本,可以看做是只有一个尺度 filter的‘金字塔’。输入是N个整幅图的feature map和一组R个RoI(proposed region)。每个特征映射都是HWC,每个RoI是一个元组(n,r,c,h,w),n是特征映射的索引,r,c,h,w分别是RoI的左上角坐标和高与宽。输出是max-pooling过得特征映射H’xW’xC,如上图中红色框线。
    Faster-RCNN整体框架
    image.png

    Faster R-CNN的主要贡献是设计了提取建议区域的网络Region Proposal Network(RPN)。代替了费时的select search,使检测速度大为提高。下图为Faster R-CNN的结构图,黄色部分为RPN,可以看出除了RPN,其它部分继承了FR-CNN的结构

    RPN整体结构
    image.png

    RPN的网络结构类似于FR-CNN,连接与最后卷基层输出的feature map,有一个RoI层,两个输出层,一个输出滑窗为建议区域的概率,另一个输出bbox回归的offset。其训练方式也类似于FR-CNN。注意:RPN与FR-CNN共用卷积层。

    image.png

    RPN通过一个滑动窗口(图中红色框)连接在最后一个卷积层输出的feature map上,然后通过全连接层调整到256-d的向量,作为输出层的输入。同时每个滑动窗对应k个anchor boxes,在论文中使用3个尺寸和3个比例的3*3=9个anchor。每个anchor对应原图上一个感受野,通过这种方法提高scale-invariant。

    Multi-task loss
    image.png

    FR-CNN的有两个网络输出层,将原来与网络分开的bbox regression的操作整合在了网络中。并设计了一个同时优化两个输出层的loss函数。

    image.png
    RoI-centric sampling与Image-centric sampling
    • RoI-centric sampling:从所有图片的所有RoI中随机均匀取样,这样每个SGD的mini-batch中包含了不同图像中的样本(SPP Net采用)。SPP Net的反向传播没有到SPP pooling之前的层,因为反向传播需要计算每一个RoI感受野的卷基层,通常会覆盖整幅图像,又慢又耗内存。FR-CNN想要解决这个限制。
    • Image-centric sampling:mini-batch采用分层采样,先对图像采样,再对RoI采样。将采样的RoI限定在个别图像内,这样同一图像的RoI共享计算和内存。通过这种策略,实现了端到端的反向传播,可以fine-tuning整个网络。

    为了使共用的卷积层在训练RPN和FR-CNN时都会收敛,论文里设计了一个四步训练的策略:

    • (1):对RPN进行end-to-end的训练,这里网络使用ImageNet pre-trained model进行初始化。
    • (2):使用第一步RPN生成的建议区域训练FR-CNN,这里也使用ImageNet pre-trained model进行初始化。
    • (3):使用上一步FR-CNN的参数初始化RPN,固定卷基层,只fine-tune RPN独有的层。(在此步已共享卷积层)
    • (4):固定卷基层,只fine-tune FR-CNN独有的层。
    训练时采用的一些策略与参数设置

    训练样本选择方法与其参数设置

    Fast-RCNN中参数的设置
        ims_per_batch 1或2
        batch_size 128
        每个batch中正样本占得比率。  fg_fraction 0.25
        与GT的IOU大于阈值0.6的ROI作为正样本。  fg_thresh=0.6
        与GT的IOU在阈值0.1到0.5之间的ROI作为负样本。bg_thresh_hi=0.5、bg_thresh_lo=0.1
    

    实现部分

    参考:http://blog.csdn.net/u012177034/article/details/52288835

    1.下载py-faster-RCNN源码
    git clone --recursive https://github.com/rbgirshick/py-faster-rcnn
    
    2.编译lib库
    cd $FRCN_ROOT/lib
    make
    
    3.编译caffe

    这部分巨恶心,由于py-faster-rcnn编写时的caffe版本很老无法直接编译,可以直接下载我提供的连接链接: https://pan.baidu.com/s/1pLkIFDx 密码: sj9y。我的配置为:GTX1070,CUDA8.0,cuDNN6.5,i7

    cd caffe-fast-rcnn  
    git remote add caffe https://github.com/BVLC/caffe.git  
    git fetch caffe  
    git merge caffe/master
    
    4.运行demo
    cd $FRCN_ROOT
    ./tools/demo.py
    
    4.修改为视频流demo

    faster-rcnn的确实不能满足实时性要求,fps在这配置下为8,延迟为0.5s左右
    由于原代码使用了matplotlib绘图模块,每次显示需要手动关闭。如果要处理视频还是使用opencv,但是opencv的参数与matplotlib不同需注意。
    demo_vedio.py
    需要改的地方在vis_detections()这个函数里
    我直接把整个代码贴上来

    #!/usr/bin/env python
    
    # --------------------------------------------------------
    # Faster R-CNN
    # Copyright (c) 2015 Microsoft
    # Licensed under The MIT License [see LICENSE for details]
    # Written by Ross Girshick
    # --------------------------------------------------------
    
    """
    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__',
               'aeroplane', 'bicycle', 'bird', 'boat',
               'bottle', 'bus', 'car', 'cat', 'chair',
               'cow', 'diningtable', 'dog', 'horse',
               'motorbike', 'person', 'pottedplant',
               'sheep', 'sofa', 'train', 'tvmonitor')
    
    NETS = {'vgg16': ('VGG16',
                      'VGG16_faster_rcnn_final.caffemodel'),
            'zf': ('ZF',
                      'ZF_faster_rcnn_final.caffemodel')}
    
    
    def vis_detections(im, class_name, dets, thresh=0.5):
        """Draw detected bounding boxes."""
        inds = np.where(dets[:, -1] >= thresh)[0]
        if len(inds) == 0:
            return
    
        for i in inds:
            bbox = dets[i, :4]
            score = dets[i, -1]
      
        font=cv2.FONT_HERSHEY_SIMPLEX
        cv2.putText(im, '{}>= {:.1f}'.format(class_name,thresh), (int(bbox[0]), int(bbox[3])), font, 1, (0,255,0), 2)
        cv2.rectangle(im,(int(bbox[0]), int(bbox[3])),(int(bbox[2]), int(bbox[1])),(0,255,0),5)
        cv2.imshow("im",im)
        
    def demo(net, im):
        """Detect object classes in an image using pre-computed object proposals."""
    
        # Load the demo image
        #im_file = os.path.join(cfg.DATA_DIR, 'demo', image_name)
        #im = cv2.imread(im_file)
        
        # Detect all object classes and regress object bounds
        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])
    
        # Visualize detections for each class
        CONF_THRESH = 0.8
        NMS_THRESH = 0.3
        for cls_ind, cls in enumerate(CLASSES[1:]):
            cls_ind += 1 # because we skipped background
            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, 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  # Use RPN for proposals
    
        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()
        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)
    
        videoCapture = cv2.VideoCapture('/home/noneland/PycharmProjects/Train0707/BR2.avi') 
        success, im = videoCapture.read()
        while success :
            demo(net, im)
            success, im = videoCapture.read() 
            if cv2.waitKey(10) & 0xFF == ord('q'):
                break
        videoCapture.release()
        cv2.destroyAllWindows()
    

    很好的一张原理图:


    image.png

    相关文章

      网友评论

      • 夜月_佳:不好意思想请问一下跑您的demo在载入模型的时候就停下来了
        是内存不够的问题吗?
        Zz鱼丸:内存不足会显式out of memary

      本文标题:Caffe学习笔记8:Faster R-CNN运行及实时性DEM

      本文链接:https://www.haomeiwen.com/subject/kpazjxtx.html