深度学习第四课程笔记-卷积神经网络之目标检测

声明!

本文参考何宽大佬所写,点击可以到达

目标定位

在图片中,需要定位到我们的目标,采用下图的方式:
在这里插入图片描述
这里Y输出有8个量,分别是PC(判断是否是我们的目标)bx,by代表目标中心位置bh,bw代表目标长宽c1,c2,c3分别代表别的目标,误差函数也有所区别,当pc=1(也就是说图里面有我们要识别的目标,我们在,误差函数相应第一个)

特征点检测

在这里插入图片描述
通过卷积得到的结果,这里可以输出不同位置对应的坐标点,可以通过这些点来大致的描绘出轮廓。

目标检测

采用基于滑动窗口的目标检测算法
在这里插入图片描述
以上图为例,训练一个带标签的卷积网络,可以实现滑动窗口目标检测,如下图:
在这里插入图片描述

  • 但是这种方法有个缺点在于计算成本,图片剪切成一个个小块,卷积神经网络需要一个个处理,如果步幅过大,检测不精细,反之,会造成计算成本过高(主要来自于重复计算)
  • 这个算法不错,但是对于单个分类任务成本高很多,同时滑动太慢,除非使用超细的粒度(框的大小)或者极小步幅,否则无法准确定位图像。目前有方法可以优化计算成本。
    卷积滑动窗口的实现
    在这里插入图片描述
    上面是我们正常的卷积,在后面转化成列向量形式是没办法用卷积的,所以这里可以通过同样维度的卷积核(这里是5*5),进而卷积保持维度相同,看下下面的图:
    在这里插入图片描述
  • 这里我们进行扩充,在第二行,分四个框,我们此时值需要一次卷积(他们之间有公共的计算资源),在我们最后的输出中,不用的小方格,就可以代表我们之前图片切块卷积的信息。下面的图可以体现这一点: 在这里插入图片描述
  • 这里我们不需要分别对图片进行切片,依次卷积,只需要对整张图片进行卷积,就能得到各个部分的预测结果。
  • 这个算法效率变高,但是仍然不能输出最精准的边界框,这里可以使用YOLO algorithm (you only look once),后面会进行介绍

边界预测

YOLO算法 (you only look once)

基本思路,使用图像分类和定位算法,使用以下9个格子中,这里分了9个格子,每个格子对应一个8维的Y的输出标签跟我们前面一样 ,目标输出为3*3*8,此时我们的目标即(object)可以跨越多个小方格,把object放到中心点所在的方格的位置处。

  • 这个算法能让神经网络输出边界框,可以有任意宽高比,并能输出更精确的坐标,不会受到滑动窗法分类器的步长大小限制,同时这只是单个卷积的体现,我们并没有进行3*3次(当然如果格子越多计算越多)运算,使用一个卷积网络,共享计算步骤。
  • YOLO算法运算速度十分快,可以进行实时识别。
  • 这里确定位置,我们把yolo算法框的左上角定为(0,0),右下角为(1,1)在这里插入图片描述

交并比函数(IoU Intersection over union )

顾名思义,就是交集和并集的比,判断对象检测算法是否良好。
这里黄色代表交集交集,绿色代表并集,他们之比>0.5(也可以自己设置更高,但一般没有低的),说明良好
在这里插入图片描述

非极大值抑制(Non-max suppression )

  • 算法可能对某个对象进行多次检测,通过这种算法保证,只会对对象进行一次检测。

  • 顾名思义,就是对于我们预测的不是最大值的进行抑制,这个算法简单来说,就是一个小车可能占了我们不同小格,当然这些小小格子是临近的,这里会有不同的预测概率值。 在这里插入图片描述

  • 先抑制掉所有小的Pc<=0.6的,剩下的我们抑制选取概率最高的,当成边框,高亮显示。

  • 把剩下的和输出边界框有很高重叠面积的和上一步输出边界框有很高交并比的边界框抛弃。

  • 如果同时对于三个对象进行检测,输出向量会有三个额外的分量,需要独立进行三次非极大值抑制,对每种类型的输出都进行一次。 在这里插入图片描述

Anchor Boxes

  • 目前存在的问题是,一个格子只能检测一个对象,如果想一个格子检测多个对象,使用如题的方法
  • 先预定几个不同的边框,把预测结果和anchor box(这里我们是两个,一般可能更多)联合起来, 在这里插入图片描述
  • 这里我们将数据y,写两次,人的边框更像是anchor box 1 ,而车的边框更像是 anchor box 2,pc便是代表着不同的对象 在这里插入图片描述

YOLO完整算法

