【pytorch】自己实现精简版YOLOV3【二】,通过darknet_53输出的特征图:得到预测框位置、置信度以及目标类别
接上篇博文:
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输出的特征图:得到预测框位置、置信度以及目标类别相关推荐
- 【pytorch】自己实现精简版YOLOV3【三】,YOLOV3输入图片预处理:输入图片缩放及将生成预测框还原至原图
接上篇博文: Yolov3网络的输入默认为416x416,然后待检测的图片不总是416x416,这就产生了如何将待检测图片,在不破坏特征的情况下缩放至416x416,并对应在网络产生预测框后,如何将4 ...
- 应用统计432考研复试提问总结精简版【二】
一.自由度是什么? 定义:构成样本统计量的独立的样本观测值的数目 解释:从书中所给的平均数的角度进行 二.讲一下对t检验的理解? t检验适用于两个变量均数间的差异检验.同时用t检验的前提下:正态性和方 ...
- 应用统计432考研复试复试提问总结精简版【一】
一.区间估计与假设检验的联系与区别 联系:二者利用样本进行推断,都属于推断统计 区别: 原理: 前者是基于大概率,后者基于小概率: 统计量:前者是构造枢轴量(不含未知参数,分布明确),后者是检验统计量 ...
- Lesson 16.5 在Pytorch中实现卷积网络(上):卷积核、输入通道与特征图在PyTorch中实现卷积网络(中):步长与填充
卷积神经网络是使用卷积层的一组神经网络.在一个成熟的CNN中,往往会涉及到卷积层.池化层.线性层(全连接层)以及各类激活函数.因此,在构筑卷积网络时,需从整体全部层的需求来进行考虑. 1 二维卷积层n ...
- 【Pytorch神经网络实战案例】21 基于Cora数据集实现Multi_Sample Dropout图卷积网络模型的论文分类
Multi-sample Dropout是Dropout的一个变种方法,该方法比普通Dropout的泛化能力更好,同时又可以缩短模型的训练时间.XMuli-sampleDropout还可以降低训练集和 ...
- pytorch可视化 resnet50特征图
参考:https://blog.csdn.net/u012435142/article/details/84711978 Python可视化resnet50所有层特征图 使用pytorch中预训练模型 ...
- 可视化pytorch网络特征图
0. 背景 在目标检测任务中,我们会使用多尺度的特征图进行预测,背后的常识是:浅层特征图包含丰富的边缘信息有利于定位小目标,高层特征图中包含大量的语义信息有利于大目标的定位和识别.为了进一步了解特征图 ...
- 史上最详细的Pytorch版yolov3代码中文注释详解(四)
史上最详细的Pytorch版yolov3代码中文注释详解(一):https://blog.csdn.net/qq_34199326/article/details/84072505 史上最详细的Pyt ...
- <计算机视觉四> pytorch版yolov3网络搭建
鼠标点击下载 项目源代码免费下载地址 <计算机视觉一> 使用标定工具标定自己的目标检测 <计算机视觉二> labelme标定的数据转换成yolo训练格式 <计算机 ...
最新文章
- 三星电子网络营销重拳出击芯片制造力求“差异化”取胜智能手机市场
- Yii2中你可能忽略但很有用的两个方法batcheach
- java定时任务_定时任务最简单的3种实现方法(超好用)
- 如何将二维数组作为函数的参数传递
- Vue的调试工具(Chrome 浏览器)配置
- python 数据去重 max()_荐 用 Python 对 Excel 表格内数据进行去重、分类,标记异常及分析...
- android开发动态图ae,动影ae动态图片特效制作
- Angular 4入门教程系列:14:PrimeNG的使用方式
- 李宏毅机器学习之Life Long Learning
- postman interceptor抓取cookie
- 使用Cobbler批量部署Linux和Windows
- Leetcode 309. Best Time to Buy and Sell Stock with Cooldown
- Android急速模拟器Genymotion安装指北
- windows下Ardupilot编译环境搭建
- toad连接数据库时报错 cannot load OCI DLL
- 蓝桥杯练习-位平方和
- https://github.com/gnustep/
- NAACL 2022 | 字节和加州大学提出ConST模型,探讨对比学习如何助力语音翻译?
- 金融要求计算机水平,什么是金融人才?符合五大标准的金融人
- 虚拟机ubuntu访问PC文件
热门文章
- .onkeypress和.onkeydown的含义 以及补充知识document.onkeypress的含义
- 万头攒动火树银花之处不必找我。如欲相见,我在各种悲喜交集处,能做的只是长途跋涉的归真返璞。
- 传苹果将弃用高通、博通芯片;华为研发投入排全球第四;​微软新文本语音模型可在 3 秒内复制任何人的声音 | 极客头条
- JAVA使用POI对Word docx模板文件替换数据工具类
- java.util.base64
- 口语8000句--(1)在家中
- 2008 国庆节流水帐
- 2022软件测试工程师涨薪攻略,3年如何达到30K
- SVN服务器端的安装和配置(服务端的使用)
- C语音面向对象编程方法及应用