IoU交并比、目标检测、RCNN、SPPNet、Fast R-CNN、Faster R-CNN、RPN区域提议网络、FPN特征金字塔、yolo、FCN基于全卷积的语义分割、反卷积、Mask RCNN

日萌社

人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新)


 

计算IoU:计算交并比

1.候选框的坐标表示为(左上角的x坐标,左上角的y坐标,右下角的x坐标,右下角的y坐标)
2.一般的都是左上角的x/y坐标小,右下角的x/y坐标大,因为x/y坐标轴的零点位于左上角处。
"""
非极大值抑制(NMS)
1.输入数据:
    通过SVM分类器对每个锚框分类好之后,每个锚框都带上了预测类别标签值和该预测类别的置信度score,最终每个锚框都放到对应的类别列表中。
2.迭代过程:
    对每个分类列表中的锚框进行处理,比如对某个类别的列表中所有锚框根据其预测类别的置信度score按从大到小进行排序,
    首先类别的列表中取出第一个score值最大的锚框放到输出列表中,然后类别的列表中剩余的所有锚框逐一和输出列表中第一个锚框进行计算IoU值(交并比),
    把IoU值>0.5的锚框都丢弃掉,只留下IoU值<0.5的锚框继续进行下一轮比较。
    下一轮比较中,仍然先把分类列表中剩余的(score值最大)第一个锚框放到输出列表中,
    然后分类列表中剩余的所有锚框再和输出列表中最后添加进去的锚框进行计算IoU值(交并比),
    同样的把IoU值>0.5的锚框都丢弃掉,只留下IoU值<0.5的锚框,以此类推继续进行下一轮比较。
"""
    """
    上一步中已经得到yolo的检测框,但其中会存在冗余的bbox,即一个目标对应多个检测框,所以使用NMS去除重复的检测框。
    利用OpenCV内置的NMS DNN模块实现即可实现非最大值抑制 ,所需要的参数是边界框、置信度、以及置信度阈值和NMS阈值。
    第一个参数是存放边界框的列表,第二个参数是存放置信度的列表,第三个参数是自己设置的置信度,第四个参数是NMS阈值。
    返回的idxs是一个一维数组,数组中的元素是保留下来的检测框boxes的索引位置。
    dnn.NMSBoxes
        作用:根据给定的检测boxes和对应的scores进行NMS(非极大值抑制)处理
        原型:NMSBoxes(bboxes, scores, score_threshold, nms_threshold, eta=None, top_k=None)
        参数:
            boxes: 待处理的边界框 bounding boxes
            scores: 对于于待处理边界框的 scores
            score_threshold: 用于过滤 boxes 的 score 阈值
            nms_threshold: NMS 用到的阈值
            indices: NMS 处理后所保留的边界框的索引值
            eta: 自适应阈值公式中的相关系数:nms_threshold_i+1 = eta * nms_threshold_i
            top_k: 如果 top_k>0,则保留最多 top_k 个边界框索引值.
    """
    # 非极大值抑制
    # 此处的confidences使用的是 最大概率的类别的预测概率值。返回值idxs:保留下来的检测框boxes的索引位置的一维数组
    idxs = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.3)
    # 存放检测框的信息,包括左上角横坐标/纵坐标,右下角横坐标/纵坐标,以及检测到的物体的置信度(检测框的预测类别的概率值),用于目标跟踪
    dets = []
    # 存在检测框的话(即检测框个数大于0)。idxs也即 保留下来的检测框boxes的索引位置的一维数组
    if len(idxs) > 0:
        #  循环检测出的每一个检测框boxes的索引位置
        for i in idxs.flatten():
            # yolo模型可以识别很多目标,因为我们在这里只是识别车,所以只有目标是车的我们进行检测,其他的忽略
            # classIDs[检测框boxes的索引位置]:根据检测框boxes的索引位置从classIDs列表中取出该检测框boxes对应的类别
            if LABELS[classIDs[i]] == "car":
                (x, y) = (boxes[i][0], boxes[i][1]) # 得到检测框的左上角的x/y坐标
                (w, h) = (boxes[i][2], boxes[i][3]) # 得到检测框的宽和高
                # cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)
                #检测框dets:[检测框的左上角的x/y坐标, 检测框的右下角的x/y坐标, 检测框的预测类别的概率值]
                dets.append([x, y, x + w, y + h, confidences[i]]) # 将检测框的信息的放入dets中

import numpy as np

def nms(bounding_boxes, confidence_score, threshold):
    """
    :param bounding_boxes: 检测的 boxes 及对应的 scores
    :param confidence_score: 置信度score
    :param threshold: 设定的阈值
    :return:
    """

    # boxes 位置
    x1 = bounding_boxes[:, 0] # 左上角的x坐标
    y1 = bounding_boxes[:, 1] # 左上角的y坐标
    x2 = bounding_boxes[:, 2] # 右下角的x坐标
    y2 = bounding_boxes[:, 3] # 右下角的y坐标

    #一般的都是左上角的x/y坐标小,右下角的x/y坐标大,因为x/y坐标轴的零点位于左上角处。
    # 右下角的x坐标x2 - 左上角的x坐标x1 = 长
    # 右下角的y坐标y2 - 左上角的y坐标y1 = 高
    areas = (x2 - x1) * (y2 - y1) # 各 box 的面积 = 长*高

    # argsort从小到大排序,返回的是元素的索引值,[::-1]表示倒排变成从大到小 排序,排序后返回的结果为元素索引值[0, 2, 1]
    order = confidence_score.argsort()[::-1] # boxes 的按照 置信度score 从大到小 排序

    keep_box = [] # 记录保留下的 boxes 作为输出列表
    keep_confidence_score = [] # 记录保留下的 置信度score 作为输出列表

    while order.size > 0:
        i = order[0] # score 最大的 box 对应的 index
        keep_box.append(i) # 将本轮 score 最大的 box 的 index 保留
        keep_confidence_score.append(i)   # 将本轮 score 最大的 box 的 置信度score

        # 计算剩余 boxes 与当前 box 的重叠程度 IoU
        """ 类别的列表中剩余的所有锚框逐一和输出列表中第一个锚框进行 计算交集,作为分子 """
        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
        """
        areas[i]:最后添加进输出列表的的锚框的面积
        areas[order[1:]]:类别列表中的剩余锚框的面积
        areas[i] + areas[order[1:]] - inter:两者相加再减去两者的交集求出两者的并集面积
        两者的交集面积作为分子,两者的并集面积作为分母,求出的分别都是剩余锚框的 IoU值(交并比)
        """
        ovr = inter / (areas[i] + areas[order[1:]] - inter)

        """
        np.where()[0] 表示行的索引 
        np.where()[1] 表示列的索引 
        把剩余锚框的<=阈值的锚框都留下继续进行下一轮比较
        此处的np.where()[0]取出的是类别列表中剩余锚框的索引值
        """
        # 保留 IoU 小于设定阈值的 boxes
        inds = np.where(ovr <= threshold)[0]
        #只保留 <=阈值的锚框,根据所取出类别列表中剩余锚框的索引值取出该部分锚框进行下一轮比较
        order = order[inds + 1]


    return keep_box, keep_confidence_score

def union(au, bu, area_intersection):
    """
    计算并集
    :param au:
    :param bu:
    :param area_intersection:
    :return:
    """
    # 计算a的面积
    area_a = (au[2] - au[0]) * (au[3] - au[1])
    # 计算b的面积
    area_b = (bu[2] - bu[0]) * (bu[3] - bu[1])
    # a和b的面积-交集面积=总共面积
    area_union = area_a + area_b - area_intersection
    return area_union


def intersection(ai, bi):
    """
    计算交集
    :param ai:a框坐标
    :param bi:b框坐标
    :return:
    """
    # 1、取出交集的左上角点
    x = max(ai[0], bi[0])
    y = max(ai[1], bi[1])
    # 2、取出交集的右下角点,并减去左上角点值,计算出交集长宽
    w = min(ai[2], bi[2]) - x
    h = min(ai[3], bi[3]) - y
    # 3、如果一个为0,返回交集面积为0
    if w < 0 or h < 0:
        return 0
    return w*h


def iou(a, b):
    """
    计算交并比
    :param a: a框坐标
    :param b: b框坐标
    :return:
    """
    # 1、如果a,b 传入有问题
    if a[0] >= a[2] or a[1] >= a[3] or b[0] >= b[2] or b[1] >= b[3]:
        return 0.0

    # 2、计算IOU
    # 交集区域
    area_i = intersection(a, b)
    # 并集区域
    area_u = union(a, b, area_i)

    return float(area_i) / float(area_u + 1e-6)  # 防止分母为0,加一个稳定系数



