yolov5的anchors及bbox的编解码原理
yolov5的anchors的编解码原理
- yolov5的anchors及bbox的编解码原理
- 1.anchor的生成
- 1)base anchor的生成
- 2)base anchor的平移和复制
- 2.bbox的编解码过程
yolov5的anchors及bbox的编解码原理
1.anchor的生成
anchor的生成分为两个步骤:
首先会生成位于feature map左上角的base anchor,众所周知yolov3有9组anchor(图2),3个不同尺度大小的输出,而3个输出各对应三组anchor;生成base anchor之后会根据不同feature map的stride对base anchor进行平移复制。
图1 anchor的生成的代码实现
图2 9组anchor h*w
1)base anchor的生成
现假设输入图片为448640,那么最后输出的三个featuremap大小从小到大依次为:1420、2840、5680,对应的stride从小到大依次为:32,16,8。**以1420的feature map为例**,stride=32,对应9组anchor中的第一组:[(116, 90), (156, 198), (373, 326)]。那么图1中的代码就干两件事儿,生成base anchor:
图3 base anchor中心点位于左上角网格的中心位置
2)base anchor的平移和复制
平移复制base anchor,stride=32(feature map为14*20,那么相对于原图一个网格边长就是32):
图4 只画了116*90的anchor的平移示意,在14*20的feature map上最终共有14*20*3=840个anchor
最终,在14×20的feature map上有14×20×3=840个anchor,在28×40的feature map上有28×40×3=3360个anchor,在5680的feature map上有5680*3=13440个anchor,共计17640个anchor。
anchor生成完毕之后,再做一些操作之后就是decoder了,decode完毕之后就是NMS
2.bbox的编解码过程
编解码代码:
@BBOX_CODERS.register_module()
class YOLOV5BBoxCoder(BaseBBoxCoder):"""YOLO BBox coder.Following `YOLO <https://arxiv.org/abs/1506.02640>`_, this coder divideimage into grids, and encode bbox (x1, y1, x2, y2) into (cx, cy, dw, dh).cx, cy in [0., 1.], denotes relative center position w.r.t the center ofbboxes. dw, dh are the same as :obj:`DeltaXYWHBBoxCoder`.Args:eps (float): Min value of cx, cy when encoding."""def __init__(self, eps=1e-6):super(BaseBBoxCoder, self).__init__()self.eps = epsdef encode(self, bboxes, gt_bboxes, stride):"""YOLOv5 and YOLOx of YOLO series don't have encode"""raise NotImplementedError("YOLOv5 doesn't have encoder!")# targetdef delta_bbox(self, bboxes, pred_bboxes):"""Get delta_bboxes from anchors and pred_bboxes.Args:bboxes: anchors.(x1,y1,x2,y2)pred_bboxes: output bboxes of YOLOv5.(x,y,w,h)"""# anchors' width and heightw, h = bboxes[..., 2] - bboxes[..., 0], bboxes[..., 3] - bboxes[..., 1]# center of x & y of pred_bboxx_center_pred = (pred_bboxes[..., 0].sigmoid() - 0.5) * 2y_center_pred = (pred_bboxes[..., 1].sigmoid() - 0.5) * 2# w & h of pred_bboxw_pred = (pred_bboxes[..., 2].sigmoid() * 2) ** 2 * wh_pred = (pred_bboxes[..., 3].sigmoid() * 2) ** 2 * hdelta_bboxes = torch.stack((x_center_pred - w_pred / 2, y_center_pred - h_pred / 2,x_center_pred + w_pred / 2, y_center_pred + h_pred / 2),dim=-1)return delta_bboxesdef decode(self, bboxes, pred_bboxes, stride):"""Apply transformation `pred_bboxes` to `boxes`.Args:boxes (torch.Tensor): Basic boxes, e.g. anchors.pred_bboxes (torch.Tensor): Encoded boxes with shapestride (torch.Tensor | int): Strides of bboxes.Returns:torch.Tensor: Decoded boxes."""assert pred_bboxes.size(0) == bboxes.size(0)assert pred_bboxes.size(-1) == bboxes.size(-1) == 4x_center = (bboxes[..., 0] + bboxes[..., 2]) * 0.5y_center = (bboxes[..., 1] + bboxes[..., 3]) * 0.5w = bboxes[..., 2] - bboxes[..., 0]h = bboxes[..., 3] - bboxes[..., 1]# Get outputs x, y# 由于mmdetection的anchor已经偏移了0.5,故*2的操作要放在外面x_center_pred = (pred_bboxes[..., 0] - 0.5) * 2 * stride + x_centery_center_pred = (pred_bboxes[..., 1] - 0.5) * 2 * stride + y_center# yolov5中正常情况应该是# x_center_pred = (pred_bboxes[..., 0] * 2. - 0.5 + grid[:, 0]) * stride # xy# y_center_pred = (pred_bboxes[..., 1] * 2. - 0.5 + grid[:, 1]) * stride # xy# wh也需要sigmoid,然后乘以4来还原w_pred = (pred_bboxes[..., 2].sigmoid() * 2) ** 2 * wh_pred = (pred_bboxes[..., 3].sigmoid() * 2) ** 2 * hdecoded_bboxes = torch.stack((x_center_pred - w_pred / 2, y_center_pred - h_pred / 2,x_center_pred + w_pred / 2, y_center_pred + h_pred / 2),dim=-1)return decoded_bboxes
bbox框的编解码原理
其实整个过程可以理解成anchor在起什么作用,下面就简单的说明一下。我们知道yolo直接去预测出目标的位置坐标是不现实的,所以yolo的作者就提出去预测gt和anchor的偏移量。
示意图说明:
图5 图中蓝色框表示Anchor,绿色框表示人工标注,红色框则表示网络的预测结果(未经过训练)
上图中我们要先得到Anchor中心点所在网格的左上角坐标a=(6,2),再得到人工标注的中心点坐标g=(6.3,3.3),我们取到点g相对于点a的偏移量,记作p=(0.3,1.3),以p点坐标为中心,宽高与人工标注相同,得到target框如下:
图6 左上角天蓝色框为target,即网络需要预测的东西 注意上图中的**天蓝色框target**就是网络需要预测的东西!好了,现在涉及到编码encode了,原来yolov5中的encode代码如下:
pxy = pxy.sigmoid() * 2 - 0.5 # pxy即网络输出的框的xy坐标
pwh = (pwh.sigmoid() * 2) ** 2 * anchor[i] # anchor[i]即对应anchor的宽高
# 可以看出来,上述变化将xy坐标约束到区间[-0.5,1.5],将wh约束到[0,4]*anhcor_wh
将encode应用到上图中的网络输出pred_bbox和anchor,设pred_bbox中心点为r=(3.3,5.2),w=1.9,h=2.2,经过上述两行代码,r=(3.3,5.2)变成(1.428, 1.489),w=1.9变成1.89,h=2.2变成2.43,将得到的新框记作delta,如下:
至此,encode就完成了,一开始我们的网络没有经过训练,框都是乱跑的,经过编码之后约束到一个区间。算法会将上图中的delta框和target送入损失函数中,让网络去学习、去更新参数,使得delta框与target框趋于重合。我们假设网络学习效果非常好,现在的delta框已经与target框几乎重合:
注意了!理一下逻辑。这个时候,我们网络的输出pred_bboxes经过encode之后得到的框(记作res)几乎就是target框,还记得之前的Anchor中心点所在网格的左上角坐标a=(6,2)吗,加到res上不就是人工标注嘛!!
至此就结束了。这边可能有一点绕,因为我觉得下面的逻辑更加合适:
参考:
MMDetection移植yolov5——(二)前向推理
yolov5的anchors及bbox的编解码原理相关推荐
- 哈夫曼编解码原理与实现【转载】
1. 哈夫曼编解码原理 霍夫曼编码(Huffman Coding)是一种编码方法,霍夫曼编码是可变字长编码(VLC)的一种. 霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编 ...
- Base64编解码原理并用Java手工实现Base64编解码
Base64编解码原理 目前Base64已经成为网络上常见的传输8比特字节代码的编码方式之一.在做支付系统时,系统之间的报文交互都需要使用Base64对明文进行转码,然后进行签名或加密,之后再次Bas ...
- 一文读懂视频编解码原理
引子 谈到视频的编解码,我们会自然地想到H.264.HEVC/H.265这些权威的视频编解码标准:谈到标准,有人觉得这个是有专门机构去研究的,我们关心应用就好:即使有兴趣读了标准和相关技术,面对更多的 ...
- MPEG4编解码原理
### Date: 2017/3/19 ### Author: SoaringLee ###Content: MPEG4 ASP编解码原理 一.MPEG4的编码原理 1 编码原理MPEG-4编码器主要 ...
- adpcm编解码原理及其代码实现
目录 1. 源代码 adpcm.h adpcm.c 2. adpcm编解码原理 1.adpcm编码原理 2.adpcm解码原理 注释说明 3. ADPCM数据存放形式 1. adpcm 数据块介绍 2 ...
- WAV系列之二:ADPCM编解码原理及代码实现
参考自:<adpcm编解码原理及其代码实现> <ADPCM编码与解码学习笔记> <音频编码:ADPCM> 文章目录 1.PCM 1.1.采样 1.2.量化编码 2. ...
- 一文读懂视频编解码原理[通俗易懂]
一文读懂视频编解码原理[通俗易懂] 引子 谈到视频的编解码,我们会自然地想到H.264.HEVC/H.265这些权威的视频编解码标准:谈到标准,有人觉得这个是有专门机构去研究的,我们关心应用就好:即使 ...
- C++安全方向:(二)2.1 base16编解码原理讲解
1.概述: 二进制转字符串 2.应用场景 (1)邮件编码 (2)xml或者json存储二进制内容 (3)网页传递数据URL (4)数据库中以文本形式存放二进制 (5)可打印的比特币钱包地址,base5 ...
- SSD ECC中的LDPC编解码原理
转自:http://blog.csdn.net/zhuzongpeng/article/details/78899198 目前SSD中ECC纠错代码主要两种BCH和LDPC.不过,随着SSD对ECC纠 ...
最新文章
- 入门Go语言神器!超全学习资源+笔记,新手从零学习全过程资源汇总
- Redis批量操作详解及性能分析
- Redis队列php多线程请求
- 微软Tech Summit 2017,等你来打Call
- PS教程第十二课:会打开 会关闭我会了
- Eigen--.block(i,j,p,q)
- Java中调用文件中所有bat脚本
- EIGRP and the OSPF redistribute
- python自动打开网页_python 自动打开浏览器
- unitywebplayer 32/64 5.3版本
- 计算机考研408高分复习规划-如何复习408才能得高分
- ArcGis如何创建/连接企业级地理数据库
- 四核网络机顶盒芯片局势分析(开放市场):rk3128将会成为四核主流
- 最难学的十大编程语言,C++排第二,它竟是第一名!不服
- UWP VS创建UWP应用项目
- golang中net/http包用法
- 支付宝app支付产品不通过app集成sdk发起支付(附源码)
- 罗技无线键盘linux,罗技发布旗下第一款无线机械游戏键盘 G613
- JavaScript笔记(狂神说)
- 网络命令一览表(绝对实用)
热门文章
- android inactive InputConnection
- Hiveserver2源码剖析---如何实现代理用户
- AI之NLP:2020年6月21日北京智源大会演讲分享之15:15-15:40黄萱菁教授《自然语言处理中的表示学习》
- 散列函数(哈希函数,Hash Function)
- 常用CASE工具介绍 (csnd.net)
- linux redis密码修改,Linux redis 安装并且修改密码
- 敏涵控股集团:大爱敏涵共创敏涵梦
- python英译汉库模块_Python 进阶之路-翻译模块
- Excel使用教程技巧
- ResNet网络详解