shortcut层。shortcut层是跳过连接
主要看《yolov3_presentation.pdf》
框住目标,需4个点(回归问题,预测点坐标)
分类问题:判断类别 person/dog/cat…
YOLOv3 vs YOLOv2:
小目标判别更准确,识别速度慢一些,能识别到person,甚至person里的tie领带。
训练数据集:COCO
网络结构
residual block:回忆ResNet的图(常考(背)):
残差层中,输入大小x = 输出大小F(x)。因为要做加法F(x)+x,要保证矩阵维度一致。
detection layer:
caffe里没有yolo的自定义层,所以要自己定义,比如定义在cpu上。
把三层1*255*13*13
和1*255*26*26
和1*255*52*52
的feature map抽取出来,做后续处理。(对应test_yolov3_caffe.py的transform_tensor函数
)
caffe实现
图像预处理阶段:
对应test_yolov3_caffe.py的letterbox_image和prep_image函数
。def letterbox_image
中,
resized_image = cv2.resize(img, (new_w,new_h), interpolation = cv2.INTER_CUBIC) #interpolation:插值(缩放)
canvas = np.full((inp_dim[1], inp_dim[0], 3), 128) #canvas 画布 生成一个灰度(128)的画布,再把图片贴在上面
后续处理 处理成每个scale输出的tensor:
转换成坐标和类别。
一张图片,输出10647*85的矩阵。
过滤和筛选所有bbox(bounding box):
- 去除所有objectness score不达到thresh的bbox
每一行(85个向量):前4位是坐标ordinate,第5位是置信度objectness score,后面80位对应80个类别的分数。
然后根据置信度排序,排除掉大部分行,比如只保留20行置信度高的行,所以剩下20*85的矩阵。
- 在剩余的每个bbox里提取最高的class_score,得到这个最高
class_score对应的物体标签,然后Non-max Suppression (NMS)
然后我们要开始用opencv画框框了。这里用到的算法叫 NMS非极大值抑制
比如上面只保留了20行,先将20行的类别分数最大的,批量分成不同的类,比如20行中有10个cat、5个person、5个dog。
(这样可以避免了: 比如人抱着一只狗,框住了人,同时也想框住狗,但如果只判别人的话,根据NMS就会把狗的判别删除)
在不同的类别中,分别进行NMS。
NMS的过程是先按置信度从大到小排序,然后分别做求坐标的重合面积,就是两个框的重合面积,如果大于某个阈值,就把第二个那行删掉,比如现在有5* 85的矩阵,第1行与第2-5行分别进行比较,求NMS,然后比如第二行重合面积大于阈值,删除。之后就不进行第2行与第3-5行分别进行比较了,而是直接第3行与第4-5行进行比较。
最后可能只剩几行了,将他们输出,就是一张图片中框出来的数量。(一张图片 好几个框)
衡量指标:mAP:
- precision 查准率
- recall 查全率
pytorch 笔记:
接收的都是tensor格式,要先转换。
data = [-1, -2, 1, 2]
tensor = torch.FloatTensor(data) # 转换成32位浮点
Variable
import torch
from torch.autograd import Variable
x = torch.linspace(-5,5,200) #x data (tensor), shape=(200, 1)
x = Variable(x) #tensor变成Variable格式
x_np = x.data.numpy() #Variable格式别的识别不了,要转换成tensor(通过x.data转换成tensor),tensor格式再转换成numpy的格式(.numpy())
unsqueeze
x = torch.unsqueeze(torch.linspace(-1, 1, 100), dim=1) # x data (tensor), shape=(100, 1)
linspace是一维数组,[1,2,3]…
unsqueeze把一维数组变成二维数组 [[1,2,3]]
继承:
class Net(torch.nn.Module): #class B(A) 类B继承A