if __name__ == '__main__':
    # 1.候选框的坐标表示为(左上角的x坐标,左上角的y坐标,右下角的x坐标,右下角的y坐标)
    # 2.一般的都是左上角的x/y坐标小,右下角的x/y坐标大,因为x/y坐标轴的零点位于左上角处。
    bounding_boxes = np.array([(187, 82, 337, 317), (150, 67, 305, 282), (246, 121, 368, 304)])
    confidence_score = np.array([0.9, 0.75, 0.8])  # 置信度score
    threshold = 0.4  # 阈(yu)值

    keep_box, keep_confidence_score = nms(bounding_boxes,confidence_score,threshold)
    print(bounding_boxes[keep_box]) #[[187  82 337 317]]
    print(keep_confidence_score) # [0]
 
def union(au, bu, area_intersection):
    """计算并集面积
    :param au: a框坐标
    :param bu: b框坐标
    :param intersection: 交集面积
    :return:
    """
    # a框面积
    area_a = (au[2] - au[0]) * (au[3] - au[1])

    # b框面积
    area_b = (bu[2] - bu[0]) * (bu[3] - bu[1])

    # a+b面积-交集面积
    area_union = area_a + area_b - area_intersection
    return area_union


def intersection(ai, bi):
    """计算交集
    :param ai: a框坐标
    :param bi: b框坐标
    :return:
    """
    # 1、求出交集的左上角点
    # ai和bi的左上角的x谁更大
    # ai和bi的左上角的y谁更大
    x_left = max(ai[0], bi[0])
    y_left = max(ai[1], bi[1])

    # 2、求出交集的右下角点
    x_right = min(ai[2], bi[2])
    y_right = min(ai[3], bi[3])

    # 求出长宽
    w = x_right - x_left
    h = y_right - y_left

    if w < 0 or h < 0:
        return 0
    return w * h


def IoU(a, b):
    """计算交并比
    :param a: a框坐标
    :param b: b框坐标
    :return:
    """
    # 1、做异常处理
    if a[0] >= a[2] or a[1] >= a[3] or b[0] >= b[2] or b[1] >= b[3]:
        return 0.0

    # 2、计算交并比,计算交集,计算并集  交集/并集+epsilon
    area_i = intersection(a, b)
    area_u = union(a, b, area_i)

    return float(area_i) / float(area_u + 1e-6)


if __name__ == '__main__':
    # 假设一个图片10 x 10的大小,左上角(0, 0) 右下角(10, 10)
    # A框:(1, 1, 5, 5),B框:(3, 3, 6, 6)
    a = (1, 1, 5, 5)
    b = (1, 1, 6, 6)
    print("交并比为:%f" % IoU(a, b))

空洞卷积


CNN 基础


CNN 网络

ResNet结构并分析其在计算机视觉方面取得成功的原因
Resnet通过引入残差单元来解决退化问题。
结构:
(1)通过增加 恒等快捷连接(identity shortcut connection)实现,直接跳过一个或多个层。优势是残差映射在实际中往往更容易优化。
(2)Resnet网络中短路连接shortcut的方式考虑到x的维度与F(X)维度可能不匹配情况,需进行维度匹配。通常采用两种方法解决这一问题。
	zero_padding(零填充):对恒等层进行0填充的方式将维度补充完整。这种方法不会增加额外的参数
	projection(投射):在恒等层采用1x1的卷积核来增加维度。这种方法会增加额外的参数
(3)bottleneck 实现方式
	使用1x1的卷积层来降维,最后一层使用1x1的卷积层来进行升维
(4)激活函数移动到残差部分可以提高模型的精度

1.一个残差单元中输入数据分两路汇合作为输出数据,其中一路数据是常见的经过两个卷积层运算后的结果,
  而另一路数据直接就是输入数据,这个路线被称为shortcut connections(快捷连接)。
2.随着网络的加深,模型不但没有变得更好,反而变差了,并不是因为发生了过拟合,
  因为即使通过使用dropout以及加大训练数据等方法均都并不能很好地解决这个问题;
  同时也不能说是网络过深导致梯度传播的衰减,因为已经有很多行之有效的方法来避免这个问题了;
  同时也不能说是网络过深导致后面的一些网络层根本没有什么用,如果说起作用的只是前面的一些网络层,
  那么这个很深的网络也就退化成了一个较浅的网络,但这样是不对的,因为即便退化成了较浅的网络,
  这个很深的神经网络与较浅的神经网络相比预测误差应该差不多,但是从实验来看这个误差反而变大了。
3.综上所述,导致更深的网络预测误差反而变大了的可能原因就是:
	这个更深的网络后面的网络层没有学习到恒等映射(identity mapping),则是学习到一些非恒等映射而导致引入了误差。
	所谓恒等映射是指输入和输出是一样的,即y=H(x)=x,更通俗地说就是这个网络层什么都没有干。
	那么,我们就可以得到一个想法,假如一个足够深度的m层神经网络,其起作用的只是前n层(n<<m),
	其后面的(m-n)层网络层只需要老老实实地什么都不干就可以了,那么这个神经网络理论上讲就具有拟合任何函数的能力。
	但是,一个令人头痛的问题就是后面的(m-n)层网络层并不会老老实实地什么都不干,它们学习到了非恒等变换的映射关系,
	就会为神经网络引入误差,从而导致模型变坏。因此,如果我们找到了一种使后面的网络层老老实实地执行恒等映射的方法,
	就可以实现网络结构的不断加深。
	残差单元恰恰就是这样的一种方法,通过引入shortcut connections(快捷连接)即直接加入了输入数据x(identity)来实现恒等映射。
4.残差是指预测值与观测值之间的差异,误差是指观测值和真实值之间的差异,这两个概念经常容易混淆。


目标检测


RCNN

3.CNN训练
	AlexNet在imagenet上训练的CNN作为预训练模型,然后将该网络的最后一个fc层的1000(AlexNet的Softmax输出1000维向量)改为
	(论文测试的数据集是20类目标object+背景background)N+1(N为类别的数目,1是1个背景)来fine-tuning微调模型用于提取4096维的特征。
	将候选区域与人工标注的真实检测框大于0.5的IOU作为正样本,小于0.5的作为负样本。

4.SVM分类器训练
	1.目的:训练N(N为类别数)个svm分类器,分别对每一个类别做一个二分类。
	2.一张图片的2000个侯选区域,那么提取出来的就是2000*4096维特征向量(R-CNN当中默认CNN层输出4096特征向量,即AlexNet网络输出层维度为4096)。
	3.R-CNN选用SVM进行二分类。假设检测20个类别,那么会提供20个不同类别的SVM分类器,每个分类器都会对2000个候选区域的4096维特征向量分别判断一次,
           这样得出[2000, 20]的得分矩阵。
	4.分类训练正负样本:
		进行正负样本的区分,将候选区域与人工标注的真实检测框IoU的值进行比较,作者是将大于0.5的IoU作为正样本,小于0.3的IoU作为负样本,
		至于为什么这里不是0.5,当设置为0.5的时候,mAP下降5%,设置为0的时候下降4%,最后取中间0.3。
		为什么这样么选择IoU负样本小于0.3的: 因为softmax的负样本(也可以理解为背景样本)是随机选择的即在整个网络中是共享的,
		而svm的负样本是相互独立的,每个类别都分别有自己的负样本,svm的负样本更加的“hard”,所以svm的分类的准确率更高。
	5.每个SVM分类器做的事情:判断2000个候选区域是属于某个类别,还是属于背景。

5.Boundingbox Regression边界框回归器:
	训练一个线性回归模型输入一个通过选择性搜索算法得到的候选区域的特征图去预测一个检测窗口。
	默认认为候选区域和GT真实框之间是线性关系的,通过训练一个线性回归器来对输入的一个候选区域进行调整回归于GT真实框,
	回归用于修正筛选后的候选区域,因为最后筛选出来的候选区域和GT真实框很接近了。
	通过参数学习寻找一种变换能使得候选区域回归调整接近到GT真实框,然后计算回归调整后的候选区域和GT真实框之间的损失。

第一步:
	1.先使用CNN对图片提取2000个候选框的特征值,对每个候选框进行正样本/负样本的标记。
	2.分类的类别是所有类别之上还要加多一个背景类别,源类别数之上再加一。
	3.标记正样本/负样本的标准:候选框与目标真实框的IoU(重合程度)大于0.5标记为正样本,小于0.5标记为负样本,并且把目标真实框的类别目标值赋值到候选框上。
	4.最终还要把这些特征值都保存到本地,供于第二步的SVM分类训练使用。

