常见目标检测算法


基于深度学习算法的目标检测算法主要分为两类:One-Stage与Two-Stage。One-Stage与Two-Stage是两种不同的思路。

1. One-Stage 目标检测模型

主要思路:是一种基于单阶段的目标检测方法,它将目标检测问题视为一个单一的回归问题。在One-Stage算法中,通常采用的是一些基于锚点的检测方法,如YOLO、SSD、RetinaNet等。这些方法通过将图像分割成不同的锚点,对每个锚点进行分类与回归,以确定是否存在目标物体以及物体的位置与大小。

One-Stage

One-Stage算法的优点是速度快、实时性好、在一些需要实时监测的场景中有很好的应用价值。不需要生成候选区域,简化了检测过程。缺点是精度相对较低,对于小目标的检测效果不太理想,也容易出现误检测或者漏检测的情况。

1.1 Yolo 目标检测模型

Yolo v1是CVPR2016的文章,从RCNN到Fast RCNN一直采用的思路是proposal+分类(proposal提供位置信息,分类提供类别信息)精度已经很高,但是速度不行。

  1. 主要创新点
    1.1 不像其它目标检测算法(例如R-CNN)采用region_proposal(回归问题) + classifiers(分类问题)的检测方式,而是将目标检测当作一个回归(regression) 问题来处理。
    1.2 使用单个网络,输入一整张图像仅经过一次推理可以得到图像中所有目标的检测框和所属类别。同时可以直接端到端(end-to-end) 地训练和优化网络。
  2. 算法优势
    2.1 YOLO的首要优势就是快,同时可以保持较高的准确率。其标准版模型在Tian X GPU上可以达到实时的45fps。另外YOLO还提供了一个fast版本,速度高达150fps,同时其检测精度大概是其它实时检测系统的2倍。
    2.2 YOLO使用全图的上下文信息,使得它相比于Fast R-CNN有更少的背景错误(在没有目标的背景区域错误地检测出目标)
    2.3 泛化能力、通用性更好,面对新领域和意外输入时地表现比R-CNN等更稳定。

1.1.1 基本流程

在这里插入图片描述

  1. Resize成448448,图片分割为77网格
  2. CNN提取特征和预测:a)772=98个bounding box(bbox)的坐标x,y,w,h和是否有物体的confidence。b)7*7=49个cell所属20个物体的概率。
  3. 过滤bbox(通过nms)
    在这里插入图片描述
    模型最终输出7730个tensor:如下图所示
    在这里插入图片描述

1.1.2 网络设计

在这里插入图片描述
网络借鉴了GoogLeNet。24个卷积层,2个全链接层。

损失函数的设计:
在这里插入图片描述

  1. 位置误差和分类误差对loss的贡献应当是不同的,因此在计算loss时引入λ c o o r d = 5 来修正坐标损失。
  2. 每张图像中都有许多网格是不包含任何目标的(即没有目标的中心点落入这些网格内),这会使得大部分网格内边界框的confidence值偏向于0,变相放大了包含目标的网格的confidence误差在计算梯度时的影响。YOLO引入λ n o o b j = 0.5来修正这一影响。
  3. 相同的位置偏差对大物体的IoU error的影响要远小于对小物体的影响,因此YOLO通过将物体大小的信息项(w,h)开平方来修正平衡二者的影响。

2. Two-Stage 目标检测模型

主要思路:是一种基于两阶段的目标检测方法,它将目标检测问题分成了两个步骤:首先生成候选区域,然后对候选区域进行分类与回归,通常采取的是基于区域提取的检测方法。如Faster-CNN、Mask R-CNN等。

在这里插入图片描述

Two-Stage算法的优点是精度高,对于小目标的检测效果较好,且可以通过一些优化手段进一步提高检测精度。缺点是速度相对较慢,需要生成大量的候选区域,增加了计算量和时间复杂度。

2.1 RCNN

2.1.1 RCNN简介

RCNN是利用深度学习进行目标检测的开山之作。作者Ross Girshick多次在PASCAL VOC的目标检测竞赛中折桂,曾在2010年带领团队获得终身成就奖。

RCNN在PASCAL VOC2012数据集上将检测率从35.1%提升至53.7%,使得CNN在目标检测领域成为常态,也使得大家开始探索CNN在其他计算机视觉领域的巨大潜力。

论文:《 Rich feature hierarchies for accurate object detection and semantic segmentation 》
作者:Ross Girshick
源码(作者提供):源码-github

2.1.2 RCNN算法基本流程

RCNN算法的流程可以分为4个步骤

  1. 一张图像生成1K~2K个候选区域(使用Selective Search方法)
  2. 对每个候选区域,使用深度网络提取特征
  3. 特征送入每一类SVM分类器,判断是否属于该类
  4. 使用回归期精细修正候选框的位置
    在这里插入图片描述

