目录

1、数据预处理

2、模型推理

2.1 推理预测框

2.2 预测框后处理


1、数据预处理

为了更好理解,整篇文章将以下面这张经典图像为例展开,图像分辨率为(720,1280,3)。

推理阶段,输入图像的分辨率(h,w,c)大小不一致,拿到图像后,首先要做的是resize处理。

yolov5中,默认图像大小为640,步长为32,具体处理步骤分为两步:

1、以最长边为基准,等比例缩放;

        r  = min(640/h,640/w),以矩形的最长边为基准,计算缩放比例 r 。

        new_h = r*h ;new_w = r*w,计算缩放后图像的分辨率,等比例缩放,长边默认为640。

        等比例缩放的好处是,目标不会产生形变,尤其针对一些长宽比例失衡的图像。

2、短边填充;

        检查短边是否能被 32 整除,如果能,则无需填充;不能,则向后寻找最接近32的倍数。

        以h为短边,dh = new_h / 32,向上取整,pad = dh*32 - new_h,要填充的长度pad。

        pad/2,在图像上下(或者左右)两边分别填充。

下面是实现数据预处理的代码,大家直接更换图片路径即可。

import cv2
import numpy as np

#替换图片路径
img_path = r'E:\AAmode\ceshi\yolov5-7.0\data\zidane.jpg'
img = cv2.imread(img_path)
h,w,c = img.shape
r = min(640/h,640/w)
new_h,new_w = int(round(r*h)),int(round(r*w))
dw, dh = 640 - new_w,640 - new_h
dw, dh = np.mod(dw, 32), np.mod(dh, 32)
dw /= 2
dh /= 2

im1 = cv2.resize(img, (new_w,new_h), interpolation=cv2.INTER_LINEAR)
top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
im2 = cv2.copyMakeBorder(im1, top, bottom, left, right, cv2.BORDER_CONSTANT, value=(114,114,114))

cv2.imshow("pad_img",im2)
cv2.waitKey(0)

示例图,预处理后的效果如下图所示。缩放后的短边 h 不能被32整除,上下分别填充灰色像素值,处理后的图像分辨率为(384,640,3)

 

2、模型推理

在yolov5中,预处理后的图片可直接喂入模型当中,模型中图片如何变化不在本章范围内,这里可将模型视为黑盒子,直接讨论输入与输出,以示例图为例展开。

2.1 推理预测框

模型会根据输入图像分辨率大小,总类别数,输出三个特征图,分别用来预测目标框。

由上图可知,输出特征图大小,由输入图像大小决定,即分别降低8倍,16倍,32倍;输出特征图的通道数,由类别 nc 决定,即 (nc + 5)* 3。

预测框数量由特征图决定,每一个特征图中,每个像素点就可预测 3 个框,所以总共 12*20*3 + 24*20*3 + 48*80*3 = 15120 个预测框。

在深度学习中,特征图一般以 tensor 数据结构存储,示例这里呢,每个像素点有3*8个通道,8个通道为一组,按组每次取8个通道中的像素值,即为该像素点上的一个预测框信息。

每个预测框包含8项信息,内容为(x,y,w,h,conf,c1,c2,c3)。

  • x,y,w,h 表示预测框的位置信息,分别表示中心点,宽高坐标;
  • conf 表示预测框置信度,范围 [0,1];
  • c1,c2,c3 表示预测框内的目标,分别属于第一类,第二类,第三类的概率;

2.2 预测框后处理

这一步属于后处理,即对模型推理出的所有预测框进行过滤,最后保留有效的预测框。

先介绍两个可调节阈值,conf_thres 和 iou_thres,后面会用到。

  • conf_thres:预测框的置信度阈值;
  • iou_thres:预测框与目标框的交并比阈值;

yolov5中的后处理步骤: 

  1. 首先会过滤掉一大批 conf < conf_thres 的预测框;
  2. 更新类别概率 ,即c1,c2,c3 = c1*conf,c2*conf,c3*conf。保留最大的类别概率,c = max(c1,c2,c3),并保存类别索引值 index(即属于第几类);
  3. 然后再次过滤掉一批 c<conf_thres 的预测框;
  4. 预测框坐标转换,中心点和宽高格式(x,y,w,h)to 两点格式(x1,y1,x2,y2);
  5. 更新预测框坐标信息,(x1,y1,x2,y2) + index * max_wh,即不同类别的预测框需加上不同的偏置量。其中,max_wh为定义的图像最大分辨率值,yolov5中默认是7680。
  6. 更新信息后的预测框 (x1,y1,x2,y2,conf),做非极大值抑制NMS处理;

其中,类别索引值index,从0开始,以递增+1的阿拉伯数字表示。即在模型中,第一类0,第二类1,第三类2,依次递增。 

 非极大值抑制 NMS :

  1. 找出所有预测框B(B1,B2,...,Bn)中置信度 conf 最高的 B1 作为基准,将 B1 与剩余预测框分别计算交并比值 IOU,将 IOU> iou_thres 阈值的预测框过滤掉,更新B。
  2. 然后继续找置信度第二高的预测框 Bm 作为基准,执行第一条操作。
  3. 按上述流程依次执行,最后保留的预测框没有任何一对是预测同一目标的。

NMS计算中用到的IOU,计算方式为 将预测框与目标框的交集除以二者的并集。

假设目标框(绿框)面积为A,预测框(红框)面积为B,可能会存在如下三种情况,包含,部分重合,相离。计算公式    IOU =\frac{\frac{}{} A\cap B}{A\cup B}

经过后处理的预测框,数量会明显下降,这里着重讲解下其中的关键两步。其中,

1、类别概率c = 类别概率c * 置信度conf,conf和c 本身的取值范围都是[0,1],小数乘小数。

这样做,一方面会在模型预测的基础上降低 分类概率值 c;另一方面呢,第一批已经过滤掉 conf < conf_thes 的预测框,现在又要过滤掉  conf * c <conf_thres 的预测框,c是小于1的,相当于变相缩小了conf。我理解的是可能为了过滤掉一些,本身框的置信度就不高(在阈值上方徘徊),而且目标类别概率值也不高的目标。

2、(x1,y1,x2,y2)+ index * 7680,index = (0,1,2..)。

根据类别索引值index,给隶属于不同类别的预测框的坐标信息加上不同的偏置量,而且这个偏置量的设置很大(远大于一般图像)。这样做,为了防止不同类的预测框,因为位置重合程度过高,而被nms过滤掉。

举个例子,示例图中,左侧这个人(person)的目标框,与其身上领带(tie)的目标框,是一种包含关系。推理阶段,如果不按类别将两个框的坐标信息划分开来,NMS过程中,计算iou,可能就会过滤掉其中一个框的信息,这样就会漏检。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