第二步:
	1.SVM分类器的个数:比如有20个类别就有20个SVM分类器,不包含背景类别。
	2.所有SVM分类器都会对存储在本地的每个候选框的特征值进行分类,有20个SVM分类器的话,那么每个候选框都有20个分类器的打分。
	3.SVM分类器分类的标准:所有类别都分别各自有一个目标真实框,所有类别的SVM分类器都会对每个候选框进行筛选,
	  只有候选框与目标真实框的IoU(重合程度)大于0.5并且被赋值了类别目标值,那么该候选框才会被分类为该类别的正样本,
	  如果与目标真实框的IoU(重合程度)小于0.3的话,那么该候选框会被分类为该类别的负样本,
	  与目标真实框的IoU(重合程度)在0.3到0.5之间的候选框会被丢弃掉,每个候选框都会被所有的SVM分类器进行逐一打分做标记

第三步:
	使用回归器对候选框的锚框点进行线性回归,使得候选框的锚框点接近真实目标框的锚框点的坐标位置


SPPNet

1.SPP-Net引入一种空间金字塔池化(spatial pyramid pooling,SPP)层通过max pooling最大池化来移除对网络固定尺寸的限制。
  SPP层放在最后一个卷积层之后。SPP层对特征进行池化(max pooling最大池化),并产生固定长度的输出,这个输出再喂给全连接层。
  解决了RCNN的缺点:
	当遇到任意尺寸的图像时,都是先将图像适应成固定尺寸,方法包括裁剪和变形。
	裁剪会导致信息的丢失,变形会导致位置信息的扭曲,就会影响识别的精度。
	对于RCNN中的卷积网络来讲都需要输入的图像尺寸固定(比如224×224)。
	这种人为的需要导致面对任意尺寸和比例的图像或子图像时降低识别的精度。

2.R-CNN和SPP-Net中的CNN区别
	1.R-CNN中的CNN
		1.R-CNN是让每个候选区域经过crop/wrap等操作变换成固定大小的图像。
		2.固定大小的图像塞给CNN 传给后面的层做训练回归分类操作。
	2.SPP-Net中的CNN
		1.SPPNet把全图塞给CNN得到全图的feature map特征图。
		2.让SS选择性搜索算法得到候选区域然后与与全图的feature map特征图直接映射,从而得到属于每个候选区域的feature map特征向量(这是映射来的,不需要过CNN)。
		3.每个候选区域的feature map特征向量大小不固定,所以这些特征向量塞给SPP层(空间金字塔变换层),SPP层接收任何大小的输入,
		  然后输出固定大小的特征向量,再塞给下一个FC层。
		4.空间金字塔池化层:
			对AlexNet中的conv5层输出的13*13*256大小的feature map分别做1x1,2x2,4x4的max pooling最大池化操作,
			从而得到1x1x256,2x2x256,4x4x256的特征图,然后把1x1x256,2x2x256,4x4x256的特征图再连接到一起,
			就是(16+4+1)x256=21x256=5376结果,接着把结果输入给下一个全连接层做进一步处理。	
		5.经过映射得到候选区域的特征向量+SPP空间金字塔变换层的转换,简化了计算,速度/精确度也上去了。

3.SPP-Net 和 RCNN 一样需要经过 CNN训练、SVM分类器训练、Boundingbox Regression边界框回归器。
	SPPNet的性能已经得到很大的改善,SPP网络也有显著的缺点。像R-CNN一样,训练过程是一个多级流水线,涉及提取特征,
	使用log损失对网络进行微调,训练SVM分类器,最后拟合检测框回归。特征也写入磁盘。网络之间不统一训练,造成很大的麻烦,
	所以接下来的Fast R-CNN就是为了解决这样的问题。

空间金字塔池化层:
	对AlexNet中的conv5层输出的13*13*256大小的feature map分别做1x1,2x2,4x4的max pooling最大池化操作,
	从而得到1x1x256,2x2x256,4x4x256的特征图,然后把1x1x256,2x2x256,4x4x256的特征图再连接到一起,
	就是(16+4+1)x256=21x256=5376结果,接着把结果输入给下一个全连接层做进一步处理。	


Fast R-CNN

1.首先RoI pooling只是一个简单版本的SPP,目的是为了减少计算时间并且得出固定长度的向量。
	1.首先将整个图片输入到一个基础卷积网络,得到整张图的feature map。
	2.选择性搜索算法的结果区域提案(ROI感兴趣区域)通过映射在整张图的feature map中得到ROI感兴趣区域自己的feature map。
	3.ROI感兴趣区域的feature map通过RoI pooling layer(ROI感兴趣区域池化层)使用max pooling最大池化到一个具有H×W的固定空间范围的小feature map(H和W是超参数),
	  每个H×W固定大小的特征会输入到一系列全连接层,得到一个RoI固定长度的特征向量(此步骤是对每一个候选区域都会进行同样的操作)。
	4.softmax层进行分类(softmax代替了SVM),输出类别有K个类别加上”背景”类。
	5.bounding box regressor边界框回归器。

2.端到端的模型(实则为伪端到端的模型)
	提出了RoI pooling layer(实际为简单版本的SPP),然后把CNN、RoI pooling、分类器、bbox回归都整合到一个模型一起训练。
	但是选择性搜索算法提取区域建议的模块并没有并入到整一个模型中,因此实际为伪端到端模型。	
	Fast R-CNN在微调阶段联合优化Softmax分类器和检测框回归,而不是分别在三个独立的阶段训练CNN、softmax分类器、回归器。

3.在Fast RCNN网络训练中,随机梯度下降(SGD)的小批量是被分层采样的,首先每批量采样N个图像,然后从每个图像采样R/N个RoI,一个批量中的N个图片一共采样R个ROI样本。
  来自同一图像的RoI在向前和向后传播中共享计算和内存。减小N,就减少了小批量的计算。例如,当N=2(一个批量里面2张图)和R=128(一个批量里面采样的ROI总数)时,
  得到的训练方案比从128幅不同的图采样一个RoI(即R-CNN和SPPnet的策略)快64倍。


Faster R-CNN、RPN区域提议网络、FPN特征金字塔

1.真正实现端到端的模型:Faster R-CNN
	抛弃SS(选择性搜索算法),引入RPN网络(实际为全卷积网络)用于生成候选区域。
  	将候选区域生成,特征提取,分类,位置回归都被统一到一个深度网络中。
	Faster R-CNN可以简单地看成是区域生成RPN网络+Fast R-CNN的模型,用区域生成RPN网络来代替Fast R-CNN中的选择性搜索算法。

2.第一步:输入图像输入Faster R-CNN网络,首先进入一个包含有13个conv、13个relu、4个poolling层的CNN网络,论文中CNN输出的特征图Feature Map为60x40x512。
3.第二步:60x40x512的Feature Map然后进入RPN网络后,首先经过一次3*3滑动窗口卷积核,得到输出的特征图大小依然是60x40x512。
	 3*3滑动窗口卷积核上的中心点映射到原图上的某一点,然后将原图上的这一点分别作为k=9种anchors锚框的中心点。
	 对于大小为WxH的卷积特征图,特征图中的每个像素点均有为k=9种锚框,总共有WxHxK个anchor锚框。
	 Anchors锚框这种方法具有平移不变性,就是说在图像中平移了物体,Anchors锚框也会跟着平移。
4.第三步:接着输入60x40x512分别平级执行两个1x1的卷积。一个是1x1x18,一个是1x1x36,均是kernel_size=1*1,p=0,stride=1。
	 60x40x512经过1x1x18输出60x40x18然后进入分类层得到60x40x9x2,最终得到前景/背景的二分类概率。
	 60x40x512经过1x1x36输出60x40x36然后进入回归层得到60x40x9x4,最终得到预测锚框(候选区域)的坐标位置值。
5.RPN网络中的分类层:softmax的二分类层对k=9种anchors锚框进行分类为是包含目标的正样本或不包含目标的背景负样本。
  RPN网络中的回归层:通过回归使正样本候选框相对于GT真实目标框进行偏移位置计算,最终回归输出预测候选框。
6.RPN中的回归实质:
	RPN网络中bounding-box回归的实质其实就是计算出预测窗口。这里以anchor锚框为基准,计算Ground Truth对其anchor锚框的平移缩放变化参数。
	在真正去计算回归损失的时候,预测值和目标值之间会有一个变化。因为是以anchor窗口为基准,所以只要使这预测值和目标值越接近,
	以此构建目标函数求最小值,那预测窗口就越接近Ground Truth,达到回归的目的。
	因此这可以认为是一个从anchor锚框到附近Ground Truth的bounding-box回归,
	也即通过anchor锚框预测边界框(bounding boxes)bbox然后回归调整接近Ground Truth(GT)真实框以此构建回归的目标函数求最小值。