2.2 Fast RCNN

2.2.1 Fast RCNN简介

Fast RCNN算法是2015年Ross Girshick(还是这位大佬)提出的,在RCNN和SPPNet的基础上进行了改进。根据名字就知道,Fast RCNN更快更强。其训练步骤实现了端到端,基于CGG16网络,其训练速度比RCNN快了9倍,测试速度快了213倍,在PASCAL VOC2012数据集达到了68.4%的准确率。

论文:《Fast R-CNN》
源码(作者提供):源码-github

2.2.2 Fast RCNN算法基本流程

Fast RCNN算法流程可以分为3个步骤

  1. 一张图像生成1K~2K个候选区域(使用Selective Search方法)
  2. 将图像输入网络得到相应的特征图,将SS算法生成的候选框投影到特征图上获得相应的特征矩阵
  3. 将每个特征矩阵通过ROI pooling层缩放到7*7大小的特征图,接着将特征图展平通过一系列全连接层得到预测结果

在这里插入图片描述

2.3 Faster RCNN

2.3.1 Faster RCNN简介

经过R-CNN和Fast RCNN的积淀,Ross Girshick(还是这位大佬)在2016年提出了新的Faster RCNN,在结构上,Faster RCNN已经将特征抽取,proposal提取,bounding box regression,classification都整合在了一个网络中,使得综合性能有较大的提高,在检测速度方面尤为明显。
在这里插入图片描述
依作者看来,如图1,Faster RCNN其实可以分为4个主要内容:

  1. Conv layers。作为一种CNN网络目标检测方法,Faster RCNN首先使用一组基础的conv+relu+pooling层提取image的feature maps。该feature maps被共享用于后续RPN层和全连接层。
  2. Region Proposal Networks。RPN网络用于生成region proposals。该层通过softmax判断anchors属于positive或者negative,再利用bounding box regression修正anchors获得精确的proposals。
  3. Roi Pooling。该层收集输入的feature maps和proposals,综合这些信息后提取proposal feature maps,送入后续全连接层判定目标类别。
  4. Classification。利用proposal feature maps计算proposal的类别,同时再次bounding box regression获得检测框最终的精确位置

2.3.2 Conv layers

Conv_layers包含了conv、pooling、relu三种层。其中Conv layers共有13个conv层,13个relu层,4个pooling层,其中在Conv layers中:

  1. 所有的conv层都是:kernel_size=3,pad=1,stride=1
  2. 所有的pooling层都是:kernel_size=2,pad=0,stride=2
    在Conv layers中对所有的卷积都做了扩边处理,导致原图变为(M+2)x(N+2),再做3x3卷积后输出MxN。这种设置保证了conv层不改变输入和输出矩阵的大小。
    在这里插入图片描述
    Conv layers中的pooling层kernel_size=2,stride=2。这样经过pooling层的MxN矩阵,都会变为(M/2)x(N/2)大小,所以一个MxN大小的矩阵经过Conv layers固定变为(M/16)x(N/16)。这样Conv layers生成的feature map中都可以与原图对应起来。

2.3.3 Region Proposal Networks(RPN)

如图展示了RPN网络的具体结构,可以看到RPN网络实际分为2条线,上面一条通过softmax分类anchors获得positive和negative分类,下面一条用于计算对于anchors的bounding box regression偏移量,以获得精确的proposal。而最后的Proposal层则负责综合positive anchors和对应bounding box regression偏移量获取proposals,同时剔除太小和超出边界的proposals。其实整个网络到了Proposal Layer这里,就完成了相当于目标定位的功能。

在这里插入图片描述
其实RPN最终就是在原图尺度上,设置了密密麻麻的候选Anchor。然后用cnn去判断哪些Anchor是里面有目标的positive anchor,哪些是没目标的negative anchor。所以,仅仅是个二分类而已!

在这里插入图片描述

  1. 在原文中使用的是ZF model中,其Conv Layers中最后的conv5层num_output=256,对应生成256张特征图,所以相当于feature map每个点都是256-dimensions
  2. 在conv5之后,做了rpn_conv/3x3卷积且num_output=256,相当于每个点又融合了周围3x3的空间信息,同时256-d不变
  3. 假设在conv5 feature map中每个点上有k个anchor(默认k=9),而每个anhcor要分positive和negative,所以每个点由256d feature转化为cls=2•k scores;而每个anchor都有(x, y, w, h)对应4个偏移量,所以reg=4•k coordinates
  4. 补充一点,全部anchors拿去训练太多了,训练程序会在合适的anchors中随机选取128个postive anchors+128个negative anchors进行训练

RPN网络结构,总结起来就是:
生成anchors -> softmax分类器提取positvie anchors -> bbox reg回归positive anchors -> Proposal Layer生成proposals

2.3.4 RoI Poing

