【技术综述】万字长文详解Faster RCNN源代码

FasterRCNN详解 FasterRCNN详解1.2.2 FasterRCNN1 模型1.1 主干网络VGG16 or ResNet50.1.2 RPN生成建议框1.3 RCNN进行分类和回归2 预测2.1 预测流程3 训练3.1 训练流程3.2 生成标签3.3 损失函数 1.2.2 FasterRCNN FasterRCNN在FastRCNN的基础上,实现端到端的训练。算法分为3个部分。主干网络提取特征、RPN生成建议框、RCNN进行分类和回归。 FasterRCNN优点: 检测精度高。 RPN网络生成先验框。 通用型、鲁棒 阅读详情

文章首发于微信公众号《有三AI》

【技术综述】万字长文详解Faster RCNN源代码

作为深度学习算法工程师,如果你想提升C++水平,就去研究caffe源代码,如果你想提升python水平,就去研究faster-rcnn源代码吧,caffe源代码我们已经解读过了,今天这一期就解读faster-rcnn源代码

 

01 Faster R-CNN概述

1.1 基础

目标检测任务关注的是图片中特定目标物体的位置。一个检测任务包含两个子任务,其一是输出这一目标的类别信息,属于分类任务。其二是输出目标的具体位置信息,属于定位任务。

分类的结果是一个类别标签,对于单分类任务而言,它就是一个数,对于多分类任务,就是一个向量。定位任务的输出是一个位置,用矩形框表示,包含矩形框左上角或中间位置的x,y坐标和矩形框的宽度高度。

目标检测在生活中具有非常广泛的应用,它也经过了非常长的发展阶段。与计算机视觉领域里大部分的算法一样,也经历了从传统的人工设计特征和浅层分类器的思路,到大数据时代使用深度神经网络进行特征学习的思路这一过程。

相信大家已经看过很多目标检测的原理综述性文章,如果没有,就参考本公众号今天发的另一篇文章《一文道尽R-CNN系列目标检测》。

本文包括两个部分:

  1. 对经典算法Faster R-CNN的源代码进行详细的说明,选用的代码为caffe版本, 链接为:https://github.com/rbgirshick/py-faster-rcnn。

  2. 基于该框架完成一个简单的实践。在正式解读代码之前,要先说清楚两个重要概念,rpn与roi pooling。

1.2 roi pooing

通常我们训练一次取多张图,也就是一个batch,一个batch中图大小一致,这是为了从源头上把控,从而获得固定维度的特征。所以在早期进行目标检测,会将候选的区域进行裁剪或缩放到统一尺度,如下图红色框。

副作用很明显,一次只选到了目标一部分,或者把目标变形了。

sppnet不从源头而是在最后一环的特征上做处理,将任意尺度(大于4*4)大小的特征,进行3种pooling,串接起来得到固定的21维,从而避免了固定尺寸输入的约束,如下。

当然你用的时候,不必要局限于4*4,2*2,1*1。

以前为了满足全连接层固定大小输入,需要在输入图进行缩放,然后提取特征。现在既然已经可以在特征空间进行缩放了,那么就不必要求输入一样大了。

原来的那些只是因为在原始空间中有了轻微的位置或者尺寸改变就要重新提取特征的大量重复操作,就不需要了,因为任意的原始图像中的输入是可以映射到特征图中的,卷积只会改变空间分辨率,不改变比例和位置。

映射很简单,等比例缩放即可,实现时考虑好padding,stride等操作。

那这跟roi pooling有什么关系呢?

ROI pooling是一个简化的spp池化,不需要这么复杂,直接一次分块pooling就行了,在经过了从原始空间到特征空间的映射之后,设定好一个pooled_w,一个pooled_h,就是将W*H的输入pooling为pooled_w*pooled_h的特征图,然后放入全连接层。 它完成的下面的输入输出的变换。

1.2 RPN

region proposal network,可知道这就是一个网络,而且是一个小小的网络。它解决了roi pooling的输入问题,就是如何得到一系列的proposal,也就是原图中的候选框。

图比较难画就借用原文了,如上,而rpn网络的功能示意图如下。

最开始当我们想要去提取一些区域来做分类和回归时,那就穷举嘛,搞不同大小,不同比例的框,在图像中从左到右,从上到下滑动,如上图,一个就选了9种。这样计算量很大,所以selective search利用语义信息改进,避免了滑动,但还是需要在原图中操作,因为特征提取不能共享。

现在不是有了sppnet和roi pooling的框架,把上面的这个在原图中进行穷举滑动的操作,换到了比原图小很多的特征空间(比如224*224 --> 13*13),还是搞滑动窗口,就得到了rpn,如下图。

rpn实现了了上面的输入输出。不同与简单滑窗的是,网络会对这个过程进行学习,得到更有效的框。

剩下的就是一些普通cnn的知识,不用多说,有了上面的这些基础后,我们开始解读代码。

 

02 py-faster-rcnn框架解读

Faster R-CNN源代码的熟悉几乎是所有从事目标检测的人员必须迈过的坎,由于目录结构比较复杂而且广泛为人所用,涉及的东西非常多,所以我们使用的时候维持该目录结构不变,下面首先对它的目录结构进行完整的分析。

目录下包括caffe-fast-rcnn,data,experiments,lib,models,tools几大模块。

2.1 caffe-fast-rcnn

这是rcnn系列框架的caffe,因为目标检测中使用到了很多官方caffe中不包括的网络层,所以必须进行定制。这里需要注意的是caffe是以子模块的方式被包含在其中,所以使用git clone命令下载代码将得到空文件夹,必须要加上递归参数-recursive,具体做法如下:

git clone --recursive

https://github.com/rbgirshick/py-faster-rcnn.git

2.2 data

该文件夹下包含两个子文件夹,一个是scripts,一个是demo。其中demo就是用于存放测试的图像,script存储着若干脚本,它用于获取一些预训练的模型。

比如运行fetch_imagenet_models.sh脚本,会在当前的文件夹下建立imagenet_models目录,并下载VGG_CNN_M_1024.v2.caffemodel VGG16.v2.caffemodel ZF.v2.caffemodel模型,这些是在ImageNet上预先训练好的模型,将用于初始化我们的检测模型的训练。

另外还在该目录下建立数据集的软链接。通常情况下,对于一些通用的数据集,我们会将它们放在公用的目录而不是某一个项目下,所以这里通常需要建立通用数据集的软链接,比如PASCAL VOC的目录。

ln -s /your/path/to/VOC2012/VOCdevkit

VOCdevkit2012

2.3 experiments

下面分为3个目录,分别是log,cfgs,scripts。cfgs存放的就是配置文件,比如faster_rcnn_end2end的配置如下:

EXP_DIR: faster_rcnn_end2end

TRAIN:

  HAS_RPN: True

  IMS_PER_BATCH: 1

  BBOX_NORMALIZE_TARGETS_PRECOMPUTED: True

  RPN_POSITIVE_OVERLAP: 0.7

  RPN_BATCHSIZE: 256

  PROPOSAL_METHOD: gt

  BG_THRESH_LO: 0.0