7.RPN网络最终生成的预测候选区域输入到Fast R-CNN中的ROI感兴趣区域池化层(简单版本的SPP),后面也全部是Fast R-CNN的步骤了。
	使用max pooling最大池化到一个具有H×W的固定空间范围的小feature map(H和W是超参数)

8.共享卷积训练
	论文开发了一种实用的4步训练算法,通过交替优化来学习共享的特征。
	第一步:(先训练CNN和RPN网络)依上述训练RPN,该CNN网络用ImageNet预训练的模型进行初始化,并端到端训练微调用于提出区域建议任务。
	第二步:(再训练CNN、Fast R-CNN、ROI感兴趣区域池化层、FC层)由Fast R-CNN利用第一步的RPN生成的建议框来训练一个单独的检测网络,
		这个检测网络同样是由ImageNet预训练的模型来进行初始化的,这时候RPN和Fast R-CNN两个网络还没有共享卷积层。
	第三步:(固定CNN网络中的参数,继续训练微调RPN)用Fast R-CNN的检测网络(这个网络同样是由ImageNet预训练的模型来进行初始化的)来初始化RPN网络进行训练微调,
		但去固定共享的CNN卷积层的参数,并且只微调RPN独有的层,现在RPN和Fast R-CNN两个网络共享CNN卷积层了。
	第四步:继续保持共享的CNN卷积层的参数固定,利用第三步RPN网络生成的新候选区域(anchor boxes锚框的回归预测框)来微调Fast R-CNN中的FC全连接层。
		这样,RPN和Fast R-CNN两个网络共享相同的CNN卷积层,构成一个统一的网络。

1.全卷积网络
 	全卷积网络,模型由卷积层、池化层组成(没有全连接层),可以接受任意大小的输入。
		过程:输入一张图片,网络由浅到深,随着卷积层和池化层不断作用,产生的特征图分辨率越来越小,但是通道数会越来越多。
		最后通过逐层上采样得到一个和输入形状一样的结果。
	全卷积(convolutional):采样端对端的卷积网络,将普通分类网络的全连接层换上对应的卷积层(FCN)。
	上采样(upsample):即反卷积(deconvolution),恢复图片的位置信息等,反卷积层可以通过最小化误差学习得到。
	跳跃连接(skip layer):通过连接不同卷积层的输出到反卷积层,来改善上采样很粗糙的问题。

	1.转置卷积 Conv2DTranspose 可被称为 反卷积、后卷积、分数步长卷积(fractionally-strided convolution)。
	2.在模型设计中,转置卷积层常⽤于将较小的特征图变换为更⼤的特征图。
	  在全卷积⽹络中,当输⼊是⾼和宽较小的特征图时,转置卷积层可以⽤来将⾼和宽放大到输⼊图像的尺⼨。
	3.转置卷积层可以放⼤特征图。在图像处理中,我们有时需要将图像放大,即上采样(upsample)。上采样的⽅法有很多,常用的有双线性插值。
  	  在全卷积⽹络中,我们将转置卷积层初始化为双线性插值的上采样。
	4.反卷积/转置卷积Conv2DTranspose
		反卷积是一种特殊的正向卷积,先按照一定的比例通过补0来扩大输入图像的尺寸,接着卷积核卷积,再进行正向卷积。
		先进行上采样,即扩大像素;再进行卷积,优点是通过参数学习达到up-sample效果会比插值方法更好
		反卷积应用:主要用来还原feature map的尺寸大小,在分割等领域会使用来还原图像大小。
	5.空洞卷积
		采用的atrous(带孔)算法扩展感受野,获取更多的上下文信息,相当于在标准概念的kernel(卷积核)中,相邻点之间添加(rate - 1)个0。
		扩张的好处是不做pooling损失信息的情况下,加大了感受野,让每个卷积输出都包含较大范围的信息。
		应用:空洞卷积通常应用在分割等low-level视觉任务中,比如分割任务、姿态估计等。

2.maskrcnn中的RPN网络
	1.maskrcnn中的RPN网络
		先对主干网络resnet101输出的每个特征图中的每个像素生成3个候选框,然后通过RPN网络比较所有候选框与GT目标进行IoU判断,
    		标记256个正负样本继续用于RPN网络训练,RPN网络实际做的是softmax二分类层(包含目标/不包含目标的背景)实现cls层,
    		用logistic回归对正样本候选框和GT目标框继续进行偏移值计算最终回归输出预测框实现reg层。
    		最终RPN网络输出200个正负样本候选框(包含目标/不包含目标的背景)提供给mrcnn进行训练,正样本占其中全部样本的的比率是0.3。
 
	2.maskrcnn网络
    		200个正负样本候选框分别输入到cls分类层(每个ROI区域Softmax多分类分配GT目标类别)、reg回归层(检测框回归调整接近GT目标框)、mask分支,
    		mask通过像素级Sigmoid和二值化损失的手段对每个ROI区域中的每个像素进行Sigmoid二分类输出,判断每个像素是否属于ROI区域所分配的GT目标类别。

1.第一步:输入图像输入Faster R-CNN网络,首先进入一个包含有13个conv、13个relu、4个poolling层的CNN网络,论文中CNN输出的特征图Feature Map为60x40x512。
2.第二步:60x40x512的Feature Map然后进入RPN网络后,首先经过一次3*3滑动窗口卷积核,得到输出的特征图大小依然是60x40x512。
	 3*3滑动窗口卷积核上的中心点映射到原图上的某一点,然后将原图上的这一点分别作为k=9种anchors锚框的中心点。
	 对于大小为WxH的卷积特征图,特征图中的每个像素点均有为k=9种锚框,总共有WxHxK个anchor锚框。
	 Anchors锚框这种方法具有平移不变性,就是说在图像中平移了物体,Anchors锚框也会跟着平移。
3.第三步:接着输入60x40x512分别平级执行两个1x1的卷积。一个是1x1x18,一个是1x1x36,均是kernel_size=1*1,p=0,stride=1。
	 60x40x512经过1x1x18输出60x40x18然后进入分类层得到60x40x9x2,最终得到前景/背景的二分类概率。
	 60x40x512经过1x1x36输出60x40x36然后进入回归层得到60x40x9x4,最终得到预测锚框(候选区域)的坐标位置值。
4.RPN网络中的分类层:softmax的二分类层对k=9种anchors锚框进行分类为是包含目标的正样本或不包含目标的背景负样本。
  RPN网络中的回归层:通过logistic回归使正样本候选框相对于GT真实目标框进行偏移位置计算,最终回归输出预测候选框。
5.RPN中的回归实质:
	RPN网络中bounding-box回归的实质其实就是计算出预测窗口。这里以anchor锚框为基准,计算Ground Truth对其anchor锚框的平移缩放变化参数。
	在真正去计算回归损失的时候,预测值和目标值之间会有一个变化。因为是以anchor窗口为基准,所以只要使这预测值和目标值越接近,
	以此构建目标函数求最小值,那预测窗口就越接近Ground Truth,达到回归的目的。
	因此这可以认为是一个从anchor窗口到附近Ground Truth的bounding-box回归。
6.RPN网络最终生成的预测候选区域输入到Fast R-CNN中的ROI感兴趣区域池化层(简单版本的SPP),后面也全部是Fast R-CNN的步骤了。
	使用max pooling最大池化到一个具有H×W的固定空间范围的小feature map(H和W是超参数)


yolo、FPN特征金字塔

