目标检测算法-yolo-v4代码详解(代码片段)

cucwwb cucwwb     2022-11-29     646

关键词:

Yolo-V4算法中对网络进行了改进,使用CSPDarknet53。网络结构如下:

技术图片

Yolo-V4与Yolo-V3上相比较:

(1)对主干网络进行了修改,将原先的Darknet53改为CSPDarknet53,其中是将激活函数改为Mish激活函数,并且在网络中加入了CSP结构。

(2)对特征提取过程的加强,添加了SPP,PANet结构。

(3)在数据预处理阶段加入Mosaic方法。

(4)在损失函数中做了改进使用了CIOU作为回归Loss。

Mish激活函数:

Mish() = x×tanh(ln(1+ex)),使用Mish函数可以对负值有更好的梯度流,而不是像ReLU函数中那样的全零。这样平滑的激活函数允许更好的信息深入神经网络,从而得到更好的准确信息。

技术图片

 

CSPNet结构:

技术图片

CSP是可以增强CNN学习能力的新型结构,CSPNet将底层的特征映射分为两部分,一部分经过密集块和过渡层,另一部分与传输的特征映射结合到下一阶段。

 

from functools import wraps
from keras import backend as K
from keras.layers import Conv2D,Add,ZeroPadding2D,UpSampling2D,Concatenate,MaxPooling2D,Layer,Input
from keras.layers.advanced_activations import LeakyReLU
from keras.layers.normalization import BatchNormalization
from keras.regularizers import l2
from keras.layers import Activation
from keras import Model
#将定义好的函数添加到keras系统中
from keras.utils import get_custom_objects


# class Mish(Activation):
#     def __init__(self,activation):
#         super(Mish, self).__init__(activation)
#         self.__name__ ="Mish"
# def mish(inputs):
#     return inputs*K.tanh(K.softplus(inputs))
# get_custom_objects().update("Mish":Mish(mish))

class Mish(Layer):
    def __init__(self):
        super(Mish, self).__init__()

    def call(self,inputs):
        return inputs * K.tanh(K.softplus(inputs))



#darknet单次卷积
def DarknetConv2D(*args,**kwargs):
    darknet_conv_kwargs = "kernel_regularizer":l2(5e-4)
    darknet_conv_kwargs["padding"]="valid" if kwargs.get("strides")==(2,2) else "same"
    darknet_conv_kwargs.update(kwargs)
    return Conv2D(*args,**darknet_conv_kwargs)

#卷积块
def DarknetConv2D_BN_Mish(x,*args,**kwargs):
    no_bias_kwargs="use_bias":False
    no_bias_kwargs.update(kwargs)
    x=DarknetConv2D(*args,**no_bias_kwargs)(x)
    x=BatchNormalization()(x)
    #x=Activation("Mish")(x)
    x=Mish()(x)
    return x


def DarknetConv2D_BN_Leaky(x, *args, **kwargs):
    no_bias_kwargs = "use_bias": False
    no_bias_kwargs.update(kwargs)
    x = DarknetConv2D(*args, **no_bias_kwargs)(x)
    x = BatchNormalization()(x)
    # x=Activation("Mish")(x)
    x = LeakyReLU(alpha=0.1)(x)
    return x



