继续我们的目标检测算法的分享,前期我们介绍了SSD目标检测算法的python实现以及Faster-RCNN目标检测算法的python实现以及yolo目标检测算法的darknet的window环境安装,本期我们简单介绍一下如何使用python来进行YOLOV3的对象检测算法
YOLOV3的基础知识大家可以参考往期文章,本期重点介绍如何使用python来实现
1、初始化模型
14-16 行:
模型的初始化依然使用cv下的DNN模型来加载模型,需要注意的是CV的版本需要大于3.4.2
5-8行:
初始化模型在coco上的label以便后期图片识别使用
10-12行:
初始化图片显示方框的颜色
2、加载图片,进行图片识别
输入识别的图片进行图片识别,这部分代码跟往期的SSD 以及RCNN目标检测算法类似
19-20行:输入图片,获取图片的长度与宽度
25-29行:计算图片的blob值,输入神经网络,进行前向反馈预测图片
只不过net.forward里面是ln, 神经网络的所有out层
3、遍历所有的out层,获取检测图片的label与置信度
遍历out层,获取检测到的label值以及置信度,检测到这里YOLOV3以及把所有的检测计算完成,但是由于yolov3对重叠图片或者靠的比较近的图片检测存在一定的问题,使用YOLOV3使用非最大值抑制来抑制弱的重叠边界
竟然把墨镜识别了手机,体现了YOLOV3在重叠图片识别的缺点
4、应用非最大值抑制来抑制弱的重叠边界,显示图片
56: 使用 非最大值抑制来抑制弱的重叠边界
58-59行:遍历所有图片
61-62行:提取检测图片的BOX
64-68行:显示图片信息
70-71行:显示图片
利用python来实现YOLOV3,与SSD 以及RCNN代码有很多类似的地方,大家可以参考往期的文章进行对比学习,把代码执行一遍
进行视频识别的思路:从视频中提取图片,进行图片识别,识别完成后,再把识别的结果实时体现在视频中,这部分代码结合前期的视频识别,大家可以参考多进程视频实时识别篇,因为没有多进程,检测速度很慢,视频看着比较卡
1、初始化模型以及视频流
2、从视频中提取图片,进行图片的blob值计算,进行神经网络的预测
3、提取检测到图片的置信度以及ID值
4、 应用非最大值抑制来抑制弱的重叠边界,显示图片
5、关闭资源,显示图片处理信息
每个目标检测算法都有自己的优缺点,个人感觉,在精度要求不是太高的情况下SSD检测算法可以实现较快的速度实现,毕竟精度差不多的情况下,我们希望速度越快越好
我们知道传统机器学习中如果要预测出一条短信是否为垃圾短信,我们会把很多条短信拿来做训练样本,然后每条短信的标签是用0和1来标注他是否为垃圾短信。通过将这些训练样本及对应的标签输入到机器学习模型中,使得模型能够学习怎样判别一条短信是否为垃圾短信,从而当随便拿一条短信输入到模型中,就能判断这个短信是否为垃圾短信了。
Yolov3算法的训练方法与传统机器学习算法训练的本质是一样的。
Yolov3中用来训练的样本实际上是一群框,yolov3通过训练这群样本框,让模型能够学习到如何将这群样本框挪动位置来框住图片中真实的物体。从而当随便拿一张图片,yolov3都能将这张图片中的物体给框住,并判断其类别。
这群样本框是怎么定义的,这群框的样本标签又该如何定义,我们接下来给大家介绍。
Yolov3的多尺度预测
Yolov3通过对图片卷积提取特征后会得到三个尺度的feature map,这三个尺度的feature map分别是13*13,26*26,52*52.然后对每个feature map的每个cell下分配三个anchor box,anchor box的尺寸有(10x13),(16x30),(33x23),(30x61),(62x45),(59x119),(116x90),(156x198),(373x326)这九种。怎么把这9个anchor box分配给3个feature map.我们可以通过如下分析得到:(10*13),(16*30),(33*23)属于小尺度的anchor box,主要用于检测小尺寸的物体,而feature map中52*52的感受野最小,适合检测小的物体,所以把(10*13),(16*30),(33*23)分配给52*52的feature map,(30x61),(62x45),(59x119)属于中等尺度的anchor box,主要用于检测中等尺寸的物体,所以把他分配给26*26(负责检测中等尺寸物体的feature map),(116x90),(156x198),(373x326)属于较大尺度的anchor box,主要用于检测较大尺寸的物体,所以把他分配给13*13(负责检测较大尺寸物体的feature map)的feature map.将上述anchor box分配好后,我们可以利用公式计算出anchor box在原图中的位置。这群在三个feature map的每一个cell下的anchor box,实际上就是我们模型的训练样本。如果将这群anchor box都还原回原图,每张图片上差不多有1万多个anchor box.我们都知道训练样本是要有样本标签的,那么yolov3是如何给训练样本(这群anchor box)打上标签呢?
如何给样本打标签
但是每张图片上就有1万多个anchor box,而且一张图片上可能有多个gt box.gt box就是我们对图片中标记的样本框。如果每一个anchor box都要打上gt box的标签,就会有两个问题,其一:anchor box与gt box之间如何对应?其二:每一张图片有一万多anchor box要训练,yolov3算法效率岂不太低。
为此yolov3采用了中心负责制,即gt box中心落在哪个cell,就由该cell上面的某个anchor box用来负责预测该gt box中的物体。
注意:不是每个cell下面都有3个anchor box吗,为什么只由某个anchor box负责预测该gt box呢?其实,这也很好解释,如果对一堆anchor box做位置移动,使其接近gtbox。那么肯定是与gt box重合度高的anchor box在做适当的坐标修正后比较接近该gt box.因此,每个gt box都要与anchor box计算交并比,找到与其交并比最大的anchor box来负责预测该gt box.
那具体来说一下 *** 作流程:
首先生成13*13*3*(80+5),26*26*3*(80+5),52*52*3(80+5)这样维度大小的三个零矩阵。
对训练样本图片做循环,在每次循环中再对gtbox做循环,在每次gtbox循环中再对9个anchor box做循环。举个例子,有10张图片,每张图片上有3个gtbox(这个gtbox就是我们对样本图片上的物体进行标注的框),用9个anchor box与gt box计算iou,找到最大的iou对应的anchor box.例如,第四个anchor box与gt box的iou最大,而我们已经知道第四个anchor box分配给了26*26的feature map.所以当前这个gt box中的物体由26*26这个feature map中某个cell中的anchor box负责预测。
怎么找到这个cell呢?
将gt box所在的原图image划分成26*26的网格,看gt box的中心落在哪个cell上,feature map上对应的那个cell就负责预测这个gtbox中的物体。假设中心落在第四行第三列上。
那么图片中该gtbox中的物体由26*26的feature map中的(4,3)的这个cell里面的第一个anchor box来预测。因此我们只用将该gtbox的坐标,类别,置信度填入该anchor box 对应的位置就好了,因为这是我们的anchor box要达到的目标。注意:我们填入的并不是gt box的坐标,而是gt box与anchorbox的坐标之间通过编码公式换算出来的一种值。而第二个anchor box与第三个anchor box不负责预测物体,所以全部填0.
Yolov3的预测值
Yolov3中的预测值在3个feature map与3*3的filter卷积得到的结果中取得。以26*26的feature map为例,26*26*256的feature map和3*3*256*(3*85)做卷积运算,输出26*26*(3*85)的预测值.这个85中80是预测的anchor box中属于每一类别的概率,4是gtbox与anchor box之间的偏移量,1是置信度,是这个anchor box中有无物体的概率和anchor box与其对应的gt box之间iou的乘积。
损失计算
上面将yolov3的样本标签,及每个样本的预测值做了解释,接下来就是如何计算损失了。Yolov3的损失函数包括三部分,坐标损失,置信度损失和分类损失。把样本分为了正负样本。
通常我们把不需要负责预测物体的anchorbox称作负样本。负样本不需要计算坐标损失和分类损失,只需要计算置信度损失,而负样本的置信度的目标值是0,就是说我这个框的置信度目标的预测值接近0,就是让算法去学习让这个框不包含物体。
而把需要负责预测物体的anchorbox称作正样本,正样本需要计算坐标损失,置信度损失和分类损失。
正负样本的区分
在yolov3中我们把anchor box样本分为正样本,负样本和忽略样本。anchor box样本标签中置信度为1的anchor box,称为正样本,置信度为0的anchor box,称为负样本。忽略样本则是从负样本中抽取出来的,如何理解呢?
由于yolov3使用了多尺度预测,不同尺度的特征图之间可能会出现重复检测的部分。例如有一个物体狗的gt box在训练时与13*13的feature map中的某个anchor box对应。此时在训练模型的预测值中,恰好26*26的feature map中的某个anchor box与该gtbox的iou达到0.93。而模型中我们让这个anchor box的置信度标签为0,网络学习结果肯定会不理想。所以我们的处理办法是,将这种与gtbox之间 iou较大(大过设定的阈值,如0.5),但又不负责预测物体的anchor box称之为忽略样本,不纳入损失计算。
在负样本中挖掘出忽略样本的步骤如下:
让所有的预测的缩放比(tx,ty,tw,th)与对应的anchorbox 进行解码,得到对应的预测框,我们称为bbox.
让这些bbox与当前预测的图片上的所有gtbox (假设有v个)计算交并比,就可以让每个bbox有对应的v个分数。对每个预测框取v个分数中的最大值,即可以得到best_score,这个best_score就是与这个anchor box交并比最大的那个gt box,他们之间的交并比。
将anchor box置信度标签为0,但best_score>阈值的部分设置为忽略样本,不参与损失计算。
而anchor box置信度标签为0,但best_score<阈值的部分才是参与损失计算的负样本。
2.Yolov3的预测流程
预测流程:
模型输出三种尺度的预测结果,分别为13*13*3*(80+5),26*26*3*(80+5),52*52*3(80+5)。此处以batch*13*13*(3*85)为例进行说明。
将输出的batch*13*13*(3*85),用输出的置信度和类别概率相乘,得到筛选各个bbox框的score值。
对筛选的物体检测框,进行非极大值抑制算法来删掉对同一类物体重合度较高的框,然后选出最后的最优框。
非极大值抑制的计算步骤:
1:设置阈值
2:对每类对象
2.1:选取该类中概率最大的框,然后用这个框与该类中的其他框计算iou,iou大于阈值则剔除,把这个最大的框放入输出列表中,这个最大的框也剔除出去
2.2:在余下的该类框中再选出概率最大的框,重复2.1的 *** 作
2.3:返回步骤2,继续下一类对象
Yolo系列采用了one-stage的识别方案,故名思意,就是一个阶段,图像进来之后,卷积提取特征,到和labels计算损失,他就一个阶段。相教于fasterrcnn,masterrcnn等需要生成大量候选框的two-stage方案,在识别速度上还是比较到位的,这样就使得它非常的实用,传说被美军应用在了导d识别方面,传说的很玄乎,也确实,无论在速度还是准确率,yolov3都做的非常不错。
我们看下yolov3的结构,先附上一张整体结构图。
从上到下我们走一遍YOLOV3流程。
1.A位置,当图像输入进来以后,图像的尺寸并不是正方形的,为了后面的计算方便,我们首先把他转换成能被32整除的正方形。为什么是32,整个网络要经过16次放缩变换(步长为2的卷积 *** 作{替代池化}),最后得到的特征图尺寸是11*11 或者12*12或者14*14这样的方格。每次转换称的正方形图像并不是固定尺寸,这样就增强了网络适应不同大小图像的能力.
2.B位置, 一个conv2d是Convolution卷积+Batch Normalization+Leaky_relu激活的组合。Batch Normalization归一化替代正则,提升模型收敛速度。Leaky_relu软路激活解决了relu激活时负数不学习的问题。
从A位置进来416*416*3的图像,经过了32(32个卷积核)*3*3(卷积核的尺寸3*3) 步长为1的卷积 *** 作之后,变成了416*416*32的输出。
3.B到C过程中,我们看到图像尺寸从416*416转换成208*208,中间有一层步长为2的卷积层,来替代池化层。比单纯的用池化层效果要好一些。
4.C位置,这里是卷积和残差连接的组合,yolov3的残差连接是同模块内的残差连接,shape相同才能连接。
C位置以下的resnet层 ,我们就不再说明了,原理和连接都是一致的。越往下,特征图的尺寸约小,特征核的层数越多。
5.我们看下E位置的尺寸是13*13*1024,D位置的尺寸是26*26*512 ,越往下的层越能识别大物体,而上面的层越能识别小物体,我们把上下两层相加,使得它同时具备了识别大物体和小物体的能力。上下两层即E层和D层怎么融合呢,我们把E层上采样,变成26*26*256,这样他就能和D层首尾相连进行拼合了。
6.拼合以后我们看到到了F位置,注意F位置的尺寸 (batch_size,26,26,75),分类数是 70 ,这里却是75,多出来的五个就是,x,y,w,h,conf(是物体与不是物体的判断)。
7.YOLO层是一个预测值和Lables目标值相减求损失的层。
yolov3一共有三个YOLO层分别去训练网络,为什么有三个,较小的特征图有比较大的视野,教大的特征图有比较小的视野,这样yolo3就拥有了既能识别大目标也能识别小目标的能力,同时,一个点既能是一种分类,也可以属于另外的分类.
8.好了,pytorch执行loss.back(),反向传播,就开始训练了。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)