在这里插入图片描述

  • 对于完整的YOLO,我们可以看到,y数据的前8行,代表着anchor box 1 (纵轴比横轴长)的数据,后八行代表 anchor box 2 数据(横轴比纵轴长)对于不是的数据Pc=0其他数据我们不在乎,在绿色框里面,我们检测到车的框横轴比纵轴长,下八行数据Pc=1 ,C2 =1 ,其他为0
  • 对于每个小图片,我们都会得到两个框框 ,抛弃掉低概率的框。在这里插入图片描述
    在这里插入图片描述
  • 丢弃完后,对于每种类型,我们都进行一次非极大值抑制,得到最终的预测。

自动驾驶,汽车识别

要解决的问题: 假设现在在做自动驾驶的汽车,首先应该做一个汽车检测系统,为了搜集数据,在汽车前引擎盖上安装了一个照相机,在开车的时候它会每隔几秒拍摄一次前方的道路。

在这里插入图片描述

  • 想让YOLO识别80个分类,可以把分类标签c cc从1到80进行标记,或者把它变为80维的向量(80个数字),在对应位置填写上0或1。视频中我们使用的是后面的方案。因为YOLO的模型训练起来是比较久的,我们将使用预先训练好的权重来进行使用。

YOLO

YOLO(“you only look once”)因为它的实时高准确率,这就使得它是目前比较流行的算法。在算法中“只看一次(only looks once)”的机制使得它在预测时只需要进行一次前向传播,在使用非最大值抑制后,它与边界框一起输出识别对象。

yolo 模型细节

在这里插入图片描述

  • 我们会使用5个锚框(anchor boxes),所以算法大致流程是这样的:图像输入(m,608,608,3) ⇒ DEEP CNN ⇒ 编码(m,19,19,5,85)。
    在这里插入图片描述
    为了方便,我们将把最后的两个维度的数据进行展开,所以最后一步的编码由(m,19,19,5,85)变为了(m,19,19,425)。
    在这里插入图片描述
    对于每个单元格的每个锚框而言,我们将计算下列元素的乘积,并提取该框包含某一类的概率。
    在这里插入图片描述
    这里有张YOLO预测图的可视化预测:
  • 对于每个19x19的单元格,找寻最大的可能性值,在5个锚框和不同的类之间取最大值
  • 根据单元格预测的最可能的对象来使用添加颜色的方式来标记单元格。 在这里插入图片描述
  • 该可视化不是YOLO算法本身进行预测的核心部分,这只是一种可视化算法中间结果的比较好的方法。
  • 另一种可视化YOLO输出的方法是绘制它输出的边界框,这样做会导致可视化是这样的:
    在这里插入图片描述
  • 在上图中们只绘制了模型所猜测的高概率的锚框,但锚框依旧是太多了。我们希望将算法的输出过滤为检测到的对象数量更少,要做到这一点,我们将使用非最大抑制:
  • 舍弃掉低概率的锚框(意思是格子算出来的概率比较低我们就不要)
  • 当几个锚框相互重叠并检测同一个物体时,只选择一个锚框。

分类阈值过滤

在这里插入图片描述
现在我们要实现函数yolo_filter_boxes(),步骤如下:

  1. 根据图4来计算对象的可能性:
a = np.random.randn(19x19,5,1) #p_c
b = np.random.randn(19x19,5,80) #c_1 ~ c_80
c = a * b #计算后的维度将会是(19x19,5,80)
  1. 对于每个锚框,需要找到:
    对分类的预测的概率拥有最大值的锚框的索引(中文文档),需要注意的是我们需要选择的轴,我们可以试着使用axis=-1
    对应的最大值的锚框(查看中文文档),需要注意的是我们需要选择的轴,我们可以试着使用axis=-1
  2. 根据阈值来创建掩码,比如执行下列操作:[0.9, 0.3, 0.4, 0.5, 0.1] < 0.4,返回的是[False, True, False, False, True],对于我们要保留的锚框,对应的掩码应该为True或者
  3. 使用TensorFlow来对box_class_scores、boxes、box_classes进行掩码操作以过滤出我们想要的锚框。