1.yolo网络结构:
	yolo网络结构分为两部分,分类模型和检测模型。
	1.yolo v1:
		检测模型部分为448*448的输入,前面有24个卷积层,最后面是2个全连接层。
		只使用1×1降维层,后面是3×3卷积层,全连接层输出7×7×30的特征图。
 	2.快速版的YOLO:
		较少卷积层(9层而不是24层)的神经网络,在这些层中使用较少的滤波器。
	  	yolo v1和快速版YOLO网络的最终输出都是7×7×30的预测张量。
	3.yolo v2:
		1.缩减了网络,所有卷积层上添加批量标准化,检测模型部分为416x416的输入,移除了全连接层,最终输出13x13的特征图。
		  由于仅使用卷积层和池化层,移除了全连接层,因此能够在不同尺寸的图像上运行,可以实时调整大小将多尺度训练应到模型中。
		2.引入Anchor机制使用锚框来预测边界框:
			检测模型输出13x13的特征图,映射到原图则为被切分成13x13的网络单元。
			13x13特征图中每个像素对应的每个单元格预测5个锚框anchor box,每个锚框都预测一个bbox边界框的位置信息、置信度和分类概率值。
			也即每个单元格上通过5个anchor锚框预测5个边界框bbox,YOLOv2可以预测13x13x5=845个边界框。
			以anchor锚框为基准,计算Ground Truth(GT)真实框对其anchor锚框的平移缩放变化参数,
			然后通过anchor锚框预测边界框(bounding boxes)bbox通过回归调整接近Ground Truth(GT)真实框以此构建回归的目标函数求最小值。
			在计算回归损失的时候,因为是以anchor窗口为基准来预测边界框bbox,所以要使预测边界框bbox和GT真实框足够接近,
			以此来构建目标函数求最小值,达到回归的目的。
		3.高分辨率分类器:
			1.分类模型:先用224x224的输入在ImageNet数据集训练分类网络,然后将输入调整到448x448继续在ImageNet数据集训练分类网络。
			2.检测模型:利用预训练得到的模型在检测数据集上fine-tuning微调。
		4.采用标准的k-means聚类实现边界框boxes尺寸维度聚类
			Faster-RCNN中的锚框anchor boxes的个数和宽高维度往往是手动精选的先验框,YOLOv2使用k-means聚类算法对训练集中的边界框做了聚类分析,
			尝试找到合适尺寸的Anchor,一开始就选择了更好的、更有代表性的先验boxes维度,那么网络就应该更容易学到准确的预测位置。
			由于我们限制bbox边界框的位置信息为单元格内的偏移量预测,因此参数化更容易学习,从而使网络更加稳定,使用维度聚类并直接预测边界框中心位置。
			希望的是误差和边界框boxes尺寸大小没有太大关系,所以通过IOU定义了如下的距离函数,使得误差和边界框boxes尺寸大小无关:

		5.细粒度功能
			不单只在13×13特征图上预测检测结果,这对于大型物体的检测是足够的,还增加从较早的层中提取26×26的分辨率特征,
			这可以增加更细粒度特征对定位较小物体有好处。实现:添加一个直通层将高分辨率特征与低分辨率特征连接起来,
			将相邻特征叠加到不同的通道中,而不是空间位置上,类似于ResNet中的恒等映射,
			即把在较早的层中所提取出来的26×26分辨率特征从26×26×512=346112的特征图变为13×13×2048=346112的特征图。
		6.多尺度训练			
			由于仅使用卷积层和池化层,移除了全连接层,因此yolo v2能够在不同尺寸的图像上进行读取训练,
			可以实时调整大小将多尺度图像训练应用到模型中。每隔几个批次迭代就改变一次网络,比如每10个批次网络会随机选择一个新的图像尺寸大小。
			由于模型缩减了32倍,所以从32的倍数中抽取:{320,352,…,608},因此,最小的选项是320×320,最大的是608×608。
	4.yolo v3:
		1.特征金字塔(FPN网络)
			1.yolo V3使用了特征金字塔(FPN网络),在13x13、26x26、52x52 一共3个不同大小的特征图上做bbox预测。
			2.3个不同大小的特征图上的每个像素点映射到原图中的每个单元格cell 均使用3种(默认)不同尺寸的锚框来预测bbox(边界框bounding boxes)。
			  每种不同尺寸的锚框Anchor boxes所预测的bbox(边界框bounding boxes)包含:
			  4个预测位置(x、y、w、h)、1个bbox置信度分数confidence scores、M个分类类别的概率值。
			3.那么一个NxN的特征图映射原图就有NxN个网格单元cell,那么这个NxN的特征图(NxN个网格单元)预测的数据量为NxNx(3x(4+1+M个分类类别的概率值))。
			  yolo V3分别在13x13、26x26、52x52 一共3个特征图做bbox预测,设置13x13为NxN的话,那么26x26为2x(NxN),52x52为4x(NxN),
			  那么3个不同尺度特征图一共预测的数据量为(NxN + 2x(NxN) + 4x(NxN)) x (3x(4+1+N个分类类别的概率值))
		2.使用二分类的逻辑回归代替了softmax来作为分类器,并使用二分类交叉熵作为损失。
		3.引入了残差模块,并进一步加深了网络,改进后的网络有53个卷积层,命名为Darknet-53。

	5.YOLO V3 Tensorflow2.0源码分析
		YOLOv3 的网络结构由基础特征提取网络、多尺度特征融合层和输出层组成。
		1.YOLOv3引入了残差模块,并进一步加深了网络,改进后的网络有53个卷积层,命名为Darknet-53。
		  特征提取网络:
			YOLOv3使用DarkNet-53作为特征提取网络:DarkNet-53 基本采用了全卷积网络,用步长为2的卷积操作替代了池化层,
			同时添加了 Residual残差单元,避免在网络层数过深时发生梯度弥散。

		2.YOLOv3借鉴了FPN的思想,从不同尺度提取特征。
		  特征融合层:
			为了解决之前YOLO版本对小目标不敏感的问题,YOLOv3采用了3个不同尺度的特征图来进行目标检测,
			分别为13x13,26x26,52x52,用来检测大、中、小三种目标。特征融合层选取Darknet-53产出的三种尺度特征图作为输入,
			借鉴了FPN(feature pyramid networks)的思想,通过一系列的卷积层和上采样对各尺度的特征图进行融合。
		3.输出层:
			同样使用了全卷积结构。3x(20+4+1)=75表示一个grid cell单元格预测的3个bounding box,4表示框的4个坐标信息,
			1表示Confidence Score,20表示VOC数据集中20个类别的概率。如果换用别的数据集,20可以更改为实际类别数量。
		
2.yolo v1输出7x7的特征图映射到原图中的7x7=49个网格单元cell中,yolo v2输出13x13的特征图映射到原图中的13x13=169个网格单元cell中
  那么这些yolo网络中的每个网格单元预测目标的流程:
	1.原始图片resize到448x448,经过yolo v1的24个卷积层/快速版的YOLO的9个卷积层之后,将图片输出成了一个7*7*30的特征图。
	  yolo v1网络输出为7x7的特征图,那么即是把输入原图切分成7x7=49个网格单元cell。
	2.yolo v1的输入原图中的7x7=49个网格单元cell
		7x7=49个像素值,理解成49个单元格,每个单元格可以代表原图的一个方块。
		每个网格单元cell都会预测N个边界框bounding boxes、每个bbox框对应的1个置信度分数confidence scores、M个类别的概率值。
	3.每个bbox框对应的1个置信度分数confidence scores
		1.如果目标的中心点落到49个网格单元中的某个网格单元cell中,那么该网格就负责检测该目标。
		  判断一个网格单元中是否包含目标,首先看一个图片中真实目标的ground truth(GT真实框)的中心点坐标是在哪一个grid cell中。
		  如果某个真实目标的ground truth(GT真实框)的中心点坐标在这一个网格单元中的话,
		  那么也就是说这个真实目标的预测就由这一个网格单元所预测bbox(边界框bounding boxes)来负责。
		  注意:如果多个目标物体的ground truth(GT真实框)的中心点坐标都出现在同一个单元格cell中的话,那么并不建议使用yolo V1,
 		        因为yolo V1中每个网格所预测的2个bbox中最终只会有1个bbox用于预测目标物体,yolo V1的每个单元格都只能预测一个物体。
		2.一个网格单元会预测N个bbox(边界框bounding boxes),如果决定了由这一个单元格来负责预测真实目标的话,
		  那么会通过N个bbox对应的各自的置信度分数confidence scores来进行比较由哪个bbox来负责预测。
		3.置信度分数confidence scores评估标准:
			这些置信度分数反映了该模型对那个框内是否包含目标的信心,以及它对自己的预测的准确度的估量。
			1.比如yolo V1中的每个单元格会预测2个bounding box,那么会由其中一个bbox来预测目标,前提是这个单元格包含物体。
			  包含目标的某一个单元格所预测的2个bounding box分别与ground truth(GT真实框)的IOU哪个更大,
			  那么IOU最大的这一个bbox更接近目标的GT真实框,那么就由这一个bounding box来负责预测该对象是否存在。
			2.计算confidence score公式:
				1.如果单元格中不包含目标,那么这一个单元格所预测的N个bbox对应的confidence scores均为0。
				2.如果单元格中包含目标,那么某个bbox的confidence score 等于 预测的bbox和ground truth(GT真实框)的IOU乘积。
				  那么负责预测该目标的bbox与ground truth(GT真实框)的IOU的最大值为1。
				3.计算置信度分数confidence scores公式:

	4.M个类别的概率值
		1.所预测的类别概率值实际为类别的条件概率值。
		  类别的条件概率值中的条件指的是这个单元格包含物体的前提下,那么预测这个物体分别是M个类别中每一个类别的概率。
		2.联合概率、条件概率与相互独立
			1.联合概率:包含多个条件,且所有条件同时成立的概率
			  记作:P(A,B)
			2.条件概率:就是事件A在另外一个事件B已经发生条件下的发生概率
			  记作:P(A|B)
			  例子:P(程序员|喜欢):在女神喜欢的条件下,职业是程序员的概率?
			3.相互独立:如果P(A, B) = P(A)P(B),则称事件A与事件B相互独立。
		3.比如yolo v1中每个单元格所预测的20个类别概率值实际预测属于这个单元格的类别概率值,并不是预测属于这个bbox的类别概率值。
		4.并不会直接使用单元格所预测的类别的条件概率值,而是通过计算类别的条件概率值和每个bbox框预测的置信度分数相乘得到每个bbox框的特定类别的置信度分数。
		  这些bbox框的特定类别的置信度分数体现了某类别出现在某bbox框中的概率以及预测框拟合目标的程度。
		  计算每个bbox框的特定类别的置信度分数公式:

	5.非最大抑制(NMS)
		得到每个bbox框的特定类别的置信度分数之后,首先设置阈值过滤掉分数低的bbox预测框,然后对过滤后剩余的bbox预测框进行非最大抑制(NMS)处理。
		最终便得到预测为某类别的bbox预测框。