而RoI Pooling层则负责收集proposal,并计算出proposal feature maps,送入后续网络。Rol pooling层有2个输入:

  1. 原始的feature maps
  2. RPN输出的proposal boxes(大小各不相同)

RoI Pooling layer forward过程:

  1. 由于proposal是对应MxN尺度的,所以首先使用spatial_scale参数将其映射回(M/16)x(N/16)大小的feature map尺度;
  2. 再将每个proposal对应的feature map区域水平分为 pool_w*pool_h 的网格;
  3. 对网格的每一份都进行max pooling处理。

这样处理后,即使大小不同的proposal输出结果都是 pool_w*pool_h 固定大小,实现了固定长度输出。
在这里插入图片描述

2.3.5 Classification

Classification部分利用已经获得的proposal feature maps,通过full connect层与softmax计算每个proposal具体属于那个类别(如人,车,电视等),输出cls_prob概率向量;同时再次利用bounding box regression获得每个proposal的位置偏移量bbox_pred,用于回归更加精确的目标检测框。
在这里插入图片描述

2.4 Faster RCNN代码实现

Faster RCNN整体流程如下图所示:
在这里插入图片描述

  1. 加载数据集
  2. 数据预处理
  3. 传入特征提取网络(backbone),得到特征图
  4. 特征图传入PRN网络
  5. 特征图信息以及RPN输出传入roi_heads(roi_heads:ROIpooling + Two MLPHead + FastRCNNPredictor + Postprocess Detections)
    将bbox信息映射回原图

2.4.1 VOC数据集

Pascal VOC2012 train/val数据集下载地址:数据集下载地址
PASCAL VOC挑战赛是一个世界级的计算机视觉挑战赛,是由欧盟资助的网络组织。PASCAL VOC挑战赛主要包括以下几类:图像分类、目标检测、目标分割、动作识别等。VOC的类别主要有20个检测类别,如下图所示:
在这里插入图片描述

2.4.2 代码与代码架构

代码来源:Faster RCNN代码
文件结构如下所示:

├── backbone: 特征提取网络,可以根据自己的要求选择
├── network_files: Faster R-CNN网络(包括Fast R-CNN以及RPN等模块)
├── train_utils: 训练验证相关模块(包括cocotools)
├── my_dataset.py: 自定义dataset用于读取VOC数据集
├── train_mobilenet.py: 以MobileNetV2做为backbone进行训练
├── train_resnet50_fpn.py: 以resnet50+FPN做为backbone进行训练
├── train_multi_GPU.py: 针对使用多GPU的用户使用
├── predict.py: 简易的预测脚本,使用训练好的权重进行预测测试
├── validation.py: 利用训练好的权重验证/测试数据的COCO指标,并生成record_mAP.txt文件
└── pascal_voc_classes.json: pascal_voc标签文件

2.4.3 模型的训练

  1. 确保提前准备好数据集
  2. 确保提前下载好对应预训练模型权重
  3. 若要训练resnet50+fpn+fasterrcnn,直接使用train_resnet50_fpn.py训练脚本
  4. 若要使用多GPU训练,使用python -m torch.distributed.launch --nproc_per_node=8 --use_env train_multi_GPU.py指令,nproc_per_node参数为使用GPU数量
  5. 如果想指定使用哪些GPU设备可在指令前加上CUDA_VISIBLE_DEVICES=0,3(例如我只要使用设备中的第1块和第4块GPU设备)
    CUDA_VISIBLE_DEVICES=0,3 python -m torch.distributed.launch --nproc_per_node=2 --use_env train_multi_GPU.py

训练过程截图:
在这里插入图片描述

2.4.4 模型的测试

模型测试方面我选择了三张图片进行初步的测试,测试结果如下所示:

def main():
    # get devices
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    print("using {} device.".format(device))

    # create model
    model = create_model(num_classes=21)

    # load train weights
    weights_path = "./save_weights/model.pth"
    assert os.path.exists(weights_path), "{} file dose not exist.".format(weights_path)
    weights_dict = torch.load(weights_path, map_location='cpu')
    weights_dict = weights_dict["model"] if "model" in weights_dict else weights_dict
    model.load_state_dict(weights_dict)
    model.to(device)

    # read class_indict
    label_json_path = './pascal_voc_classes.json'
    assert os.path.exists(label_json_path), "json file {} dose not exist.".format(label_json_path)
    with open(label_json_path, 'r') as f:
        class_dict = json.load(f)

    category_index = {str(v): str(k) for k, v in class_dict.items()}

    # load image
    original_img = Image.open("./test1.jpg")

    # from pil image to tensor, do not normalize image
    data_transform = transforms.Compose([transforms.ToTensor()])
    img = data_transform(original_img)
    # expand batch dimension
    img = torch.unsqueeze(img, dim=0)

    model.eval()  # 进入验证模式
    with torch.no_grad():
        # init
        img_height, img_width = img.shape[-2:]
        init_img = torch.zeros((1, 3, img_height, img_width), device=device)
        model(init_img)

        t_start = time_synchronized()
        predictions = model(img.to(device))[0]
        t_end = time_synchronized()
        print("inference+NMS time: {}".format(t_end - t_start))

        predict_boxes = predictions["boxes"].to("cpu").numpy()
        predict_classes = predictions["labels"].to("cpu").numpy()
        predict_scores = predictions["scores"].to("cpu").numpy()

        if len(predict_boxes) == 0:
            print("没有检测到任何目标!")

        plot_img = draw_objs(original_img,
                             predict_boxes,
                             predict_classes,
                             predict_scores,
                             category_index=category_index,
                             box_thresh=0.5,
                             line_thickness=3,
                             font='arial.ttf',
                             font_size=20)
        plt.imshow(plot_img)
        plt.show()
        # 保存预测的图片结果
        plot_img.save("test_result.jpg")