def resblock_body(x,num_filters,num_blocks,all_narrow=True):
    preconv1 =ZeroPadding2D(padding=((1,0),(1,0)))(x)
    preconv1 =DarknetConv2D_BN_Mish(preconv1,num_filters,(3,3),strides=(2,2))
    #生成一个大的残差边
    shortconv =DarknetConv2D_BN_Mish(preconv1,num_filters//2 if all_narrow else num_filters,(1,1))
    #主干部分的卷积
    mainconv =DarknetConv2D_BN_Mish(preconv1,num_filters//2 if all_narrow else num_filters,(1,1))

    for i in range(num_blocks):
        x=DarknetConv2D_BN_Mish(mainconv,num_filters//2,(1,1))
        x=DarknetConv2D_BN_Mish(x,num_filters//2 if all_narrow else num_filters,(3,3))

        mainconv=Add()([mainconv,x])
    postconv =DarknetConv2D_BN_Mish(mainconv,num_filters//2 if all_narrow else num_filters,(1,1))
    route = Concatenate()([postconv,shortconv])

    return DarknetConv2D_BN_Mish(route,num_filters,(1,1))


def darknet_body(x):
    x =DarknetConv2D_BN_Mish(x,32,(3,3))
    x=resblock_body(x,64,1,False)
    x=resblock_body(x,128,2)
    x=resblock_body(x,256,8)
    feat1=x
    x=resblock_body(x,512,8)
    feat2=x
    x=resblock_body(x,1024,4)
    feat3=x
    return feat1,feat2,feat3

 

Mosaic数据增强:

(1)每次读取四张图片

(2)分别对这四张图片进行翻转,缩放,色域变化等,并且按照四个方向位置摆好。

(3)进行图片的组合和框的组合。

Label Smoothing-防止过拟合:

在分类模型当中,经常对标签使用one-hot的形式,然后去预测属于每一个标签的概率,如果不考虑多标签的情况下,选择概率最大的作为我们的预测标签。但是在实际过程中可能会存在两个问题。

(1)可能导致过拟合。

(2)模型对于预测过于自信,以至于忽略可能的小样本标签。

 产生上述问题的原因就是因为我们真正在计算交叉熵损失函数的时候,对于真实标签概率的取值要么是1,要么是0,表征我们已知样本属于某一类别的概率是为1的确定事件,属于其他类别的概率则均为0。Label Smoothing的原理就是为损失函数增强其他标签的损失函数值,类似于其为非标签增加了一定的可选择性。

注:如果分类准确,也就是说交叉熵对分类正确给的是最大激励,但实际上有一些标注数据并不一定是准确的。所以使用上述标签并不一定是最优的。

Label Smoothing:标签×(1-ξ)+ξ/标签个数×[1,1,...1]

def Label_Smoothing(y_true,label_smoothing):
    y_true = np.cast(y_true,tf.float32)
    num_classes = float((y_true.shape[-1]))
    label_smoothing = K.constant(label_smoothing,dtype=K.floatx())
    return y_true * (1.0-label_smoothing) + label_smoothing/num_classes

Loss函数:

Loss-IOU

使用Loss-IOU可能会产生梯度消失,因为当BBOX和真实框无交集的时候,这时候Loss-IOU始终为1。反向传播的时候梯度就为0了,产生了梯度消失。Loss-IOU=1-|B∩Bgt|/|B∪Bgt|

Loss-IOU会产生以下几点问题:

(1)如果两个框没有相交,则IOU=0,这是无法反映两个框的距离,并且损失函数此时不存在梯度,无法通过梯度下降训练。

(2)即使相同的IOU也不能代表检测框的定位效果相同。

Loss-GIOU

Loss-GIOU=1-IOU+|c-B∪Bgt|/|c|,与IOU相比,GIOU不仅关注重叠区域,当B和Bgt相对于彼此没有很好的对准时,封闭形状c中的两个对称形状B和Bgt之间的空白空间增加,因此,GIOU的值可以更好的反映两个对称物体之间如何发生重叠,GIOU在两者无交集且无限远的时候是取最小值-1,因此GIOU是一个非常好的距离度量指标。

IOU和GIOU没有考虑到真实框与预测中心之间的距离。实际情况下,中心点的距离越小框预测的越准。GIOU在水平和垂直方向误差很大也就是包含关系。

Loss-DIOU

Loss-DIOU = 1-IOU+δ2(b,bgt)/c2,在Loss-DIOU中,b,bgt分别代表了anchor框和目标框的中心点,且δ代表的是计算两个中心点间的欧式距离,c代表的是能够同时覆盖anchor和目标框的最小矩形的对角线的距离。

(1)DIOU在与目标框不重叠时,仍然可以为边界框提供移动方向。

(2)Loss-DIOU可以直接最小化两个目标的距离,因此比Loss-GIOU收敛的块。

(3)对于包含两个框的水平方向和垂直方向上这种情况,Loss-DIOU可以回归的非常快。

Loss-CIOU

Loss-CIOU=1-IOU+δ(b,bgt)/c2+αV,V=4/Π2[arctan(wgt/hgt)-arctan(w/h)]2,α=V/(1-IOU)+V,从α参数来看,损失函数会更加倾向于往重叠的区域增多方向优化。

#b1预测框,b2真实框
def box_ciou(b1,b2):
    b1_xy = b1[...,:2]
    b1_wh = b1[...,2:4]
    b1_wh_half = b1_wh/2.
    b1_mins = b1_xy-b1_wh_half
    b1_maxes = b1_xy+b1_wh_half

    b2_xy = b2[...,:2]
    b2_wh = b2[...,2:4]
    b2_wh_half = b2_wh/2.0
    b2_mins = b2_xy-b2_wh_half
    b2_maxes = b2_xy+b2_wh_half

    intersect_mins = K.maximum(b1_mins,b2_mins)
    intersect_maxes = K.minimum(b1_maxes,b2_maxes)
    intersect_wh = K.maximum(intersect_maxes-intersect_mins,0.)
    intersect_area = intersect_wh[...,0]*intersect_wh[...,1]
    b1_area = b1_wh[...,0]*b1_wh[...,1]
    b2_area = b2_wh[...,0]*b2_wh[...,1]

    union_area = b1_area+b2_area-intersect_area
    #K.epsilon()返回一个浮点数
    iou = intersect_area/(union_area+K.epsilon())
    #计算中心距离
    center_distance = K.sum(K.square(b1_xy-b2_xy),axis=-1)

    #找到包裹两个框的最小框的左上角跟右下角
    enclose_mins = K.minimum(b1_mins,b2_mins)
    enclose_maxes = K.maximum(b1_maxes,b2_maxes)
    enclose_wh = K.maximum(enclose_maxes-enclose_mins,0.0)

    #计算对角线距离
    enclose_diagonal = K.sum(K.square(enclose_wh),axis=-1)

    ciou = iou - 1.0 *(center_distance)/(enclose_diagonal+K.epsilon())

    v = 4*K.square(tf.math.atan2(b1_wh[...,0],b1_wh[...,1])-tf.math.atan2(b2_wh[...,0],b2_wh[...,1]))/(math.pi*math.pi)

    alpha = v/(1.0-iou+v)
    ciou = ciou-alpha*v
    ciou = K.expand_dims(ciou,axis=-1)

    return ciou



def get_loss_con(ytrue,ypre,noobj_scale,object_mask,IOU):
    object_mask = K.squeeze(object_mask,axis=-1)
    con_delta = object_mask*(ypre*IOU-ytrue) + noobj_scale*(1-object_mask)*(ypre*IOU-ytrue)
    loss_con = K.sum(K.square(con_delta),list(range(1,4)))

    return loss_con

其他的代码跟V3一样。

模拟余弦退火(学习率):

ηt = ηimin + 1/2imax-ηimin) (1-cos(Tcur/Ti)Π),ηimax和ηimin是学习率的范围,Tcur是随着iteration变化的,Ti是当前run总共的epoch数目。余弦退火衰减算法,学习率会先上升再下降,上升的时候使用线性上升,下降的时候模拟cos函数下降。Tcur/Ti =iteration/TotalIterations。

import numpy as np
import matplotlib.pyplot as plt


def compute_eta_t(eta_min, eta_max, T_cur, Ti):
    pi = np.pi
    eta_t = eta_min + 0.5 * (eta_max - eta_min) * (np.cos(pi * T_cur / Ti) + 1)
    return eta_t


# 每Ti个epoch进行一次restart。
Ti = [20, 40, 80, 160]
n_batches = 200
eta_ts = []
for ti in Ti:
    T_cur = np.arange(0, ti, 1 / n_batches)
    for t_cur in T_cur:
        eta_ts.append(compute_eta_t(0, 1, t_cur, ti))

n_iterations = sum(Ti) * n_batches
epoch = np.arange(0, n_iterations) / n_batches

plt.plot(epoch, eta_ts)
plt.show()

 

目标检测算法fasterr-cnn(详解)(代码片段)

FasterR-CNN学习目标1.FasterR-CNN2.RPN原理2.1anchors3.FasterRCNN训练3.1FasterR-CNN的训练3.2候选区域的训练4.效果对比5.FasterR-CNN总结6.总结7.问题8.开源kerasFasterRCNN模型介绍学习目标目标了解FasterR-CNN的特点知道RPN的原理以及作用【目标检测算... 查看详情

目标检测算法r-cnn(详解)(代码片段)

目标检测算法之R-CNN学习目标1.目标检测-Overfeat模型1.1滑动窗口1.2Overfeat模型总结2.目标检测-R-CNN模型2.1完整R-CNN结构2.2候选区域(RegionofInterest)得出2.3CNN网络提取特征2.4特征向量训练分类器SVM2.5非最大抑制(NMS)2.... 查看详情

从零开始学习目标检测:yolo算法详解(代码片段)

从零开始学习目标检测:YOLO算法详解文章目录从零开始学习目标检测:YOLO算法详解1.🌟什么是目标检测?2.🌟传统的目标检测与基于深度学习的目标检测3.🌟目标检测算法的工作流程4.🌟目标检测可以干什... 查看详情

keras深度学习实战(13)——目标检测基础详解(代码片段)

Keras深度学习实战(13)——目标检测基础详解0.前言1.目标检测概念2.创建自定义目标检测数据集2.1windows2.2Ubuntu2.3MacOS3.使用选择性搜索在图像内生成候选区域3.1候选区域3.2选择性搜索3.3使用选择性搜索生成候选区域4.交并... 查看详情

模型训练目标检测实现分享四:详解yolov4算法实现(代码片段)

...设计与实践,实践部分包括darknet与pytorch。 本文是目标检测类算法实现分享的第四篇,前面已经写过三篇,感兴趣的同学可以 查看详情

多目标跟踪(mot)--deepsort原理及代码详解(代码片段)

...体框架(流程)3.1框架概要3.2流程分析4.DeepSort各模块讲解4.1目标检测模块4.1.1目标检测模型概述4.1.2Detection类解析4.2轨迹跟踪模块4.2 查看详情

目标检测算法—yolo-v1

...?YOLO:youonlylookonce。只需要看一眼,就可以检测识别出目标,主要是突出这个算法 快 的特点。(原文:Yolo系列之前的文章:主要是rcnn系列的,他们的基本思想都是通过产生大量的regionproposal,然后再用分类器去判断分... 查看详情

目标检测雷达目标cfar检测算法(代码片段)

目录一、概述1、基本概念2、基础知识二、CFAR检测算法1、基本原理2、几种典型的CFAR检测算法(1)CA(CellAveraging)-CFAR检测算法(2)GO-CFAR、SO-CFAR检测算法(3)OS-CFAR检测算法(4)补充说明三、不同CFAR检测算法... 查看详情

目标检测算法ssd(singleshotmultiboxdetector)(代码片段)

SSD:SingleShotMultiBoxDetector学习目标1.SSD1.1简介1.2结构1.3流程1.4Detector&classifier1.4.1PriorBox层-defaultboxes1.4.2localization与confidence2.训练与测试流程2.1train流程2.2test流程3.比较4.总结学习目标目标知道SSD的结构说明Detect 查看详情

一阶段目标检测网络-retinanet详解(代码片段)

摘要1,引言2,相关工作3,网络架构3.1,Backbone3.2,Neck3.3,Head4,FocalLoss4.1,CrossEntropy4.2,BalancedCrossEntropy4.3,FocalLossDefinition5,代码解读5.1,Backbone5.2,Neck5.3,Head5.4,先验框Anchor赋值5.5,BBoxEncoderDecoder5.6,Focal 查看详情

openmmlab目标检测(代码片段)

OpenMMLab目标检测1.目标检测简介1.1滑窗2.基础知识2.1边界框(BoundingBox)2.2交并比IntersectionOverUnion2.3置信度ConfidenceScore2.4非极大值抑制Non-MaximumSuppression2.5边界框回归BoundingBoxRegression2.6边界框编码BboxCoding3.两阶段目标检测算... 查看详情

目标检测网络ssd详解(代码片段)

SSD目标检测网络  使用SSD检测网络一段时间了,研究过代码,也踩过坑,算是有能力来总结下SSD目标检测网络了。1.SSD300_Vgg16  最基础的SSD网络是以Vgg16作为backbone,输入图片尺寸为300x300,这里以其为示例,详细剖析下SSD检测... 查看详情

opencv项目实战目标检测:自动检测出现的所有动态目标(代码片段)

...ff0c;显示视频,保存视频三、项目实战:实时动态目标检测实时动态目标检测一、项目思路1、获取视频、读取帧图像2、计算连续两张图像的像素绝对差获取动态目标3、图像预处理:灰度图、高斯模糊、二值化、膨胀4... 查看详情

目标检测与识别车辆信息原理与实践详解(代码片段)

目标检测与识别车辆信息是一种应用广泛的技术,它可以帮助我们更好地了解道路交通状况,提高交通安全性。在本文中,我将详细介绍目标检测与识别车辆信息的工作原理、应用场景、挑战和未来发展方向。一、目标检测与识... 查看详情

目标检测雷达目标cfar检测算法(代码片段)

...收机输出的包络超过了某一设置门限,就认为出现了目标。雷达在探测时会受到噪声、杂波和干扰的影响,因而采用固定门限进行目标检测时会产生一定的虚警,特别是当杂波背景起伏变化时虚警率会急剧上升,... 查看详情

最短路-dijkstra算法:朴素版&堆优化版(java详解)(代码片段)

最短路-Dijkstra算法(Java版)朴素版Dijkstra算法1.目标2.算法3.关键代码4.例题5.参考代码堆优化版Dijkstra算法1.原理2.算法3.关键代码4.例题5.参考代码朴素版Dijkstra算法1.目标找到从一个点到其他点的最短距离2.算法初始化距离d... 查看详情

二阶段目标检测网络-maskrcnn详解(代码片段)

ROIPooling和ROIAlign的区别MaskR-CNN网络结构骨干网络FPNanchor锚框生成规则实验参考资料ROIPooling和ROIAlign的区别UnderstandingRegionofInterest—(RoIAlignandRoIWarp)MaskR-CNN网络结构MaskRCNN继承自FasterRCNN主要有三个改进:featuremap的提取采用了FPN的多... 查看详情

目标检测算法总结(代码片段)

转自:https://www.cnblogs.com/guoyaohua/p/8994246.html目标检测是很多计算机视觉任务的基础,不论我们需要实现图像与文字的交互还是需要识别精细类别,它都提供了可靠的信息。本文对目标检测进行了整体回顾,第一部分从RCNN开始介... 查看详情