TEST:

  HAS_RPN: True

其中比较重要的包括HAS_RPN,RPN_BATCHSIZE等。Log目录就存放log日志。scripts存放的就是bash训练脚本,可以用end2end或者alt_opt两种方式训练。

每一个训练脚本都包含两个步骤,训练和测试。

time ./tools/train_net.py --gpu ${GPU_ID} \

  --solver models/${PT_DIR}/${NET}/faster_rcnn_end2end/solver.prototxt \

  --weights data/imagenet_models/${NET}.v2.caffemodel \

  --imdb ${TRAIN_IMDB} \

  --iters ${ITERS} \

  --cfg experiments/cfgs/faster_rcnn_end2end.yml \

  ${EXTRA_ARGS}

如上就是训练部分代码,对于默认的任务,我们不需要修改这里的代码,但是如果我们不想用预训练,或者相关的配置发生了变化,比如yml格式的配置文件,预训练模型的前缀格式,需要配置自定义的数据集等等,则需要修改此处代码。

2.4 Models目录

该目录下包含两个文件夹,coco和pascal voc,可知是两个通用数据集。在各个数据集的子目录下存储了一系列模型结构的配置,如models/pascal/VGG_CNN_M_1024/目录,存储的就是用于训练coco数据集的VGG模型。

在该目录下,有fast_rcnn,faster_rcnn_alt_opt,faster_rcnn_end_to_end三套模型结构,各自有所不同。

fast_rcnn即fast_rcnn方法,它下面只包含了train.prototxt,test.prototxt,solver.prototxt三个文件,它对rcnn的改进主要在于重用了卷积特征,没有region proposal框架。

faster_rcnn_alt_opt,faster_rcnn_end_to_end都是faster rcnn框架,包括了region proposal模块。在faster_rcnn_alt_opt目录下,包含了4个训练文件和对应的solver文件,为:

stage1_fast_rcnn_solver30k40k.pt,stage1_fast_rcnn_train.pt,stage1_rpn_solver60k80k.pt,stage1_rpn_train.pt,stage2_fast_rcnn_solver30k40k.pt,stage2_fast_rcnn_train.pt,

stage2_rpn_solver60k80k.pt,stage2_rpn_train.pt。

其中stage1过程是分别采用了ImageNet分类任务上训练好的模型进行region proposal的学习和faster rcnn检测的学习,stage2则是在stage1已经训练好的模型的基础上进行进一步的学习。

faster_rcnn_end_to_end就是端到端的训练方法,使用起来更加简单,所以我们这一小节会使用faster_rcnn_end_to_end方法,目录下只包括了train.prototxt,test.prototxt,solver.prototxt。

当要在我们自己的数据集上完成检测任务的时候,就可以建立与pascal_voc和coco平级的目录。

2.5 Lib目录

lib目录下包含了非常多的子目录,包括datasets,fast_rcnn,nms,pycocotools,roi_data_layer,rpn,transform,utils,这是faster rcnn框架中很多方法的实现目录,下面对其进行详细解读。

(1) utils目录

这是最基础的一个目录,主要就是blob.py和bbox.pyx。blob.py用于将图像进行预处理,包括减去均值,缩放等操作,然后封装到caffe的blob中。

    for i in xrange(num_images):

        im = ims[i]

        blob[i, 0:im.shape[0], 0:im.shape[1], :] = im

    channel_swap = (0, 3, 1, 2)

    blob = blob.transpose(channel_swap)

封装的核心代码如上,首先按照图像的存储格式(H,W,C)进行赋值,然后调整通道和高,宽的顺序,这在我们使用训练好的模型进行预测的时候是必要的操作。而且,有的时候采用RGB格式进行训练,有的使用采用BGR格式进行训练,也需要做对应的调整。

bbox.pyx用于计算两个box集合的overlaps,即重叠度。一个输入是(N,4)形状的真值boxes,一个输入是(K,4)形状的查询boxes,输出为(N,K)形状,即逐个box相互匹配的结果。

(2) datasets目录

datasets目录下有目录VOCdevkit-matlab-wrapper,tools,以及脚本coco.py,pascal_voc.py,voc_eval.py,factory.py,ds_util.py,imdb.py。

我们按照调用关系来看,首先是ds_util.py,它包含了一些最基础的函数,比如unique_boxes函数,可以通过不同尺度因子的缩放,从一系列的框中获取不重复框的数组指标,用于过滤重复框。

具体实现采用了hash的方法,代码如下:

v = np.array([1, 1e3, 1e6, 1e9])

hashes = np.round(boxes * scale).dot(v).astype(np.int)

box的4个坐标,与上面的v进行外积后转换为一个数,再进行判断。

xywh_to_xyxy,xyxy_to_xywh函数分别是框的两种表达形式的相互转换,前者采用一个顶点坐标和长宽表示矩形,后者采用两个顶点坐标表示矩形,各有用途。

validata_boxes函数用于去除无效框,即超出边界或者左右,上下,不满足几何关系的点,比如右边顶点的x坐标小于左边顶点。filer_small_boxes用于去掉过小的检测框。

接下来看imdb.py,这是数据集类imdb的定义脚本,非常重要。从它的初始化函数_init_可以看出,类成员变量包括数据集的名字self._name,检测的类别名字self._classes与具体的数量self._num_classes,候选区域的选取方法self._obj_proposer,roi数据集self._roidb与它的指针self._roidb_handler,候选框提取默认采用了selective_search方法。

roidb是它最重要的数据结构,它是一个数组。数组中的每一个元素其实就是一张图的属性,以字典的形式存储它的若干属性,共4个key,为boxes,gt_overlaps,gt_classes,flipped。

候选框boxes就是一个图像中的若干的box,每一个box是一个4维的向量,包含左上角和右下角的坐标。类别信息gt_classes,就是对应boxes中各个box的类别信息。真值gt_overlaps,它的维度大小为boxes的个数乘以类别的数量,可知存储的就是输入box和真实标注之间的重叠度。另外如果设置了变量flipped,还可以存储该图像的翻转版本,这就是一个镜像操作,是最常用的数据增强操作。

roidb的生成调用了create_roidb_from_box_list函数,它将输入的box_list添加到roidb中。如果没有gt_roidb的输入,那么就是下面的逻辑,可见就是将boxes存入数据库中,并初始化gt_overlaps,gt_classes等变量。

boxes = box_list[i]

num_boxes = boxes.shape[0]

overlaps = np.zeros((num_boxes, self.num_classes), dtype=np.float32)

overlaps = scipy.sparse.csr_matrix(overlaps)

roidb.append({

                'boxes' : boxes,

                'gt_classes' : np.zeros((num_boxes,), dtype=np.int32),

                'gt_overlaps' : overlaps,

                'flipped' : False,

                'seg_areas' : np.zeros((num_boxes,), dtype=np.float32),

            })

如果输入gt_roidb非空,则需要将输入的box与其进行比对计算得到gt_overlaps,代码如下:

