接上篇博文:
YOLOv3网络在三个特征图中预测出( 4 + 1 + c ) × k 个值,即特征图上每个点对应4个边界坐标(实际为偏移量),1个置信度值,C个类别值(C个类别置信度);数量k为特征图上每个点预测出的边框数量,默认为3:
下图先验框由聚类算法得到:

特征图上的预测目标为:

上图中蓝色字样为最终预测目标,tx及ty为网格中心至网格左上角的偏移量;bx及by为预测看中心点坐标;etw及wth为边框长度缩放因子,pw及ph为先验框的高宽,bw,bh为最终预测框的高宽。sigmod函数将预测框中心坐标偏移量限制在当前网格中(坐标范围为0至1之间),加速收敛。
这样,cx及cy,pw及ph已知,只用预测出tw,th及tx及ty四个值,就能通过计算确定最终目标框的位置。注意,预测出的所有的b值均是经过归一化处理的。
对于分类的类别,使用logistic激活函数(将特征值代入sigmoid函数内部),而不使用softmax激活函数,logistic激活函数彼此相互独立,不同类别之间不会相互抑制,这就方便了对同一目标的多标签检测,比如一个目标既是人,又是男人。
代码实现的主要难点集中在tensor的多维运算。
使用pytorch实现如下:

import os.path
from typing import Iterator
import numpy as np
import torch
import cv2
import matplotlib.pyplot as plt
from PIL import Image
from torch.utils.data import Dataset, DataLoader, Subset, random_split
import re
from functools import reduce
from torch.utils.tensorboard import SummaryWriter as Writer
from torchvision import transforms, datasets
import torchvision as tv
from torch import nn
import torch.nn.functional as F
import time
import math
class DecodeBoxGeneratedFromFeatures():#   13x13的特征层对应的anchor是[116,90],[156,198],[373,326]#   26x26的特征层对应的anchor是[30,61],[62,45],[59,119]#   52x52的特征层对应的anchor是[10,13],[16,30],[33,23]anchors=\{  13:[[116,90],[156,198],[373,326]],26: [[30,61],[62,45],[59,119]],52: [[10,13],[16,30],[33,23]],}'''由特征图生成对应的预测结果,FeaturesMap为darknet35输出的其中一种特征图形状为:(batchsize,(5+classNum)*3,width,hight)'''def __init__(self,FeaturesMap,classNum):self.__dict__.update(self.anchors)self.FeaturesMap=FeaturesMap#目前高宽总是相等的self.imgH=FeaturesMap.shape[2]self.imgW = FeaturesMap.shape[2]if self.imgH not in [13,26,52]:raise Exception('输入的特征图尺寸只能是13,26,52中的一种')self.batchSize=FeaturesMap.shape[0]#预测的属性self.predictAttars=FeaturesMap.shape[1]self.classNum=classNum#变换原特征图至理想输出向量,默认特征图上每个点输出3个预测框self.FeaturesMap=self.FeaturesMap.view(self.batchSize,3,5+self.classNum,self.imgH,self.imgH)#为了便于解析,将输出预测值换到最后一维:self.FeaturesMap=self.FeaturesMap.permute(0, 1, 3, 4, 2).contiguous()#提取出相关的预测值:最后一维按顺序为 中心偏移量(tx,ty),宽高缩放比(tw,th),置信度conf,以及classnum的分类向量'''训练前的原始输出不具有实际意义,需要人为进行指定:同一尺寸特征图的每一个点,都有3个对应的预测输出值,下面torch.Size([1, 3, 26, 26])中的3,是指每个特征图上的点有3个预测,而不是3通道图像'''#tx的形状为:torch.Size([1, 3, 26, 26]),该特征图共计3*26*26个tx值;self.tx=torch.sigmoid(self.FeaturesMap[...,0])self.ty = torch.sigmoid(self.FeaturesMap[..., 1])self.tw=self.FeaturesMap[..., 2]self.th = self.FeaturesMap[..., 3]#下面两者配合损失函数使用sigmoid函数:self.conf = torch.sigmoid(self.FeaturesMap[..., 4])self.classPrediction=torch.sigmoid(self.FeaturesMap[..., 5:])#坐标公式中,所有值是以特征图长宽为依据的,下面要对原始尺寸归一化:#特征图上每点相对于原图来看是多长:self.scale=416.0/self.imgH#由聚类产生的Anchor是相对于原图的,将其也相对于特征图:self.anchorChoised=[[anchor[0]/self.scale,anchor[1]/self.scale] for anchor in self.anchors[self.imgH]]#生成网格值:即图中的cx及cy:生成类似(1,3,26,26)一样的结构,便于同位置相加'''其中torch.linspace(start, end, steps=100);repeat将通道1复制self.imgH个,通道2不变,再通过repeat新增第一维,为self.batchSize * 3,再通过view的方法,将该维分散成self.batchSize,3,同self.tx的形状一致'''self.gridx=torch.linspace(0, self.imgW - 1, self.imgW).repeat(self.imgH, 1).repeat(self.batchSize * 3, 1, 1).view(self.tx.shape).type(torch.FloatTensor)self.gridy=torch.linspace(0, self.imgW - 1, self.imgW).repeat(self.imgH, 1).repeat(self.batchSize * 3, 1, 1).view(self.ty.shape).type(torch.FloatTensor)'''将self.anchorChoised也处理成与self.tw一致,即torch.Size([1, 3, 26, 26]),方便与缩放系数self.tw相乘:(注:index_select用法:dim:表示从第几维挑选数据,类型为int值;index:表示从第一个参数维度中的哪个位置挑选数据,类型为torch.Tensor类的实例;使用后原tensor不降维。)待操作anchorChoised有0维行和1维列,形如:[[116,90],[156,198],[373,326]]对于生成与self.tw同shape的tensor,先取出第1维中的下标为0的元素:[[116],[156],[373]],size(3,1):#'''step1=torch.FloatTensor(self.anchorChoised).index_select(1, torch.LongTensor([0]))'''按行复制self.batchSize个,size(self.batchSize*3,1)'''step2=step1.repeat(self.batchSize, 1)'''扩充至3维,将列扩充self.imgH * self.imgW倍,size(1,self.batchSize*3,self.imgH * self.imgW)'''step3=step2.repeat(1, 1, self.imgH * self.imgW)'''调整至size(batchsize,3,imgH, imgW):view函数是将待变换tensor从第0维至第一维展平成1维后再从最后一维开始向第0维按目标shape依次排列而成的,由于矩阵元素都一致,变换只用关注shape,即可按维度顺序进行重分配,即(1,self.batchSize*3,self.imgH * self.imgW)-》(batchsize,3,imgH, imgW)'''anchor_w=step3.view(self.tw.shape)#下面相同的手法得到anchor_h:step1 = torch.FloatTensor(self.anchorChoised).index_select(1, torch.LongTensor([1]))step2 = step1.repeat(self.batchSize, 1)step3 = step2.repeat(1, 1, self.imgH * self.imgW)anchor_h = step3.view(self.th.shape)#盒子位置:x,y,w,h#首先创建大小一致的容器self.boxPosition=torch.FloatTensor(self.FeaturesMap[...,0:4].shape)print(self.boxPosition.shape)self.boxPosition[...,0]=self.tx+self.gridxself.boxPosition[..., 1] = self.ty + self.gridyself.boxPosition[..., 2] = anchor_w*torch.exp(self.tw)self.boxPosition[..., 3] = anchor_h*torch.exp(self.th)#输出该尺寸特征图的所有预测Boxsdef givePredictedBoxs(self):'''注1:self.boxPosition.view(self.batchSize, -1, 4) / _scale这里输出的x.y.w.h为这四个点坐标值相对于特征图的比例值,该比例值乘以特征图长度,就为特征图中box大小位置。该比例乘以原图,就能得到原图图上box的大小位置。这是因为网络输出特征图和原图差了一个缩放比self.scale,而比例值在各自图中具有不变性,'''_scale = torch.Tensor([self.imgH, self.imgW,self.imgH, self.imgW]).type(torch.FloatTensor)'''注2:这里使用了pytorch的广播机制:(self.batchSize, -1, 4) / (1,4),从最后一维开始对照,相同维度取最大的一维,再逐元素相乘。(self.batchSize, -1, 4)(                 1, 4)按最大取值:(self.batchSize, -1, 4)将待乘两向量对应元素相除。得出最终结果。'''output = torch.cat((self.boxPosition.view(self.batchSize, -1, 4) / _scale,self.conf.view(self.batchSize, -1, 1), self.classPrediction.view(self.batchSize, -1, self.classNum)), -1)return output.detach()#测试:用k模拟特征图
k=torch.rand(2,24,26,26)
#设为3分类
a=DecodeBoxGeneratedFromFeatures(k,3)
print(a.givePredictedBoxs().shape)