第一张:
在这里插入图片描述

在这里插入图片描述
第二张:
在这里插入图片描述在这里插入图片描述
第三张:
在这里插入图片描述
在这里插入图片描述

3. Anchor-free目标检测模型

当前anchor-based目标检测方法可分one-stage、two-stage两种。one-stage模型利用anchor机制得到大量的框,之后直接加入回归、分类分支对框进行分类与微调。two-stage模型则首先提出大量的候选框,使召回率达到最大,之后在第二个stage对这些候选框进行分类与回归。无论是one-stage还是two-stage方法都存在大量的计算资源浪费和必须后处理(nms)的问题,从而无法实现end-to-end

3.1 Centernet 目标检测模型

CenterNet是一个计算机视觉框架和架构,用于目标检测和姿态估计等任务。它是由Hei Law和Jia Deng在2019年的计算机视觉与模式识别(CVPR)会议上发表的论文"Objects as Points"中提出的。其基本流程如下:

  1. 用目标框中心点表示物体
  2. 使用中心点位置的特征预测中心点offset和目标框的长、宽
  3. 每个中心点只产生一个框,从而无需nms后处理,实现真正的end-to-end

目标检测常采用Anchor的方法来获取物体可能存在的位置,再对该位置进行分类,这样的做法耗时、低效,同时需要后处理(比如NMS)。本文将目标看成一个点,即目标bounding box的中心点,整个问题转变成了关键点估计问题,其他目标属性,比如尺寸、3D位置、方向和姿态等都以估计的中心点为基准进行参数回归。

3.1.1 网络结构

常用Resnet50作为backbone,这里主要介绍resnet50_center_net,其网络结构如下:
在这里插入图片描述

3.1.2 heatmap生成

CenterNet将目标当成一个点来检测,即用目标box的中心点来表示这个目标,预测目标的中心点偏移量(offset),宽高(size)来得到物体实际box,而heatmap则是表示分类信息。每一个类别都有一张heatmap,每一张heatmap上,若某个坐标处有物体目标的中心点,即在该坐标处产生一个keypoint(用高斯圆表示)

如下图左边是缩放后送入网络的图片,尺寸为512x512,右边是生成的heatmap图,尺寸为128x128(网络最后预测的heatmap尺度为128x128。其步骤如下:

  1. 将目标的box缩放到128x128的尺度上,然后求box的中心点坐标并取整,设为point
  2. 根据目标box大小计算高斯圆的半径,设为R
  3. 在heatmap图上,以point为圆心,半径为R填充高斯函数计算值。(point点处为最大值,沿着半径向外按高斯函数递减)

在这里插入图片描述
heatmap上的关键点之所以采用二维高斯核来表示,是由于对于在目标中心点附近的一些点,期预测出来的box和gt_box的IOU可能会大于0.7,不能直接对这些预测值进行惩罚,需要温和一点,所以采用高斯核

关于高斯圆的半径确定,主要还是依赖于目标box的宽高,其计算方法为下图所示。 实际情况中会取IOU=0.7,即下图中的overlap=0.7作为临界值,然后分别计算出三种情况的半径,取最小值作为高斯核的半径r
在这里插入图片描述

3.1.3 Loss函数

center_net的loss包括三部分,heatmap的loss,目标长宽预测loss,目标中心点偏移值loss。其中heatmap的LK采用改进的focal loss,长宽预测的Lsize和目标中心点偏移Loff都采用L1Loss, 而且Lsize加上了0.1的权重。
在这里插入图片描述

Heatmap loss

相比focal loss,负样本的loss里面多了一个(1-Yxyc)β​, 是为了抑制0<Yxyc​<1的负样本的loss(heatmap高斯中心点附近那些点)
在这里插入图片描述

WH loss

在这里插入图片描述

offset loss

在这里插入图片描述

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值