if gt_roidb is not None and gt_roidb[i]['boxes'].size > 0:

gt_boxes = gt_roidb[i]['boxes']

    gt_classes = gt_roidb[i]['gt_classes']

    gt_overlaps = bbox_overlaps(boxes.astype(np.float),gt_boxes.astype(np.float))

    argmaxes = gt_overlaps.argmax(axis=1)

    maxes = gt_overlaps.max(axis=1)

I = np.where(maxes > 0)[0]

overlaps[I, gt_classes[argmaxes[I]]] = maxes[I]

将输入的boxes与数据库中boxes进行比对,调用了bbox_overlaps函数。比对完之后结果存入 overlaps。

bbox_overlaps的结果overlaps是一个二维矩阵,第一维大小等于输入boxes中的框的数量,第二维就是类别数目,所存储的每一个值就是与真实标注进行最佳匹配的结果,即重叠度。但是最后存储的时候调用了overlaps = scipy.sparse.csr_matrix(overlaps)进行稀疏压缩,因为其中大部分的值其实是空的,一张图包含的类别数目有限。

还有一个变量gt_classes,在从该函数创建的时候并未赋值,即等于0,因为这个函数是用于将从rpn框架中返回的框添加到数据库中,并非是真实的标注。当gt_classes非零,说明是真实的标注,这样的数据集就是train或者val数据集,它们在一开始就被创建,反之则是test数据集。gt_classes非零的样本和为零的样本在数据集中是连续存储的。

该脚本中另一个重要的函数就是evaluate_recall,这就是用于计算average iou的函数。它的输入包括candidate_boxes,即候选框。假如没有输入,则评估时取该roidb中的非真值box。threholds,即IoU阈值,如果没有输入则默认从0.5到0.95,按照0.05的步长迭代。area,用于评估的面积大小阈值,默认覆盖0到1e10的尺度,尺度是指框的面积。还有一个limit,用于限制评估的框的数量。

返回平均召回率average recall,每一个IoU重合度阈值下的召回向量,设定的IoU阈值向量,以及所有的真值标签。

当进行评估的时候,首先要按照上面设计的面积大小阈值,得到有效的index。

max_gt_overlaps = self.roidb[i]['gt_overlaps'].toarray().max(axis=1)

gt_inds = np.where((self.roidb[i]['gt_classes'] > 0) &

      (max_gt_overlaps == 1))[0]   首先获得需要评估的index

gt_boxes = self.roidb[i]['boxes'][gt_inds, :]  得到对应的boxes

gt_areas = self.roidb[i]['seg_areas'][gt_inds]

valid_gt_inds = np.where((gt_areas >= area_range[0]) &

       (gt_areas <= area_range[1]))[0]  得到符合面积约束的index

gt_boxes = gt_boxes[valid_gt_inds, :]

num_pos += len(valid_gt_inds)  记录符合条件的框的个数

计算重叠度的过程是对每一个真值box进行遍历,寻找到与其重叠度最大的候选框,得到各个真值box的被重叠度。挑选其中被重叠度最高的真值box,然后找到对应的与其重叠度最高的box,得到了一组匹配和相应的重叠度。标记这两个box,后续的迭代不再使用,然后循环计算,直到所有的真值框被遍历完毕。

pascal_voc.py和coco.py就是利用上面的几个脚本来创建对应这两个数据集的格式,用于后续对模型的测试,下面就是pascal voc的数据库的创建过程。

def _load_pascal_annotation(self, index):

        """

        Load image and bounding boxes info from XML file in the PASCAL VOC

        format.

        """

        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" area for pascal is just the box area

        seg_areas = np.zeros((num_objs), dtype=np.float32)

 

        # Load object bounding boxes into a data frame.

        for ix, obj in enumerate(objs):

            bbox = obj.find('bndbox')

            # Make pixel indexes 0-based

            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}

从上面脚本可知,输入就是xml格式的标注文件,通过obj变量获得x1,y1,x2,y2,即标注信息,以及cls类别信息,并标注overlaps等于1。另外seg_areas实际上就是标注框的面积。

(3) nms目录

该目录下主要是cpu和gpu版本的非极大值抑制计算方法,非极大抑制算法在目标检测中应用相当广泛,其主要目的是消除多余的框,找到最佳的物体检测位置。

实现的核心思想是首先将各个框的置信度进行排序,然后选择其中置信度最高的框A,将其作为标准,同时设置一个阈值。然后开始遍历其他框,当其他框B与A的重合程度超过阈值就将B舍弃掉,然后在剩余的框中选择置信度最大的框,重复上述操作。

我们以py_cpu_nms.py为例,并添加了注释。

import numpy as np

def py_cpu_nms(dets, thresh):

    """Pure Python NMS baseline."""

    x1 = dets[:, 0]

    y1 = dets[:, 1]

    x2 = dets[:, 2]

    y2 = dets[:, 3]

    scores = dets[:, 4]  

    areas = (x2 - x1 + 1) * (y2 - y1 + 1)  #此处用于计算每一个框的面积

    order = scores.argsort()[::-1]    #按照分数大小对其进行从高到低排序

 

    keep = []

    while order.size > 0:

        i = order[0]     #取分数最高的那个框

        keep.append(i)  #保留这个框

        xx1 = np.maximum(x1[i], x1[order[1:]])

        yy1 = np.maximum(y1[i], y1[order[1:]])

        xx2 = np.minimum(x2[i], x2[order[1:]])

        yy2 = np.minimum(y2[i], y2[order[1:]])        #计算当前分数最大矩形框与其他矩形框的相交后的坐标

 

        w = np.maximum(0.0, xx2 - xx1 + 1)

        h = np.maximum(0.0, yy2 - yy1 + 1)     

        inter = w * h      #计算相交框的面积

        ovr = inter / (areas[i] + areas[order[1:]] - inter)  #计算IOU:重叠面积/(面积1+面积2-重叠面积)

 

        inds = np.where(ovr <= thresh)[0]   #取出IOU小于阈值的框

        order = order[inds + 1]     #更新排序序列

 

    return keep

(4) roi data layer目录

该目录下有3个脚本,layer.py,minibatch.py,roidb.py。

layer.py包含了caffe的RoIDataLayer网络层的实现。通常来说一个caffe网络层的实现,需要包括setup,forward,backward等函数的实现,对于数据层还需实现shuffle,批量获取数据等函数。

Roidatalayer是一个数据层,也是训练时的输入层,其中最重要的函数是setup函数,用于设置各类输出数据的尺度信息。

根据是否有RPN模块,这两种情况下的配置是不一样的,我们直接看caffe的网络配置就能明白,比较fast rcnn和faster rcnn。

首先是fast rcnn:

name: "VGG_CNN_M_1024"

layer {

  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': 21"

  }

}

可以看到,它的top输出为rois,labels,bbox_targets, bbox_inside_weights, bbox_outside_weights总共5个属性。