3.yolo V1、yolo V2、yolo V3 的bbox(边界框bounding boxes)数目变化
	1.yolo V1:
		1.每个网格单元cell预测2个(默认)bbox(边界框bounding boxes):
			yolo网络输出的7x7的特征图把输入原图切分成7x7=49个网格单元,那么输入图像一共有 7x7x2=98个bbox(边界框bounding boxes)。
		2.每个网格单元就要预测2个(默认)bbox(边界框bounding boxes),那么一个网格单元要预测的数据量就是 2x(4+1)+20=30。
		  7x7=49个网格单元一共预测的数据量:7x7x(2x(4+1)+20)=1470。
			2:每个网格单元预测的2个(默认)bbox(边界框bounding boxes)。
			4+1:每个bbox(边界框bounding boxes)包含 4个预测位置(x、y、w、h)和1个bbox置信度分数confidence scores。
			20:所预测的20个类别概率值实际预测属于这个单元格的类别概率值,并不是预测属于这个bbox的类别概率值。
			    所预测的类别概率值实际为类别的条件概率值。类别的条件概率值中的条件指的是这个单元格包含物体的前提下,
			    那么预测这个物体分别是M个类别中每一个类别的概率。并不会直接使用单元格所预测的类别的条件概率值,
			    而是通过计算类别的条件概率值和每个bbox框预测的置信度分数相乘得到每个bbox框的特定类别的置信度分数。
		             这些bbox框的特定类别的置信度分数体现了某类别出现在某bbox框中的概率以及预测框拟合目标的程度。
		3.yolo V1的缺点:
			正因为yolo V1中每个网格所预测的2个bbox中最终只会有1个bbox用于预测目标物体,即每个单元格cell只会预测1个目标物体,
			如果多个目标物体的ground truth(GT真实框)的中心点坐标都出现在同一个单元格cell中的话,那么并不建议使用yolo V1,
			因为yolo V1的每个单元格都只能预测一个物体。

	2.yolo V2:
		1.每个网格单元cell都使用5种(默认)不同尺寸的锚框Anchor boxes来预测bbox(边界框bounding boxes),
		  一个网格单元cell中每种不同尺寸的锚框Anchor boxes各预测一个bbox(边界框bounding boxes),一共预测5个(默认)bbox(边界框bounding boxes)。
		  输入图像一共预测有 13x13x5=845个bbox(边界框bounding boxes)。
		  输入图像一共预测的数据量(假如预测20个类别和在13x13特征图上做预测):13x13x(5x(4+1+20))=169*125=21125
		  注意:5个(默认)的锚框Anchor boxes的尺寸大小都是不一样的。
		2.每种不同尺寸的锚框Anchor boxes所预测的bbox(边界框bounding boxes)包含:4个预测位置(x、y、w、h),1个bbox置信度分数confidence scores,
		  N个分类类别的预测概率值。
		3.一个网格单元cell中5种(默认)不同尺寸的锚框Anchor boxes所预测的5个(默认)bbox(边界框bounding boxes)一共预测的数据量(假如预测20个类别):
			5x(4+1+20)=125
				1.5代表5个(默认)bbox(边界框bounding boxes)。
				2.每个bbox(边界框bounding boxes)都分别有4个预测位置(x、y、w、h),1个bbox置信度分数confidence scores,20个类别的预测概率值。
				3.所预测的20个类别概率值实际预测属于这个单元格的类别概率值,并不是预测属于这个bbox的类别概率值。
			    	  所预测的类别概率值实际为类别的条件概率值。类别的条件概率值中的条件指的是这个单元格包含物体的前提下,
			    	  那么预测这个物体分别是M个类别中每一个类别的概率。并不会直接使用单元格所预测的类别的条件概率值,
			    	  而是通过计算类别的条件概率值和每个bbox框预测的置信度分数相乘得到每个bbox框的特定类别的置信度分数。
		             	  这些bbox框的特定类别的置信度分数体现了某类别出现在某bbox框中的概率以及预测框拟合目标的程度。
		4.YOLO V2基于卷积的Anchor机制(Convolutional With Anchor Boxes):
			移除了全连接层,并使用5个(默认)不同尺寸的锚框Anchor boxes来预测bbox(边界框bounding boxes)。
		  	YOLO V2通过缩减网络,使用416x416的输入,模型下采样的总步长为32,最后得到13x13的特征图,
		  	13x13的特征图对应在输入原图分割13x13个单元格cell。
		  	每个单元格cell预测5个不同尺寸锚框anchor boxes对应的bbox(边界框bounding boxes),
			每个锚框anchor box所预测的bbox(边界框bounding boxes) 包含4个位置信息、1个置信度、N个分类类别的概率值。
		  	YOLO V2采用的5种不同尺寸锚框Anchor boxes可以预测13x13x5=845个bbox(边界框bounding boxes)。
		  	YOLO V2引⼊faster rcnn中anchor机制,anchor尺度就是用来预测网络预测值和目标GT做尺度变换的。

	3.yolo V3:
		1.特征金字塔(FPN网络)
			1.yolo V3使用了特征金字塔(FPN网络),在13x13、26x26、52x52 一共3个不同大小的特征图上做bbox预测。
			2.3个不同大小的特征图上的每个像素点映射到原图中的每个单元格cell 均使用3种(默认)不同尺寸的锚框来预测bbox(边界框bounding boxes)。
			  每种不同尺寸的锚框Anchor boxes所预测的bbox(边界框bounding boxes)包含:
			  4个预测位置(x、y、w、h)、1个bbox置信度分数confidence scores、M个分类类别的概率值。
			3.那么一个NxN的特征图映射原图就有NxN个网格单元cell,那么这个NxN的特征图(NxN个网格单元)预测的数据量为NxNx(3x(4+1+M个分类类别的概率值))。
			  yolo V3分别在13x13、26x26、52x52 一共3个特征图做bbox预测,设置13x13为NxN的话,那么26x26为2x(NxN),52x52为4x(NxN),
			  那么3个不同尺度特征图一共预测的数据量为(NxN + 2x(NxN) + 4x(NxN)) x (3x(4+1+N个分类类别的概率值))

		2.每种不同尺度特征图上所设置的先验框(bbox边界框bounding boxes)大小,
		  会从下面的array数组yolo_anchors中选出对应合适的组合作为先验框(bbox边界框bounding boxes)的大小。
			yolo_anchors = np.array([(10, 13), (16, 30), (33, 23), (30, 61), (62, 45), (59, 119), (116, 90), (156, 198), (373, 326)], 
					  np.float32) / 416
						  