测试输出结果为:

torch.Size([2, 2028, 8])

【pytorch】自己实现精简版YOLOV3【二】,通过darknet_53输出的特征图:得到预测框位置、置信度以及目标类别相关推荐

  1. 【pytorch】自己实现精简版YOLOV3【三】,YOLOV3输入图片预处理:输入图片缩放及将生成预测框还原至原图

    接上篇博文: Yolov3网络的输入默认为416x416,然后待检测的图片不总是416x416,这就产生了如何将待检测图片,在不破坏特征的情况下缩放至416x416,并对应在网络产生预测框后,如何将4 ...

  2. 应用统计432考研复试提问总结精简版【二】

    一.自由度是什么? 定义:构成样本统计量的独立的样本观测值的数目 解释:从书中所给的平均数的角度进行 二.讲一下对t检验的理解? t检验适用于两个变量均数间的差异检验.同时用t检验的前提下:正态性和方 ...

  3. 应用统计432考研复试复试提问总结精简版【一】

    一.区间估计与假设检验的联系与区别 联系:二者利用样本进行推断,都属于推断统计 区别: 原理: 前者是基于大概率,后者基于小概率: 统计量:前者是构造枢轴量(不含未知参数,分布明确),后者是检验统计量 ...

  4. Lesson 16.5 在Pytorch中实现卷积网络(上):卷积核、输入通道与特征图在PyTorch中实现卷积网络(中):步长与填充

    卷积神经网络是使用卷积层的一组神经网络.在一个成熟的CNN中,往往会涉及到卷积层.池化层.线性层(全连接层)以及各类激活函数.因此,在构筑卷积网络时,需从整体全部层的需求来进行考虑. 1 二维卷积层n ...

  5. 【Pytorch神经网络实战案例】21 基于Cora数据集实现Multi_Sample Dropout图卷积网络模型的论文分类

    Multi-sample Dropout是Dropout的一个变种方法,该方法比普通Dropout的泛化能力更好,同时又可以缩短模型的训练时间.XMuli-sampleDropout还可以降低训练集和 ...

  6. pytorch可视化 resnet50特征图

    参考:https://blog.csdn.net/u012435142/article/details/84711978 Python可视化resnet50所有层特征图 使用pytorch中预训练模型 ...

  7. 可视化pytorch网络特征图

    0. 背景 在目标检测任务中,我们会使用多尺度的特征图进行预测,背后的常识是:浅层特征图包含丰富的边缘信息有利于定位小目标,高层特征图中包含大量的语义信息有利于大目标的定位和识别.为了进一步了解特征图 ...

  8. 史上最详细的Pytorch版yolov3代码中文注释详解(四)

    史上最详细的Pytorch版yolov3代码中文注释详解(一):https://blog.csdn.net/qq_34199326/article/details/84072505 史上最详细的Pyt ...

  9. <计算机视觉四> pytorch版yolov3网络搭建

    鼠标点击下载     项目源代码免费下载地址 <计算机视觉一> 使用标定工具标定自己的目标检测 <计算机视觉二> labelme标定的数据转换成yolo训练格式 <计算机 ...