rois是selective search方法提取出的候选区域,尺度为(1,5),按照(index,x1,y1,x2,y2)的格式来存储。labels和bbox_targets是区域的分类和回归标签,bbox_inside_weights是正样本回归loss的权重,默认为1,负样本为0,表明在回归任务中,只采用正样本进行计算。bbox_outside_weights用于平衡正负样本的权重,它们将在计算SmoothL1Loss的时候被使用,各自的计算方法如下:

bbox_inside_weights[labels == 1, :] = np.array(cfg.TRAIN.RPN_BBOX_INSIDE_WEIGHTS)

if cfg.TRAIN.RPN_POSITIVE_WEIGHT < 0:

    # uniform weighting of examples (given non-uniform sampling)

    num_examples = np.sum(labels >= 0)

    positive_weights = np.ones((1, 4)) * 1.0 / num_examples

    negative_weights = np.ones((1, 4)) * 1.0 / num_examples

else:

    assert ((cfg.TRAIN.RPN_POSITIVE_WEIGHT > 0) &

            (cfg.TRAIN.RPN_POSITIVE_WEIGHT < 1))

    positive_weights = (cfg.TRAIN.RPN_POSITIVE_WEIGHT /

                        np.sum(labels == 1))

    negative_weights = ((1.0 - cfg.TRAIN.RPN_POSITIVE_WEIGHT) /

                        np.sum(labels == 0))

bbox_outside_weights[labels == 1, :] = positive_weights

bbox_outside_weights[labels == 0, :] = negative_weights

 

 然后是faster rcnn:

name: "VGG_CNN_M_1024"

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': 21"

  }

}

可以看到,它的top输出是im_info,gt_boxes,两者的尺度分别为(1,3)和(1,4)。而上面的rois,labels,bbox_targets, bbox_inside_weights, bbox_outside_weights全部通过rpn框架来生成,rpn框架我们下面讲。

roi_data中需要批量获取数据,实现就在minibatch.py中了,它实现一次从roidb中获取多个样本的操作,主要函数是get_minibatch,根据是否使用rpn来进行操作。

如果使用rpn,则只需要输出gt_boxes和im_info,直接从roidb数据库中获取即可。如果不使用rpn,则需要自己来生成前景和背景的rois训练图片,调用了两个函数_sample_rois,_project_im_rois。

_sample_rois函数生成前景和背景,接口如下:

_sample_rois(roidb, fg_rois_per_image, rois_per_image, num_classes)

通过rois_per_image指定需要生成的训练样本的数量, fg_rois_per_image指定前景正样本的数量。一个前景正样本就是满足与真值box中的最大重叠度大于一定阈值cfg.TRAIN.FG_THRESH的样本,一个背景就是与真值box中的最大重叠度大于一定阈值cfg.TRAIN.FG_THRELO,小于一定阈值cfg.TRAIN.BG_THRESH_SH的样本,选择样本的方法当然就是从符合条件的样本中随机选择,如果满足条件的样本不够,那就按照最低值来选择。

_project_im_rois就是一个缩放,因为训练的时候使用了不同的尺度。

(5) rpn目录

该目录就是region proposal模块,包含有generate_anchors.py,proposal_layer.py,anchor_target_layer.py,proposal_target_layer.py,generate.py脚本。

rpn有几个任务需要完成,产生一些anchors,完成anchor到图像空间的映射,得到训练样本。

generate_anchors脚本就是用于产生anchors,它使用16*16的参考窗口,产生3个比例(1:1,1:2,2:1),三个缩放尺度(0.5, 1, 2)的anchors,共9个。在原论文中对应到原始图像空间,3个尺度是(128, 256与512),代码如下:

def generate_anchors(base_size=16, ratios=[0.5, 1, 2],

                     scales=2**np.arange(3, 6)):

    base_anchor = np.array([1, 1, base_size, base_size]) - 1

    ratio_anchors = _ratio_enum(base_anchor, ratios)

    anchors = np.vstack([_scale_enum(ratio_anchors[i, :], scales)

                         for i in xrange(ratio_anchors.shape[0])])

    return anchors

anchor_target_layer.py就是实现了AnchorTargetLayer,它与generate_anchors配合使用,共同产生anchors的样本rpn,用于rpn的分类和回归任务,anchor_target_layer层的caffe配置如下。

layer {

  name: 'rpn-data'

  type: 'Python'

  bottom: 'rpn_cls_score'

  bottom: 'gt_boxes'

  bottom: 'im_info'

  bottom: 'data'

  top: 'rpn_labels'

  top: 'rpn_bbox_targets'

  top: 'rpn_bbox_inside_weights'

  top: 'rpn_bbox_outside_weights'

  python_param {

    module: 'rpn.anchor_target_layer'

    layer: 'AnchorTargetLayer'

    param_str: "'feat_stride': 16"

  }

}

可知,anchor_target_layer的输入是gt_boxes,im_info,rpn_cls_score,data,输出就是rpn_labels,rpn_bbox_targets, rpn_bbox_inside_weights, rpn_bbox_outside_weights。rpn_cls_score是rpn网络的第一个卷积的分类分支的输出,rpn网络正是通过rpn-data的指导学习到了如何提取proposals。

假如输入rpn网络的为256*13*13的特征,那么一个rpn的输出通常是一个18*13*13的分类特征图和一个36*13*13的回归特征图,它们都是通过1*1的卷积生成。13*13就是特征图的大小,它并不会改变。一个18*1*1就对应每一个位置的9个anchor的分类信息,这里的分类不管具体的类别,只分前景与背景,anchor显示里面有物体存在时可对其进行回归。一个36*1*1就对应每一个位置的9个anchor的回归信息,这是一个相对值。后面要做的,就是利用这些anchors,生成propasals了。

proposal_layer脚本,定义了ProposalLayer的类,就是从rpn的输出开始,得到最终的proposals,输入有三个,网络配置如下。

layer {

  name: 'proposal'

  type: 'Python'

  bottom: 'rpn_cls_prob_reshape'

  bottom: 'rpn_bbox_pred'

  bottom: 'im_info'

  top: 'rpn_rois'

#  top: 'rpn_scores'

  python_param {

    module: 'rpn.proposal_layer'

    layer: 'ProposalLayer'

    param_str: "'feat_stride': 16"

  }

}

可以看到,输入了rpn_bbox_pred,rpn_cls_pro_shape以及im_info,输出rpn_rois,也就是object proposals,由bbox_transform_inv函数完成坐标变换,接口如下:

proposals = bbox_transform_inv(anchors, bbox_deltas)

这里的bbox_deltas就是上面的rpn_bbox_pred,它就是预测的anchor的偏移量,它的尺寸大小是(1, 4 * A, H, W),其中H,W就是特征图的大小,而A就是基础anchors的个数,就是上面的9。Anchors的大小则是(K * A, 4),其中K是偏移位置的种类,偏移位置就是将anchors在特征图上进行滑动的偏移量,可知包含了x和y两个方向,产生的方法如下:

shift_x = np.arange(0, width) * self._feat_stride

shift_y = np.arange(0, height) * self._feat_stride