4.预测bbox位置:通过回归offset 代替 直接回归坐标	  					  
	1.每个bbox(边界框bounding boxes)的预测数据量:4个预测位置(x、y、w、h)、1个bbox置信度分数confidence scores、N个类别的预测概率值。
	  预测的bbox的4个预测位置(x、y、w、h)都是相对于正在处理的网格单元进行计算而言的。
 
	2.(x, y) 
		1.预测的bbox的(x, y) 
			(x, y)表示bbox的中心点相对于单元格(grid cell)原点的偏移值,单元格(grid cell)的原点即为该单元格的左上角顶点坐标(top-left)。
	 	  	yolo将单元格的左上角的top-left顶点(原点)设置为(0, 0),右下角的bottom-right顶点设置为(1, 1),所以x和y的取值范围都分别在0到1之间。
	  	  	x和y将始终介于0到1之间,因为bbox的中心点始终位于该单元格(grid cell)之内。
	  	  	之所以把(x, y)预测为bbox中心点相对于单元格原点的位置坐标,是因为可以使得计算界限在0到1的值之间,也使得更加容易学习,从而使网络更加稳定。
		2.yolo输出层输出的(bx, by) 
			把预测的bbox的(tx, ty)转换为yolo输出层输出的(bx, by)。
			σ读作sigma。Cx和Cy分别为当前单元格(grid cell)距离输入原图的左上角原点的边距离。W和H为输入原图像的宽和高。分别除以W和H,目的是归一化。
			σ(tx) + Cx:边界框的中心点在输入原图像中的x坐标,也即边界框的中心点离输入原图像原点的x方向长度
		  	σ(ty) + Cy:边界框的中心点在输入原图像中的y坐标,也即边界框的中心点离输入原图像原点的y方向长度
			tx->bx:bx = (σ(tx) + Cx) / W
			ty->by:by = (σ(ty) + Cy) / H
			 (bx, by) 相对于整张图片的宽和高, 通过图像宽度和高度来规范边界框的中心点坐标,即使用图片的宽和高标准化自己, 使之取值范围也在(0, 1)之间。
	3.(w, h) 
		1.预测的bbox的(w, h)
			(w, h)分别为bbox边界框的高度与相应单元网格的高度之比、bbox边界框的宽度与相应单元网格的宽度之比。
		  	根据所预测的bbox(边界框bounding boxes)是大于还是小于单元格(grid cell)的尺寸来决定(w, h)的取值范围是大于1还是在0到1之间。
	  	  	如果边界框bbox的尺寸小于单元格(grid cell)的尺寸的话,w和h的取值范围都分别是在0到1之间。
	  	  	如果边界框bbox的尺寸大于单元格(grid cell)的尺寸的话,w和h的取值范围都可以大于1。
 		2.yolo输出层输出的(bw, bh)
			把预测的bbox的(tw, th)转换为yolo输出层输出的(bw, bh)。
			pw和ph分别为手动设定的锚框Anchor boxes宽和高。
		  	pw * e^tw:边界框在输入原图像中的宽度
		  	ph * e^th:边界框在输入原图像中的高度
			tw->bw:bw = (pw * e^tw) / W
			th->bh:bh = (ph * e^th) / H
			 (bw, bh) 相对于整张图片的宽和高, 通过图像宽度和高度来规范边界框的宽度和高度,即使用图片的宽和高标准化自己, 使之取值范围也在(0, 1)之间。
 
	4.yolo V2、yolo V3都基于卷积的Anchor机制(Convolutional With Anchor Boxes)
		yolo V2使用5种不同尺寸的锚框Anchor boxes预测一共5个边界框的4个位置信息、1个置信度、N个分类类别的概率值。
		yolo V3使用3种不同尺寸的锚框Anchor boxes预测一共3个边界框的4个位置信息、1个置信度、N个分类类别的概率值。

	5.anchor尺寸就是用来预测网络预测值和目标GT之间做尺度变换的。
	  比如下面的蓝色框是锚框Anchor boxes预测的bbox(边界框bounding boxes),黑色点的矩形框是锚框Anchor boxes。
	  每一个锚框Anchor boxes预测的bbox(边界框bounding boxes)都包含 tx、ty、tw、th、to(置信度)。
	  如果这个单元格(grid cell)距离输入原图的左上角原点的边距离为(cx,cy),该单元格(grid cell)对应的边界框bbox维度(边界框优先bounding box prior)的
	  长和宽分别为(pw,ph),pw和ph实际即为手动设定的锚框Anchor boxes宽和高,那么对应的边界框bbox计算结果实际为:
		1.yolo V2/yolo V3中不同尺寸的锚框Anchor boxes所预测的bbox(边界框bounding boxes)的4个位置信息为(tx, ty, tw, th),
		  那么tx和ty分别为相对于单元格(grid cell)原点的0到1之间取值的值,tw和th则根据所预测的bbox(边界框bounding boxes)是大于还是小于
		  单元格(grid cell)的尺寸来决定tw和th的取值范围是在0到1之间还是在大于1。
		2.pw和ph分别为手动设定的锚框Anchor boxes宽和高,而yolo网络最终计算的预测结果为(bx, by, bw, bh),
		  因此需要把预测的bbox的位置信息(tx, ty, tw, th)转换为yolo输出层的最终输出的位置信息(bx, by, bw, bh)。
		3.把(tx, ty, tw, th)转换为(bx, by, bw, bh)作为yolo输出层的最终输出:
			σ读作sigma。Cx和Cy分别为当前单元格(grid cell)距离输入原图的左上角原点的边距离。W和H为输入原图像的宽和高。分别除以W和H,目的是归一化。
			tx->bx:bx = (σ(tx) + Cx) / W
			ty->by:by = (σ(ty) + Cy) / H
			tw->bw:bw = (pw * e^tw) / W
			th->bh:bh = (ph * e^th) / H
		4.σ(tx) + Cx:边界框的中心点在输入原图像中的x坐标,也即边界框的中心点离输入原图像原点的x方向长度
		  σ(ty) + Cy:边界框的中心点在输入原图像中的y坐标,也即边界框的中心点离输入原图像原点的y方向长度
		  pw * e^tw:边界框在输入原图像中的宽度
		  ph * e^th:边界框在输入原图像中的高度

    """
    输出layerOutsputs介绍:
        是YOLO算法在图片中检测到的bbx的信息
        由于YOLO v3有三个输出,也就是上面提到的['yolo_82', 'yolo_94', 'yolo_106']
        因此layerOutsputs是一个长度为3的列表
        其中,列表中每一个元素的维度是(num_detection, 85)
        num_detections表示该层输出检测到bbx的个数
        85:因为该模型在COCO数据集上训练,[5:]表示类别概率;[0:4]表示bbx的位置信息;[5]表示置信度
    下面对网络输出的bbx进行检查:
        判定每一个bbx的置信度是否足够的高,以及执行NMS算法去除冗余的bbx
    """
    # 遍历每个输出层[yolo-82, yolo-94, yolo-106]
    for output in layerOutputs:
        # 遍历某个输出层的检测框结果
        for detection in output:
            # detction检测框:1*85维度的向量。其中[5:]表示类别,[0:4]bbox的位置信息 [4]置信度
            scores = detection[5:] #80个类别的概率值。scores的大小应该是1*80,因为在训练yolo模型时是80类目标
            classID = np.argmax(scores) #获取最大概率值的类别索引值
            confidence = scores[classID] #根据最大概率值的类别索引值 获取出对应的类别
            #如果该最大概率的类别的预测概率值 大于 0.3
            if confidence > 0.3:
                """
                1.pw和ph分别为手动设定的锚框Anchor boxes宽和高,而网络最终计算的预测结果为(bx, by, bw, bh),
                  因此需要把(tx, ty, tw, th)转换为(bx, by, bw, bh)。
                2.把(tx, ty, tw, th)转换为(bx, by, bw, bh)作为yolo输出层的最终输出:
                    σ读作sigma。Cx和Cy分别为当前单元格(grid cell)距离输入原图的左上角原点的边距离。
                    W和H为输入原图像的宽和高。分别除以W和H,目的是归一化。
                    
                        tx->bx:bx = (σ(tx) + Cx) / W
                        ty->by:by = (σ(ty) + Cy) / H
                        tw->bw:bw = (pw * e^tw) / W
                        th->bh:bh = (ph * e^th) / H
                        
                        σ(tx) + Cx:边界框的中心点在输入原图像中的x坐标,也即边界框的中心点离输入原图像原点的x方向长度
                        σ(ty) + Cy:边界框的中心点在输入原图像中的y坐标,也即边界框的中心点离输入原图像原点的y方向长度
                        pw * e^tw:边界框在输入原图像中的宽度
                        ph * e^th:边界框在输入原图像中的高度
                """
                # 将检测结果边界框的坐标还原至与原图片适配,YOLO返回的是边界框的中心坐标以及边界框的宽度和高度
                box = detection[0:4] * np.array([W, H, W, H])
                # 使用 astype("int") 对上述 array 进行强制类型转换
                # centerX:检测框的中心点横坐标, centerY:检测框的中心点纵坐标,width:检测框的宽度,height:检测框的高度
                (centerX, centerY, width, height) = box.astype("int")
                # 计算边界框的左上角的横坐标:检测框的中心点横坐标 - 检测框的宽度/2
                x = int(centerX - width / 2)
                # 计算边界框的左上角的纵坐标:检测框的中心点纵坐标 - 检测框的高度/2
                y = int(centerY - height / 2)
                # 更新检测到的目标框,置信度和类别ID
                # boxes:[边界框的左上角的横坐标, 边界框的左上角的纵坐标, 检测框的宽度, 检测框的高度]
                boxes.append([x, y, int(width), int(height)]) # 将边框的信息添加到列表boxes
                confidences.append(float(confidence)) # 将识别出是某种物体的置信度添加到列表confidences
                classIDs.append(classID) # 将识别物体归属于哪一类的信息添加到列表classIDs