最新文章

  1. 三星电子网络营销重拳出击芯片制造力求“差异化”取胜智能手机市场
  2. Yii2中你可能忽略但很有用的两个方法batcheach
  3. java定时任务_定时任务最简单的3种实现方法(超好用)
  4. 如何将二维数组作为函数的参数传递
  5. Vue的调试工具(Chrome 浏览器)配置
  6. python 数据去重 max()_荐 用 Python 对 Excel 表格内数据进行去重、分类,标记异常及分析...
  7. android开发动态图ae,动影ae动态图片特效制作
  8. Angular 4入门教程系列:14:PrimeNG的使用方式
  9. 李宏毅机器学习之Life Long Learning
  10. postman interceptor抓取cookie
  11. 使用Cobbler批量部署Linux和Windows
  12. Leetcode 309. Best Time to Buy and Sell Stock with Cooldown
  13. Android急速模拟器Genymotion安装指北
  14. windows下Ardupilot编译环境搭建
  15. toad连接数据库时报错 cannot load OCI DLL
  16. 蓝桥杯练习-位平方和
  17. https://github.com/gnustep/
  18. NAACL 2022 | 字节和加州大学提出ConST模型,探讨对比学习如何助力语音翻译?
  19. 金融要求计算机水平,什么是金融人才?符合五大标准的金融人
  20. 虚拟机ubuntu访问PC文件

热门文章

  1. .onkeypress和.onkeydown的含义 以及补充知识document.onkeypress的含义
  2. 万头攒动火树银花之处不必找我。如欲相见,我在各种悲喜交集处,能做的只是长途跋涉的归真返璞。
  3. 传苹果将弃用高通、博通芯片;华为研发投入排全球第四;​微软新文本语音模型可在 3 秒内复制任何人的声音 | 极客头条
  4. JAVA使用POI对Word docx模板文件替换数据工具类
  5. java.util.base64
  6. 口语8000句--(1)在家中
  7. 2008 国庆节流水帐
  8. 2022软件测试工程师涨薪攻略,3年如何达到30K
  9. SVN服务器端的安装和配置(服务端的使用)
  10. C语音面向对象编程方法及应用