shift_x, shift_y = np.meshgrid(shift_x, shift_y)

shifts = np.vstack((shift_x.ravel(), shift_y.ravel(),

         shift_x.ravel(), shift_y.ravel())).transpose()

得到了初始的proposals之后,再经过裁剪,过滤,排序,非极大值抑制后就可以用了。

proposal_target_layer,就是从上面选择出的object proposals采样得到训练样本,流程与上面roi_data_layer层中没有rpn模块时产生训练样本类似,因此不再赘述。

labels, rois, bbox_targets, bbox_inside_weights = _sample_rois(

            all_rois, gt_boxes, fg_rois_per_image,

            rois_per_image, self._num_classes)

最后是generate脚本,就是高层的调用脚本,即使用RPN方法从imdb或者图像中产生proposals。

(6) fast_rcnn目录

该目录有bbox_transform.py,config.py,nms.wrapper.py,test.py,train.py几个脚本。

config.py是一个配置参数的脚本,它配置了非常多的默认变量,非常重要。如果想要修改,也不应该在该脚本中修改,而是到先前提到的experements目录下进行配置。

配置包含两部分,一个是训练部分的配置,一个是测试部分的配置。训练部分的配置如下,我们添加注释。

# Training options

__C.TRAIN.SCALES = (600,) #训练尺度,可以配置为一个数组

__C.TRAIN.MAX_SIZE = 1000 #缩放后图像最长边的上限

__C.TRAIN.IMS_PER_BATCH = 2 #每一个batch使用的图像数量

__C.TRAIN.BATCH_SIZE = 128 #每一个batch中使用的ROIs的数量

__C.TRAIN.FG_FRACTION = 0.25 #每一个batch中前景的比例

__C.TRAIN.FG_THRESH = 0.5 #ROI前景阈值

__C.TRAIN.BG_THRESH_HI = 0.5 #ROI背景高阈值

__C.TRAIN.BG_THRESH_LO = 0.1 #ROI背景低阈值

__C.TRAIN.USE_FLIPPED = True #训练时是否进行水平翻转

__C.TRAIN.BBOX_REG = True #是否训练回归

__C.TRAIN.BBOX_THRESH = 0.5 #用于训练回归的roi与真值box的重叠阈值

__C.TRAIN.SNAPSHOT_ITERS = 10000 #snapshot间隔

__C.TRAIN.SNAPSHOT_INFIX = '' #snapshot前缀

__C.TRAIN.BBOX_NORMALIZE_TARGETS = True #bbox归一化方法,去均值和方差

__C.TRAIN.BBOX_NORMALIZE_MEANS = (0.0, 0.0, 0.0, 0.0)

__C.TRAIN.BBOX_NORMALIZE_STDS = (0.1, 0.1, 0.2, 0.2)

__C.TRAIN.BBOX_INSIDE_WEIGHTS = (1.0, 1.0, 1.0, 1.0) #rpn 前景box权重

__C.TRAIN.PROPOSAL_METHOD = 'selective_search' #默认proposal方法

__C.TRAIN.ASPECT_GROUPING = True #一个batch中选择尺度相似的样本

__C.TRAIN.HAS_RPN = False #是否使用RPN

__C.TRAIN.RPN_POSITIVE_OVERLAP = 0.7 #正样本IoU阈值

__C.TRAIN.RPN_NEGATIVE_OVERLAP = 0.3 #负样本IoU阈值

__C.TRAIN.RPN_CLOBBER_POSITIVES = False

__C.TRAIN.RPN_FG_FRACTION = 0.5 #前景样本的比例

__C.TRAIN.RPN_BATCHSIZE = 256 #RPN样本数量

__C.TRAIN.RPN_NMS_THRESH = 0.7 #NMS阈值

__C.TRAIN.RPN_PRE_NMS_TOP_N = 12000 #使用NMS前,要保留的top scores的box数量

__C.TRAIN.RPN_POST_NMS_TOP_N = 2000 #使用NMS后,要保留的top scores的box数量

__C.TRAIN.RPN_MIN_SIZE = 16 #原始图像空间中的proposal最小尺寸阈值

测试时相关配置类似,此处不再一一解释。

bbox_transform.py中的bbox_transform函数计算的是两个N * 4的矩阵之间的相关回归矩阵,两个输入矩阵一个是anchors,一个是gt boxes,本质上是在求解每一个anchor相对于它的对应gt box的(dx, dy, dw, dh)的四个回归值,返回结果的shape为[N, 4],使用了log指数变换。

bbox_transform.py中的bbox_transform_inv函数用于将rpn网络产生的deltas进行变换处理,求出变换后的对应到原始图像空间的boxes,它输入boxes和deltas,boxes表示原始anchors,即未经任何处理仅仅是经过平移之后产生的anchors,shape为[N, 4],N表示anchors的数目。deltas就是RPN网络产生的数据,即网络'rpn_bbox_pred'层的输出,shape为[N, (1 + classes) * 4],classes表示类别数目,1 表示背景,N表示anchors的数目,核心代码如下。

widths = boxes[:, 2] - boxes[:, 0] + 1.0

heights = boxes[:, 3] - boxes[:, 1] + 1.0

ctr_x = boxes[:, 0] + 0.5 * widths

ctr_y = boxes[:, 1] + 0.5 * heights

dx = deltas[:, 0::4]

dy = deltas[:, 1::4]

dw = deltas[:, 2::4]

dh = deltas[:, 3::4]

pred_ctr_x = dx * widths[:, np.newaxis] + ctr_x[:, np.newaxis]

pred_ctr_y = dy * heights[:, np.newaxis] + ctr_y[:, np.newaxis]

pred_w = np.exp(dw) * widths[:, np.newaxis]

pred_h = np.exp(dh) * heights[:, np.newaxis]

pred_boxes = np.zeros(deltas.shape, dtype=deltas.dtype)

# x1

pred_boxes[:, 0::4] = pred_ctr_x - 0.5 * pred_w

# y1

pred_boxes[:, 1::4] = pred_ctr_y - 0.5 * pred_h

# x2

pred_boxes[:, 2::4] = pred_ctr_x + 0.5 * pred_w

# y2

pred_boxes[:, 3::4] = pred_ctr_y + 0.5 * pred_h

可以看出,它与bbox_transform是配合使用的,bbox_transform使用了对数变换将anchor存储下来,而bbox_transform_inv则将其恢复到图像空间。

网络的回归坐标预测的是一个经过平移和尺度缩放的因子,如果采用原始的图像坐标,则可能覆盖从0~1000这样几个数量级差距的数值,很难优化。

train.py和test.py分别是训练主脚本和测试主脚本。在训练主脚本中,定义了一个类solverWrapper,包含训练的函数和存储模型结果的函数。

test.py脚本中最重要的函数是im_detect,它的输入是caffe的模型指针,输入BGR顺序的彩色图像,以及可选的R*4的候选框,这适用于使用selective search提取候选框的方法,拥有rpn框架的faster rcnn则不需要。