FCN基于全卷积的语义分割、FPN特征金字塔、反卷积(转置卷积)

参数:
1、filters:整数,输出空间的维数(即卷积中输出过滤器的数量)。
2、kernel_size:2个整数或元组/列表,指定2D卷积窗口的高度和宽度。可以是单个整数,那么认为所有空间尺寸指定相同的值。
4、strides:
	一个整数或2个整数的元组/列表,指定沿高度和宽度的卷积步幅。可以是单个整数,那么认为所有空间尺寸指定相同的值。
	指定任何步幅值strides不等于1 与 指定任何dilation_rate值不等于1 之间不兼容。
5、padding:"valid"或"same"(不区分大小写)。
6、output_padding:
	一个整数或2个整数的元组/列表,指定沿输出张量的高度和宽度的填充量。可以是单个整数,那么认为所有空间尺寸指定相同的值。
	沿给定尺寸的输出填充量必须小于沿相同尺寸的步幅。如果设置为None(默认),则推断输出形状。
7、data_format:
	字符串,channels_last(默认)或channels_first。输入中channels的位置顺序。 
	channels_last对应于具有(batch, height, width, channels)形状的输入。channels_first 对应于具有(batch, channels, height, width)形状的输入。
	默认为image_data_format在Keras配置文件中找到的值~/.keras/keras.json。如果您从未设置,那么它将是“channels_last”。
8、dilation_rate:
	一个整数或2个整数的元组/列表,指定用于扩张卷积的扩张率。可以是单个整数,那么认为所有空间尺寸指定相同的值。
	当前,指定任何dilation_rate值不等于1 与 指定任何步幅值strides不等于1 之间不兼容。
9、activation:要使用的激活功能。如果您未指定任何内容,则不会应用任何激活,即线性激活a(x)=x。
10、use_bias:布尔值,层是否使用偏置向量。
11、kernel_initializer:kernel权重矩阵的初始化程序。
12、bias_initializer:偏置矢量的初始化器。


Mask RCNN

1.Mask RCNN解决的是实例分割,主要是把物体检测和语义分割组合在了一起来进行实例分割。
2.Mask RCNN的主干架构使用的是ResNet-101-FPN,并且在Faster R-CNN网络上作修改,包含以下两个阶段。
	1.第1个阶段:
		1.采用ResNet-FPN(特征金字塔)网络结构来提取特征,ResNet-FPN(特征金字塔)中的[P2,P3,P4,P5,P6]5个不同层级输出的特征图作为RPN的输入,
		  每个不同层级输出的特征图上分别使用不同尺度大小的锚框,锚框的尺度大小分别是32^2、64^2、128^2、256^2、512^2,同时也有3种不同长宽比,
		  总共有15种不同尺度的锚框。
		2.特征金字塔每层输出的特征图都接上RPN的predictor head结构(3x3卷积分别输出给2个1x1卷积分别对应RPN的分类层和回归层),
		  RPN做预测框分类和预测框回归目的用于提出候选目标的边界框,然后把RPN预测的候选区域输出给ROI Align。

	2.第2个阶段:
		1.把ROI Pooling层(ROI感兴趣区域池化层)替换成了ROI Align。
		  ROI Align的输入是 ResNet-FPN(特征金字塔)中的[P2,P3,P4,P5]4个不同层级输出的特征图 和 RPN预测的候选区域。
		2.ROI Align在原来做预测框分类和预测框回归的基础上,再增加多了一个二进制mask掩码(1,0)的分支。
		  mask掩码分支基于FCN层(全卷积的语义分割)为每个感兴趣区域生成一个m*m的二进制掩码(1,0)。
3.RPN网络
	先对主干网络resnet101输出的每个特征图中的每个像素生成3个候选框,然后通过RPN网络比较所有候选框与GT目标进行IoU判断,
	标记256个正负样本继续用于RPN网络训练,RPN网络实际做的是softmax二分类层(包含目标/不包含目标的背景)实现cls层,
	用logistic回归对正样本候选框和GT目标框继续进行偏移值计算最终回归输出预测框实现reg层。
	最终RPN网络输出200个正负样本候选框(包含目标/不包含目标的背景)提供给后续网络继续进行训练,正样本占其中全部样本的的比率是0.3。

4.Mask RCNN网络
	1.200个正负样本候选框分别输入到三个分支:
		cls分类层(每个ROI感兴趣区域进行Softmax多分类分配GT目标类别)、reg回归层(检测框进行回归调整接近GT目标框)、mask掩码分支。
    	2.mask掩码分支:
		1.ROI感兴趣区域经过ROI Align输出的特征图分别输出给cls分类层、reg回归层、mask掩码分支。
		  ROI Align输出的特征图通过cls分类层已经由GT目标分配到一个真实类别k,那么同样的特征图输入到mask掩码分支中所输出的m*m*K,
		  就需要对m*m的特征图中的每个像素进行sigmoid二分类判断是否属于分类层所分配的真实类别k,
		  因为ROI感兴趣区域通过分类层已经分配得到了一个真实类别k,那么然后就需要判断ROI感兴趣区域中的每个像素都是否属于所分配的真实类别k。
		2.mask掩码预测分支使用全卷积网络(反卷积结构),每个RoI感兴趣区域(候选区域)输入到mask分支中都会输出预测K个总类别数的m*m的二进制掩码(1,0)
		  即m*m*K的二进制掩码,K代表总类别数,此处即通道数,每个类别都对应一个m*m的二进制掩码(1,0)。
		3.对于一个ROI感兴趣区域默认只代表一个物体的目标类别,假设总类别数为K,那么每个ROI感兴趣区域都会被分配到一个GT真实类别。
  		  一个ROI感兴趣区域之所以只对应一个GT真实类别,因为这个区域已经足够小了,
		  就只需要判断ROI感兴趣区域中的每个像素是否属于这一个ROI感兴趣区域所属的GT真实类别的二分类即可,
		  可以看做是ROI感兴趣区域中的像素都是是否属于这一个ROI感兴趣区域所属的GT真实类别。
		4.正负样本:与GT真实框的IoU重合度超过0.5的RoI感兴趣区域视为正例, 否则为反例。
		5.mask掩码分支的损失只定义在正例上。m*m的二进制掩码(1,0)中的每个像素只使用分类分支softmax预测输出的第k个类别作为当前像素sigmoid处理后得到的结果,
		  与ROI感兴趣区域所分配的GT真实类别进行逻辑回归损失计算,其他类别的地方不贡献损失。

 

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
本课程适合具有一定深度学习基础,希望发展为深度学习之计算机视觉方向的算法工程师和研发人员的同学们。基于深度学习的计算机视觉是目前人工智能最活跃的领域,应用非常广泛,如人脸识别和无人驾驶中的机器视觉等。该领域的发展日新月异,网络模型和算法层出不穷。如何快速入门并达到可以从事研发的高度对新手和中级水平的学生而言面临不少的挑战。精心准备的本课程希望帮助大家尽快掌握基于深度学习的计算机视觉的基本原理、核心算法和当前的领先技术,从而有望成为深度学习之计算机视觉方向的算法工程师和研发人员。本课程系统面地讲述基于深度学习的计算机视觉技术的原理并进行项目实践。课程涵盖计算机视觉的七大任务,包括图像分类、目标检测、图像分割(语义分割、实例分割、景分割)、人脸识别、图像描述、图像检索、图像生成(利用生成对抗网络)。本课程注重原理和实践相结合,逐篇深入解读经典和前沿论文70余篇,图文并茂破译算法难点, 使用思维导图梳理技术要点。项目实践使用Keras框架(后端为Tensorflow),学员可快速上手。通过本课程的学习,学员可把握基于深度学习的计算机视觉的技术发展脉络,掌握相关技术原理和算法,有助于开展该领域的研究与开发实战工作。另外,深度学习之计算机视觉方向的知识结构及学习建议请参见本人CSDN博客。本课程提供课程资料的课件PPT(pdf格式)和项目实践代码,方便学员学习和复习。本课程分为上下两部分,其中上部包含课程的前五章(课程介绍、深度学习基础、图像分类、目标检测、图像分割),下部包含课程的后四章(人脸识别、图像描述、图像检索、图像生成)。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

あずにゃん

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值