目标检测是计算机视觉领域中非常重要的一个研究方向,它是将图像或者视频中目标与其他不感兴趣的部分进行区分,判断是否存在目标,确定目标位置,识别目标种类的任务,即定位+分类。传统的目标检测模型有VJ.Det[1,2],HOG.Det[3],DPM[4,5,6],直到2012年,CNN模型日益成熟化,以深度学习为基础的目标检测模型开始发展,主要分为单阶段模型(One stage)和两阶段模型(Two stage),发展路径如下:
目标检测也面临许多挑战:
目标检测也细分了很多领域
(1)BBox(边界框)
BBox:Bounding Box,边界框,边界框分为两种:Groud-truth(真实框,也简称gt_box)和prediction box(预测框,也简称pred_box),使用边界框(bounding box)来表示物体的位置,边界框是正好能包含物体的矩形框,通常有两个格式
(x1,y1,x2,y2)
(x1,y1)是矩形框的左上角的坐标,(x2,y2)是矩形框的右上角的坐标。
(x ,y ,w ,h )
(x,y)是矩形框中心点的坐标,w ww是矩形框的宽度,h hh是矩形框的高度。
(2)Anchor(锚框)
锚框与物体边界框不同,是由人们假想出来的一种框。先设定好锚框的大小和形状,再以图像上某一个点为中心画出矩形框, 将这些锚框当成可能的候选区域。
(3)RoI(Region of Interest):特定的感兴趣区域
(4)Region Proposal :候选区域
(5)RPN(Pegion Proposal Network):区域生成网络,用于生成候选区域的网络。
(6)IoU(Intersaction over Union)
在检测任务中,使用交并比(Intersection of Union,IoU)作为衡量指标。这一概念来源于数学中的集合,用来描述两个集合A AA和B BB之间的关系,它等于两个集合的交集里面所包含的元素个数,除以它们的并集里面所包含的元素个数,具体计算公式如下:
我们将用这个概念来描述两个框之间的重合度。两个框可以看成是两个像素的集合,它们的交并比等于两个框重合部分的面积除以它们合并起来的面积。
(7)mAP
AP(Average Precision)是某一类以Precision、Recall为纵、横坐标的曲线下的面积,mAP(mean Average Precision)是所有类别AP平均。
(8)NMS
搜索局部最大值,抑制极大值。
在Ross Girshick等人提出DPM方法后,目标检测进入瓶颈期,图像特征提取成为难点,随着CNN的发展,也开始尝试将神经网络加入到目标检测任务中。该图是几个模型的差异对比:
(1)R-CNN
R-CNN的全称是Region-CNN,是第一个成功将深度学习应用到目标检测中的算法,传统的目标检测方法是在图片上穷举出所有物体可能出现的区域框,对这些区域提取特征并进行分类,得到所有分类成功的区域,通过非极大值抑制(Non-maximum suppression)输出结果。R-CNN的实现步骤是
采用提取框(Selective Search):搜索候选区域,并对候选区域提取特征,并将提取到的特征存储起来。
对每个框提取特征(CNN):在数据集上训练CNN,R-CNN论文中使用的网络是AlexNet,数据集是ImageNet,在目标检测的数据集上,对训练好的CNN做微调。
图像分类(SVM):使用分类模型SVM进行训练
边框回归:通过非最大抑制策略对同一类别的ROI(region of interest)进行合并得到最终的检测结果,即得到每个矩形框的置信度。
不足:
(2)Fast R-CNN
在改进Fast R-CNN之前,有一个版本是SPPNet(Spatial Pyramind Pooling Convolutional
Networks),将CNN的输入从固定尺寸改进为任意尺寸,加入ROI池化层(即对ROI的区域进行池化),使得网络的输入图像可以是任意尺寸,输出则不变,是固定维数的向量。
Fast R-CNN在SPPNet的基础上,将 SVM分类改成了神经网络进行分类,全连接层有两个输出,一个输出负责分类(softmax),另一个输出负责框回归(bbox regressor)。
最终得到两个结果:softmax分类以及L2回归,损失函数是分类和回归的加权和。
不足:
ROI Pooling的不足:
(3)Faster R-CNN
为了解决Selective Search带来的耗时问题,Faster R-CNN引用了RPN来进行候选区域的提取,RPN是一个全卷积神经网络(Fully Convolutional Network),输入是前一层任意大小的特征图,输出是一系列的矩形目标候选区,在卷积神经网络的最后一个特征层上滑动。
为了适应多种形状的物体,RPN定义了k种不同尺度的滑窗,并将这些滑窗成为anchor,在Faster R-CNN论文中,用了9种anchor。
在分类任务中,需计算每个anchor和真实标记矩形框gt_box的IOU
在回归任务中,需计算anchor和gt_box的横、纵坐标及宽高的偏移量,Loss函数的是通过smooth L1进行计算的,公式为
ROI Align:消除ROI Padding的误差
在区域内均匀的取N个点,找到特征图上离每个点最近的四个点,再通过双线性插值的方式,得到点的输出值,最后对N个点取平均得到区域的输出。
(4)进阶模型
方案可以构造多尺度金字塔,期望模型能够具备检测不同大小尺度物体的能力,具体方案如下图:
FPN是以骨干网络的输出为输入,将特征进行上采样并与上一层特征相加得到FPN结构每一层的输出,网络结构图如下
在FPN结构中,会存在多个ROI Align,将FPN的特征金字塔类比为图像金字塔,可以通过面积来对候选框进行分配。
Cascade R-CNN主要是对IoU指标的改进,IoU是计算两个框之间的重叠区域,在模型中涉及到的细节有:一、计算基于Anchor和GT框的IoU值,二是基于预测框和真实框的IoU值。通过调整IoU的阈值并未对模型有较大提升,单一阈值训练的模型有限,因此,对模型进行多Head改进。
Libra R-CNN进行三方面的改进,分别是特征融合、采样策略、损失函数。
增强FPN的特征融合:
采样策略:
Loss(Smooth L1 loss--->Balanced L1 loss):
还有Mask R-CNN、RFCN、Light-Head R-CNN等模型的改进
(1)安装
#下载PaddleDetection
! git clone https://github.com/PaddlePaddle/PaddleDetection
#解压
! unzip -o PaddleDetection.zip
#安装cocoapi
! pip install "git+https://hub.fastgit.org/cocodataset/cocoapi.git#subdirectory=PythonAPI"
#安装需求包,在PaddleDetection路径下
!pip install -r requirements.txt
#配置环境变量
%env PYTHONPATH=.:$PYTHONPATH
%env CUDA_VISIBLE_DEVICES=0
#验证
! python ppdet/modeling/tests/test_architectures.py
(2)介绍
在PaddleDetection中实现目标检测、关键点检测、实例分割等算法,具体模型如下:
(3)模型包内容拆解
核心文件有四个configs、dataset、demo、tools, 包含了数据集、测试、模型、训练整个过程,可以按需调整实现。
教程参考:飞桨AI Studio - 人工智能学习与实训社区
(4)实现
#运行代码---训练操作,并进行验证集验证
! python -u tools/train.py -c ../faster_rcnn_r34_1x.yml --eval
其中,faster_rcnn_r34_1x.yml为配置文件,内容如下
DataReader配置:
#预测,并可视化
! python -u tools/infer.py -c ../faster_rcnn_r34_1x.yml \
--infer_img=../PCB_DATASET/images/04_missing_hole_10.jpg \
-o weights=output/faster_rcnn_r34_1x/best_model
其他模型实现步骤跟faster R-CNN相似!
(1)安装
直接用pip就能完成安装操作,故忽略。
(2)实现(参考pytorch教程文档)
import torchvision
from torchvision.models.detection.faster_rcnn import FastRCNNPredictor
from torchvision.models.detection.mask_rcnn import MaskRCNNPredictor
def get_model_instance_segmentation(num_classes):
# load an instance segmentation model pre-trained on COCO
model = torchvision.models.detection.maskrcnn_resnet50_fpn(pretrained=True)
# get number of input features for the classifier
in_features = model.roi_heads.box_predictor.cls_score.in_features
# replace the pre-trained head with a new one
model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)
# now get the number of input features for the mask classifier
in_features_mask = model.roi_heads.mask_predictor.conv5_mask.in_channels
hidden_layer = 256
# and replace the mask predictor with a new one
model.roi_heads.mask_predictor = MaskRCNNPredictor(in_features_mask,
hidden_layer,
num_classes)
return model
(3)实现细节
rpn = RegionProposalNetwork(
rpn_anchor_generator, rpn_head,
rpn_fg_iou_thresh, rpn_bg_iou_thresh,
rpn_batch_size_per_image, rpn_positive_fraction,
rpn_pre_nms_top_n, rpn_post_nms_top_n, rpn_nms_thresh,
score_thresh=rpn_score_thresh)
#rpn_anchor_generator:AnchorGenerator-生成锚框
#rpn_head:RPNHead(包含classification and regression 的RPN head,参数:输入特征的通道数,被预测的anchors数量)
roi_heads = RoIHeads(
# Box
box_roi_pool, box_head, box_predictor,
box_fg_iou_thresh, box_bg_iou_thresh,
box_batch_size_per_image, box_positive_fraction,
bbox_reg_weights,
box_score_thresh, box_nms_thresh, box_detections_per_img)
box_head: TwoMLPHead:两个linear
box_roi_pool:MultiScaleRoIAlign
box_predictor: FastRCNNPredictor 两个linear,一个做classifer,一个做box regression