返回包括两个值,一个是scores,一个是boxes。scores就是各个候选框中各个类别的概率,boxes就是各个候选中的目标的回归坐标。

im_detect方法首先调用_get_blobs函数,它输入im和boxes。在_get_blobs函数中首先调用_get_image_blob获得不同尺度的测试输入,测试尺度在cfg.TEST.SCALES中进行配置。

假如没有rpn网络,则boxes非空,这时候需要配置的输入为blobs['rois']。调用_get_rois_blob函数,它会调用_project_im_rois得到不同尺度的输入RoI。

假如有rpn网络,则需要配置blobs['im_info'],它会用于辅助RPN框架从特征空间到原始图像空间的映射。

Forward部分代码如下:

forward_kwargs = {'data': blobs['data'].astype(np.float32, copy=False)}

if cfg.TEST.HAS_RPN:

   forward_kwargs['im_info'] = blobs['im_info'].astype(np.float32, copy=False)

else:

   forward_kwargs['rois'] = blobs['rois'].astype(np.float32, copy=False)

blobs_out = net.forward(**forward_kwargs)

前向传播的结果在blobs_out中,分类器如果使用SVM,则分类结果为scores = net.blobs['cls_score'].data,如果使用cnn softmax,则分类结果为scores = blobs_out['cls_prob']。

如果有边界回归网络,获取回归结果的代码如下:

box_deltas = blobs_out['bbox_pred']

pred_boxes = bbox_transform_inv(boxes, box_deltas)

pred_boxes = clip_boxes(pred_boxes, im.shape)

可知原始的回归结果是一个偏移量,它需要通过bbox_transform_inv反投影到图像空间。test.py脚本中还包含函数apply_nms,用于对网络输出的结果进行非极大值抑制。

2.6 tools 目录

该目录包含的就是最高层的可执行脚本,包括_init_paths.py,compress_net.py,demo.py,eval_recall.py,reval.py,rpn_genetate.py这几个脚本。

_init_paths.py,用于初始化若干路径,包括caffe的路径以及lib的路径,一般大型的工程用这样的一个文件剥离出路径是很好的选择。

compress_net.py,这是用于压缩参数的脚本,使用了SVD矩阵分解的方法来对模型进行压缩,这通常对于全连接层是非常有效的,因为对于一些经典的网络如AlexNet,VGGNet等,全连接层占据了网络的绝大部分参数。脚本中给出的例子对VGGNet的fc6层和fc7层进行了压缩,读者可以使用这个脚本去对更多的带全连接层的网络进行压缩尝试。

demo.py,这是一个demo演示脚本,调用了fast_rcnn中的test脚本中的检测函数,使用了工程自带的一些图像以及预先提取好的proposal,配置好模型之后就可以进行演示。如果要测试自己的模型和数据,也可以非常方便进行修改。

eval_recall.py,这是用于在测试数据集上对所训练的模型进行评估的脚本,默认使用的数据集是voc_2007_test,它会统计在不同阈值下的检测框召回率。

reval.py:对已经检测好的结果进行评估。

rpn_genetate.py,这个脚本调用了rpn中的genetate函数,产生一个测试数据集的proposal并将其存储到pkl文件。

test_net.py,测试训练好的fast rcnn网络的脚本,调用了fast rcnn的test函数。

train_faster_rcnn_alt_opt.py,这是faster rcnn文章中的使用交替的训练方法来训练faster rcnn网络的具体实现,它包括4个阶段,分别是:

RPN第1阶段,使用在imagenet分类任务上进行训练的模型来初始化参数,生成proposals。

fast rcnn第1阶段,使用在imagenet分类任务上进行训练的模型来初始化参数,使用刚刚生成的proposal进行fast rcnn的训练。

RPN第2阶段,使用fast rcnn训练好的参数进行初始化,并生成proposal。

fast rcnn 第2阶段,使用RPN第2阶段中的模型进行参数初始化。

train_net.py,训练脚本。

train_svms.py,R-CNN网络的SVM训练脚本,可以不关注。

在熟悉了框架后,就可以使用我们的数据进行训练了。

 

03 网络分析

下面我们开始一个任务,就来个猫脸检测吧,使用VGG CNN 1024网络,看一下网络结构图,然后我们按模块解析一下。

3.1 input

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': 2"

  }

}

这里要改的,就是num_classes,因为我们只有一个猫脸,前景类别数目等于1。

3.2 rpn

layer {

  name: "rpn_conv/3x3"

  type: "Convolution"

  bottom: "conv5"

  top: "rpn/output"

  param { lr_mult: 1.0 }

  param { lr_mult: 2.0 }

  convolution_param {

    num_output: 256

    kernel_size: 3 pad: 1 stride: 1

    weight_filler { type: "gaussian" std: 0.01 }

    bias_filler { type: "constant" value: 0 }

  }

}

layer {

  name: "rpn_relu/3x3"

  type: "ReLU"

  bottom: "rpn/output"

  top: "rpn/output"

}

layer {

  name: "rpn_cls_score"

  type: "Convolution"

  bottom: "rpn/output"

  top: "rpn_cls_score"

  param { lr_mult: 1.0 }

  param { lr_mult: 2.0 }

  convolution_param {

    num_output: 18   # 2(bg/fg) * 9(anchors)

    kernel_size: 1 pad: 0 stride: 1

    weight_filler { type: "gaussian" std: 0.01 }

    bias_filler { type: "constant" value: 0 }

  }

}

 

layer {

  name: "rpn_bbox_pred"

  type: "Convolution"

  bottom: "rpn/output"

  top: "rpn_bbox_pred"

  param { lr_mult: 1.0 }

  param { lr_mult: 2.0 }

  convolution_param {

    num_output: 36   # 4 * 9(anchors)

    kernel_size: 1 pad: 0 stride: 1

    weight_filler { type: "gaussian" std: 0.01 }

    bias_filler { type: "constant" value: 0 }

  }

}

具体的网络拓扑结构图如下:

从上图可以看出,rpn网络的输入来自于conv5卷积层的输出,后面接了rpn_conv/3x3层,输出通道数为256,stride=1。

rpn_conv/3x3层产生了两个分支,一个是rpn_cls_score,一个是rpn_bbox_pred,分别是分类和回归框的特征。

rpn_cls_score输出为18个通道,这是9个anchors的前背景概率,它一边和gt_boxes,im_info,data一起作为AnchorTargetLayer层的输入,产生分类的真值rpn_labels,回归的真值rpn_bbox_targets。另一边则经过rpn_cls_score_reshape进行reshape,然后与rpn_labels一起产生分类损失。

rpn_bbox_ppred输出为36个通道,就是9个anchors的回归预测结果,它与rpn_bbox_targets比较产生回归损失。rpn_cls_score_reshape重新reshape后得到rpn_cls_prob,rpn_cls_prob_shape,它与rpn_bbox_pred以及输入,共同得到了region prososal,就是候选的检测框。