def yolo_filter_boxes(box_confidence, boxes, box_class_probs, threshold=0.6):
    """
    通过阈值来过滤对象和分类的置信度。

    参数:
        box_confidence  - tensor类型,维度为(19,19,5,1),包含19x19单元格中每个单元格预测的5个锚框中的所有的锚框的pc (一些对象的置信概率)。
        boxes - tensor类型,维度为(19,19,5,4),包含了所有的锚框的(px,py,ph,pw )。
        box_class_probs - tensor类型,维度为(19,19,5,80),包含了所有单元格中所有锚框的所有对象( c1,c2,c3,···,c80 )检测的概率。
        threshold - 实数,阈值,如果分类预测的概率高于它,那个分么这类概率预测的就会被保留。

    返回:
        scores - tensor 类型,维度为(None,),包含了保留了的锚框的分类概率。
        boxes - tensor 类型,维度为(None,4),包含了保留了的锚框的(b_x, b_y, b_h, b_w)
        classess - tensor 类型,维度为(None,),包含了保留了的锚框的索引

    注意:"None"是因为你不知道所选框的确切数量,因为它取决于阈值。
          比如:如果有10个锚框,scores的实际输出大小将是(10,)
    """

    # 第一步:计算锚框的得分
    box_scores = box_confidence * box_class_probs
    # 计算后的维度将会是(19x19,5,80),box_confidence维度为(19,19,5,1),5是5个锚框,1为Pc=0或者Pc=1,
    # 代表这个方块有没有我们要检测的。0时候我们就不在乎其他值
    # 第二步:找到最大值的锚框的索引以及对应的最大值的锚框的分数(即索引代表我们属于哪种类型的C,分数代表这种类型出现的概率)
    box_classes = K.argmax(box_scores, axis=-1)
    box_class_scores = K.max(box_scores, axis=-1)

    # 第三步:根据阈值创建掩码(过滤掉低概率的)
    filtering_mask = (box_class_scores >= threshold)

    # 对scores, boxes 以及 classes使用掩码
    scores = tf.boolean_mask(box_class_scores, filtering_mask)
    boxes = tf.boolean_mask(boxes, filtering_mask)
    classes = tf.boolean_mask(box_classes, filtering_mask)
    # tf.boolean_mask将输入的数组挑出想要的数据输出,在原来的一堆中,挑出高概率的。
    return scores, boxes, classes

非最大值抑制

  • 即使是我们通过阈值来过滤了一些得分较低的分类,但是我们依旧会有很多的锚框被留了下来,第二个过滤器就是让下图左边变为右边,我们叫它非最大值抑制( non-maximum suppression (NMS)) 在这里插入图片描述
    非最大值抑制使用了一个非常重要的功能,叫做交并比(Intersection over Union (IoU))
    在这里插入图片描述

实现交并比函数iou(),伪代码如下:

在这里插入图片描述

def iou(box1, box2):
    """
    实现两个锚框的交并比的计算

    参数:
        box1 - 第一个锚框,元组类型,(x1, y1, x2, y2)
        box2 - 第二个锚框,元组类型,(x1, y1, x2, y2)

    返回:
        iou - 实数,交并比。
    """
    # 计算相交的区域的面积
    xi1 = np.maximum(box1[0], box2[0])
    yi1 = np.maximum(box1[1], box2[1])
    xi2 = np.minimum(box1[2], box2[2])
    yi2 = np.minimum(box1[3], box2[3])
    inter_area = (xi1 - xi2) * (yi1 - yi2)

    # 计算并集,公式为:Union(A,B) = A + B - Inter(A,B)
    box1_area = (box1[2] - box1[0]) * (box1[3] - box1[1])
    box2_area = (box2[2] - box2[0]) * (box2[3] - box2[1])
    union_area = box1_area + box2_area - inter_area

    # 计算交并比
    iou = inter_area / union_area

    return iou

实现非最大值抑制函数,关键步骤如下:

  1. 选择分值高的锚框
  2. 计算与其他框的重叠部分,并删除与iou_threshold相比重叠的框。
  3. 返回第一步,直到不再有比当前选中的框得分更低的框。
    这将删除与选定框有较大重叠的其他所有锚框,只有得分最高的锚框仍然存在

我们要实现的函数名为yolo_non_max_suppression(),使用TensorFlow实现,TensorFlow有两个内置函数用于实现非最大抑制。

def yolo_non_max_suppression(scores, boxes, classes, max_boxes=10, iou_threshold=0.5):
    """
    为锚框实现非最大值抑制( Non-max suppression (NMS))

    参数:
        scores - tensor类型,维度为(None,),yolo_filter_boxes()的输出
        boxes - tensor类型,维度为(None,4),yolo_filter_boxes()的输出,已缩放到图像大小(见下文)
        classes - tensor类型,维度为(None,),yolo_filter_boxes()的输出
        max_boxes - 整数,预测的锚框数量的最大值
        iou_threshold - 实数,交并比阈值。

    返回:
        scores - tensor类型,维度为(,None),每个锚框的预测的可能值
        boxes - tensor类型,维度为(4,None),预测的锚框的坐标
        classes - tensor类型,维度为(,None),每个锚框的预测的分类

    注意:"None"是明显小于max_boxes的,这个函数也会改变scores、boxes、classes的维度,这会为下一步操作提供方便。

    """
    max_boxes_tensor = K.variable(max_boxes, dtype="int32")  # 用于tf.image.non_max_suppression()
    tf.Session().run(tf.variables_initializer([max_boxes_tensor]))  # 初始化变量max_boxes_tensor

    # 使用使用tf.image.non_max_suppression()来获取与我们保留的框相对应的索引列表
    nms_indices = tf.image.non_max_suppression(boxes, scores, max_boxes, iou_threshold)

    # 使用K.gather()来选择保留的锚框
    scores = K.gather(scores, nms_indices)
    boxes = K
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值