在ProposalLayer层中配置了一个重要参数,就是feat_stride,这是前面的卷积层的feat_stride大小。ProposalLayer层完成的功能就是根据RPN的输出结果,提取出所需的目标框,而目标框是在原始的图像空间,所以这里需要预先计算出feat_stride的大小。ProposalLayer层的输出与data层一起获得最终的proposal roi,这将作为roi pooling层的输入。

3.3 roi pooing

前面得到了proposal roi之后,就可以进行roi pooling层,配置如下:

layer {

  name: "roi_pool5"

  type: "ROIPooling"

  bottom: "conv5"

  bottom: "rois"

  top: "pool5"

  roi_pooling_param {

    pooled_w: 6

    pooled_h: 6

    spatial_scale: 0.0625 # 1/16

  }

}

可以看到,它配置了几个参数,最终spatial_scale对应的就是前面的feat_stride,等于1/16,用于从图像空间的roi到特征空间roi的投影。

而pooled_w,pooled_h则是最终要pooling的特征图的大小,这里配置为6*6,从13*13的输入下采样而来。

 

04 训练与测试

写到这里我们就简略一些。要做的就是三步,为了简单,保持使用pascal接口,步骤如下。

(1)准备voc格式的数据,可以找开源数据集或者使用labelme等工具集标注,然后配置好路径。替换掉pacvoc的ImageSets/Main目录下面的文件list,以及JPEGS和Annotations目录下的文件。

(2)然后到lib\datasets\pascal_voc.py中更改self._classes中的类别,由于我们这里是二分类的检测,所以将多余的类别删除,只保留背景,添加face类别。

(3)使用experements/tools下面的脚本训练吧。

遇到了坑,就直接跳和爬吧!

 

感受一下大小脸,大姿态,遮挡,误检,漏检。

路漫漫其修远兮.......

更多请关注微信公众号《有三AI》与知乎《有三AI学院》。

【代码阅读】Faster RCNN 网络结构详解 这里写自定义目录标题Faster RCNNImage Pro-Processing主干网络 Faster RCNN作为two stage目标检测方法的代表作,其中有很多模块非常经典,在后续的two stage的模型中有广泛的应用。而且在3D Object Detection的问题中,也是如此。这就回顾一下Faster RCNN的网络结构。 这里推荐一个博客,http://www.telesens.... 阅读详情

相关推荐

Pytorch官方Faster R-CNN源代码解析(一)——特征提取

Faster R-CNN论文链接 Pytorch官方Faster R-CNN的代码文档链接。Pytorch官方使用的示例代码如下: 下面主要就示例代码进行详细说明。首先,初始化 Faster R-CNN 模型。 可以看出,这里使用的是主干网络 Resnet-50-FPN 的 Faster R-CNN。接下来 Debug 进内部代码。 Debug 进获取 ResNet_FPN 主干网络对应代码。 Debug进获取 ResNet-50 主干网络的代码。 ResNet-50 的网络结构如下图所示。 ResNet

hhhcbw的博客,欢迎各位来访 4649

Faster Rcnn详解及代码解读

1.backbone含义 backbone用于特征提取,通常使用的是VGG16或者ResNet网络,其中要经过4个pooling层,且经过多层卷积后层数也发生了变化,但仍要保证在进行下一次池化之前,特征图深度为上一次池化之前深度的两倍。故第一个pooling层的strides=4,第二个的strides=2,第三个的pooling层的strides=2,第四个的pooling层的的strides=2,所以得到的特征图的shape分别为:[1, 304, 304, 256]、[1,...

qq_41018669的博客 7337

基于FSL的DTI数据预处理流程

最近在学习处理DTI数据,总结了一份应用FSL做DTI数据预处理的流程与大家交流交流。如果有错误的地方欢迎大家指正!        我用的数据是Philips的数据,如果是GE或者西门子的数据可能会有所不同。   原始数据:包括3DT1数据和高分辨率DTI数据,均是dicom格式。 工具:MRICRON和FSL,所有的命令均在Linux的终端中运行。   1.格式转换:将后缀名为dcm

zaza_zaza的博客 2万+

【KnowledgeBase】一篇较为详细的Faster RCNN代码解读

本文将带大家稍微详细地了解Faster RCNN的整体构造以及对应的每个块的构造细节。

weixin_47691066的博客 2991

当图像配准遇见边缘计算:低功耗设备的优化实践

本文探讨了在边缘计算环境下优化图像配准技术的实践方法,重点解决低功耗设备如树莓派和Jetson Nano上的算力瓶颈问题。通过算法轻量化、硬件加速和内存优化等策略,实现了毫秒级图像配准,适用于智能安防、移动医疗等实时性要求高的场景。

weixin_29054195的博客 389

Jetson AGX Orin 新手避坑:解决‘找不到nvidia-jetpack包’的完整修复指南

本文详细介绍了Jetson AGX Orin设备在安装JetPack开发套件时遇到的'nvidia-jetpack包缺失'问题的完整解决方案。通过分析问题根源、提供分步修复指南以及系统优化建议,帮助开发者快速解决这一常见问题,充分发挥Jetson AGX Orin的边缘计算性能。

weixin_42520909的博客 462

kcp 介绍与源代码分析_【技术综述】万字长文详解Faster RCNN源代码(四)

首发于《有三AI》【技术综述】万字长文详解Faster RCNN源代码​mp.weixin.qq.comFaster R-CNN将分成四部分介绍。总共有Faster R-CNN概述,py-faster-rcnn框架解读,网络分析,和训练与测试四部分内容。第四篇将介绍网络分析,和训练与测试。3. 网络分析下面我们开始一个任务,就来个猫脸检测吧,使用VGG CNN 1024网络,看一下网络结构图,然后...

weixin_42348026的博客 221

蓝桥杯算法:打印图形——六芒星

【输入格式】 输入一行包含一个整数 n。 【输出格式】 输出一个六芒星,表示满足题意的图形。 【样例输入】 3 4 【样例输出】 【评测用例规模与约定】 对于所有评测用例,1 ≤ n ≤ 20。 总结: 第一次做图形题,做了蛮久,图形题有很多的方式去完成,它考验的是你能不能找到更简单的那一种方式. 我初看到这个图形,第一种想法是把这个六芒星当做六个小三角形来做,然后以某种规则排列一下,就能做出来,但是尝试了一下感觉太麻烦了。 然后我的第二种想法是,这个图形是对称图形,怎么能写出一半吗? 这样另一半想办

KeepCodeing 3843

深度学习之目标检测(五)faster-rcnn

深度学习之目标检测(五)faster-rcnn

DDDDavid的博客 359

3D Slicer-最强大的开源医学图像分割工具简要概述

3D Slicer 是一个免费的开源软件平台,用于医学、生物医学和其他 3D 图像的可视化、处理、分割、配准和分析。读/写DICOM图像和多种其他格式;三维图像、多边形网格和体积渲染的交互式可视化;手动编辑和标记图像;使用刚性和非刚性算法融合和共同配准数据;图像自动分割;跟踪图像引导程序的设备。所有的功能模块可在工具栏里找到,提供搜索,下拉选择,左右切换等功能。3D slicer的大概情况就介绍到这里。它的功能非常强大,也没有必要说掌握每个功能的使用。

Tina姐的博客 2万+

2021秋-北邮计算机导论期末考试(BUPT)

2021秋-北邮计算机导论期末考试(BUPT) 难度较低适合新手练习

weixin_73985779的博客 1500

nsga2代码解读python_代码资料

faster RCNN TensorFlow版本:龙鹏:【技术综述】万字长文详解Faster RCNN源代码(一) buptscdc:tensorflow 版faster rcnn代码理解(1) lonlon ago:Tensorflow 版本 Faster RCNN 代码解读 Faster RCNN源码解析(1) Faster RCNN源码解析(2) Faster R-CNN 源码解析(Tens...

weixin_39856589的博客 707

Slow waitForAckedSeqno took 64873ms (threshold=30000ms). File being written

Slow waitForAckedSeqno took 64873ms (threshold=30000ms). File being written

zhengzaifeidelushang的博客 2011

keras faster物体检测_全网 | 深度学习目标检测算法(精选12篇)

太多的公众号每天的文章是否让你眼花缭乱?刷了好多文章,发现大都是转来转去?今天我在全网公众号里为大家精选主题为深度学习目标检测算法的文章12篇,其中包括综述,R-CNN,SPP-Net,Fast R-CNN,Faster R-CNN,Mask R-CNN,R-FCN,YOLO V1,YOLO V2,YOLO V3,SSD,FPN等。目标检测的任务是找出图像中所有感兴趣的目标(物体),确定...

weixin_39564527的博客 134

计算机视觉卷积神经网络(CNN)基础:从LeNet到ResNet

计算机视觉卷积神经网络(CNN)基础:从LeNet到ResNet,在计算机视觉领域,卷积神经网络(Convolutional Neural Network,CNN)已然成为推动众多任务发展的核心力量。从早期简单的图像识别,到如今复杂的目标检测、语义分割、图像生成等任务,CNN 都展现出了卓越的性能。CNN 的发展历程见证了一系列经典模型的诞生,其中 LeNet 作为开山之作,为 CNN 的发展奠定了基础,而 ResNet 则通过创新性的设计,突破了传统神经网络的限制,使得网络能够构建得更深、性能更优。

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 14万+

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

目标检测:Faster-RCNN算法细节及代码解析

** Faster-RCNN是多阶段目标检测算法RCNN系列中的集大成者,下面来看看分别看看这个系列的算法细节。 ** **注:只简单讲解RCNN,Fast-RCNN算法。后面会重点讲解Fater-RCNN算法。 一、RCNN RCNN是2013年出现的目标检测算法,首先将深度学习引 入目标检测领域 , m A P 由 D P M 的 3 5 . 1 提 升 至 53.7。 示意图如下: 具体步骤如下: ①首先准备一张输入图片; ②候选区域生成:使用Selective Search算法,在输入图像上生成~

m0_49100031的博客 1万+

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

目标检测代码解读一(FasterRCNN)

FasterRCNN框架图如下图所示 1. RPN RPN中完成的任务有: 计算每个预测特征层上的预测目标概率和bboxes regression参数 生成一个batch的图像的所有anchors信息 将预测的bbox regression参数应用到anchors上得到最终预测bbox坐标 筛除小boxes框,nms处理,根据预测概率获取前post_nms_top_n个目标 计算每个anchors最匹配的gt,并将anchors进分类为前景,背景以及废弃的anchors 结合anchors以及对应的gt

蓝鲸鱼的博客 3599

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Faster R-CNN 源码解读 (傻瓜版) - Pytorch

前言 本篇写了很多第一次看代码做的注释。 为了便于搞懂核心脉络,对所有的分支选择都做了简化。 层次结构与jwyang的实现版本有差异,因为源版本里存在很多冗余代码。 目的是构造一个最简训练模型。 萌新学的话,可以在搭建成功之后,再自行扩展。 参考源代码:https://github.com/jwyang/faster-rcnn.pytorch/tree/pytorch-1.0 ...

w55100的博客 1万+

Faster RCNN 网络搭建代码解析

Faster RCNN 前几篇写了yolo系列的模型训练以及模型优化,加速,这篇是关于Faster RCNN。Faster RCNN所用的数据集是来自yolo v3,基本可以无缝使用。数据集参考:https://blog.youkuaiyun.com/kui9702/article/details/122954209 本节代码 GitHub:https://github.com/kile97/faster-rcnn-pytorch Faster RCNN的网络结构主要分为3部分: backbone 骨干网络

kui9702的博客 2686

Faster RCNN 代码解析

本文主要是对 Faster RCNN 流程和代码进行解析

YWRTH的博客 1634

Faster RCNN算法解析(附源代码,可以直接运行)

一、前言知识 1、基于Region Proposal(候选区域)的深度学习目标检测算法 Region Proposal(候选区域),就是预先找出图中目标可能出现的位置,通过利用图像中的纹理、边缘、颜色等信息,保证在选取较少窗口(几千个甚至几百个)的情况下保持较高的召回率(IoU,Intersection-over-Union)。 2、什么是IoU? Intersection over Un...

qq_29462849的博客 5万+

[学习笔记] Faster R-CNN源码解析

1. 如何使用PyTorch官方代码;2. 自定义Dataset;3. Faster R-CNN框架图; 4. Faster R-CNN核心代码

Le0v1n 的博客 4730

Faster-RCNN代码详解

部分注释中写的参数以mobilenet为Backbone,Pascal VOC为数据集作举例注释以特征图size=(34,25)为例,不同大小的图片生成的特征图尺寸不一定相同。

weixin_51528791的博客 2150

Faster R-CNN代码详解 标注数据形状

Faster R-CNN代码实战–潘登同学的深度学习笔记 文章目录Faster R-CNN代码实战--潘登同学的深度学习笔记数据集介绍数据处理先看combined_roidbRoIDataLayerget_output_dirTrian过程create_architecturebuild_networkBuild headBuild RPN回到_anchor_component回到Build RPN接一层3\*3卷积,再接一层1\*1卷积Build proposals_proposal_layer_anch

weixin_52185313的博客 3986

Faster-RCNN源码分析

code paper 参考文献:Faster R-CNN理解、讨论 一、FasterRCNN类 class FasterRCNN(GeneralizedRCNN): """ 模型的输入应为张量列表,每个张量为[C,H,W]形状,每个图像张量为1张,且范围应为0-1。不同的图像可以具有不同的大小。 模型的行为会根据其处于训练或评估模式而变化。 在train期间,模型期望输入张量以及目标(字典列表)都包含: -框(FloatTensor [N,4]):格式为[

蓝鲸鱼的博客 961
上一篇: 【AI杂谈】从一篇参考文献比正文还长的文章,杂谈深度学习综述
下一篇: 【资源总结】国内AI领域的赛事全集
言有三
言有三 领域专家: 人工智能技术领域 领域专家: 人工智能技术领域
博客等级 码龄15年 3635粉丝 976原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

言有三

三人行必有AI

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值