SSD目标检测的个人总结(1)—— 锚框的生成
SSD目标检测的个人总结(1)—— 锚框的生成
- 前言
- 锚框
- 锚框的生成
- 锚框的绘制
前言
沐神的代码看了很久、B站上的视频也刷了很多遍,感叹下自己的基础确实不怎么扎实,锚框部分的底层代码几乎是一行行撸过来的,因此对整个学习的部分做一个总结先放上沐神的b站和电子教程,以示敬意!
沐神的b站
动手学深度学习电子版
锚框
以SSD(单发多框检测)为例,在输入图像上,我们会以图片的每一个像素为中心,生成多个缩放比(Size)和宽高比(Ratio)的边界框,这些边界框被称为锚框(anchor box)
锚框的生成
锚框的生成是以图像像素为中心,生成不同形状的锚框,对于每一张图片,均有宽度w和高度h,对宽度和高度进行缩放,决定了锚框的缩放比,而缩放后的锚框,通过更改宽高比,从而使得锚框对不同比例的物体有更好的适应能力。
如下列代码所示,size表示分别覆盖了20%——96%左右的图像区域;ratios表示每个缩放后的锚框的长和宽的比值;
#sizes——锚框在特征图上的覆盖范围
#ratios——锚框长和宽的比例组合
sizes = [[0.2,0.272],[0.3,0.447],[0.54,0.619],[0.71,0.79],[0.88,0.961]]ratios = [[1,2,0.5]]*5
沐神在动手学深度学习的第二版中,还提到了一些锚框生成的条件,由于SSD目标检测的思想是通过每个像素来生成N个锚框,对于一张480320的图片而言,如果我们假定买个像素生成3个锚框,我们在一张图像上将会得到480320*3 = 460800个锚框,很容易计算量过大;因此在具体实践中,我们只考虑在相同缩放比下,不同宽高比的组合或者是相同宽高比下,不同缩放比的组合
假设图像的高度为h,宽度为w,缩放比的个数为n,宽高比的个数为m,则对于每一个像素来说,我们能够生成的锚框的数量为
n+m-1 既 缩放比个数+宽高比个数-1
具体代码实现如下,可以参考李沐动手学深度学习中的代码,本人仅根据个人理解和实际运行,做了抽取和注释
def multibox_prior(data, sizes, ratios):"""生成以每个像素为中心具有不同形状的锚框"""# 输入图像的高宽,输入数据数据格式为(批次,通道数,高,宽)in_height, in_width = data.shape[-2:]# 提供size和ratio的数量,s为缩放比,r为宽高比num_sizes, num_ratios = len(sizes), len(ratios)# 每个像素生成锚框数量的计算,该例为3+3-1boxes_per_pixel = (num_sizes + num_ratios - 1)# 生成缩放比和宽高比的tensorsize_tensor = torch.tensor(sizes)ratio_tensor = torch.tensor(ratios)# 为了将锚点移动到像素的中心,需要设置偏移量。# 因为一个像素的的高为1且宽为1,我们选择偏移我们的中心0.5offset_h, offset_w = 0.5, 0.5steps_h = 1.0 / in_height # 在y轴上缩放步长steps_w = 1.0 / in_width # 在x轴上缩放步长# 生成锚框的所有中心点# 在高度和宽度中,对每个像素加上偏移量,并进行尺度缩放,在每个像素中心点生成锚框center_h = (torch.arange(in_height) + offset_h) * steps_hcenter_w = (torch.arange(in_width) + offset_w) * steps_wshift_y, shift_x = torch.meshgrid(center_h, center_w)shift_y, shift_x = shift_y.reshape(-1), shift_x.reshape(-1)# 生成“boxes_per_pixel”个高和宽,# 之后用于创建锚框的四角坐标(xmin,xmax,ymin,ymax)# 锚框的宽度:w√sr;锚框的高度:hs/√r,# 固定缩放比,调整宽高比进行锚框宽高组合;固定宽高比,调整缩放比进行锚框宽高组合; w = torch.cat((size_tensor * torch.sqrt(ratio_tensor[0]),sizes[0] * torch.sqrt(ratio_tensor[1:])))\* in_height / in_width # 处理矩形输入h = torch.cat((size_tensor / torch.sqrt(ratio_tensor[0]),sizes[0] / torch.sqrt(ratio_tensor[1:])))# 除以2来获得半高和半宽anchor_manipulations = torch.stack((-w, -h, w, h)).T.repeat(in_height * in_width, 1) / 2# 每个中心点都将有“boxes_per_pixel”个锚框,# 所以生成含所有锚框中心的网格,重复了“boxes_per_pixel”次out_grid = torch.stack([shift_x, shift_y, shift_x, shift_y],dim=1).repeat_interleave(boxes_per_pixel, dim=0)output = out_grid + anchor_manipulationsreturn output.unsqueeze(0)
需要注意的是,在沐神的代码中,锚框的生成做了缩放,这样做的好处是,可以根据任意比例大小的图片的宽高,进行锚框的生成,也能够基于此进行预测,我们给定一组测试数据,对该方法进行验证
h,w = 561,728
test_data = torch.rand(size = (1,3,h,w))
test_sample = multibox_prior(test_data , sizes=[0.75, 0.5, 0.25], ratios=[1, 2, 0.5])
test_sample.shape
以下结果表明,每一张561*728分辨率的图片,根据宽高比和缩放比生成的锚框约有204万个,每一个锚框包含四个值,分别是以单个像素为中心缩放和偏移后的锚框的左上角的x,y以及右下角的x,y
torch.Size([1, 2042040, 4])
通过数组下标对单个像素生成的锚框进行访问,我们先通过reshape张量的形状,以便我们进行访问,输入以下代码后,可以得出该像素下缩放+偏移后锚框的坐标:
# 转变数据为(图像高、图像宽,-1,坐标点)的形式
boxes = test_sample.reshape(h, w, -1, 4)
# 访问(250,250)像素点生成的第一个锚框的坐标值
boxes[250, 250, 0, :]
tensor([0.06, 0.07, 0.63, 0.82])
若想还原在图像上的真实坐标点,可以采用如下方法,返回该像素点所生成的锚框在原始图片上的真实坐标信息,变量box_scale为原始图像的宽和高:
boxes = test_sample.reshape(h, w, -1, 4)
box_scale = torch.tensor((w,h,w,h))
boxes[250, 250, :, :]*box_scale
tensor([[ 40.13, 40.12, 460.88, 460.87],
[110.25, 110.25, 390.75, 390.75],
[180.38, 180.38, 320.62, 320.62],
[-47.02, 101.74, 548.02, 399.26],
[101.74, -47.02, 399.26, 548.02]]
锚框的绘制
在生成锚框后,我们可以结合沐神的d2l包,在样例图片上绘制我们得到的锚框,我们所选择的是图片上坐标为(250,250)的像素所生成的锚框:
def show_bboxes(axes, bboxes, labels=None, colors=None):"""显示所有边界框"""def _make_list(obj, default_values=None):if obj is None:obj = default_valueselif not isinstance(obj, (list, tuple)):obj = [obj]return objlabels = _make_list(labels)colors = _make_list(colors, ['b', 'g', 'r', 'm', 'c'])for i, bbox in enumerate(bboxes):color = colors[i % len(colors)]rect = d2l.bbox_to_rect(bbox.detach().numpy(), color)axes.add_patch(rect)if labels and len(labels) > i:text_color = 'k' if color == 'w' else 'w'axes.text(rect.xy[0], rect.xy[1], labels[i],va='center', ha='center', fontsize=9, color=text_color,bbox=dict(facecolor=color, lw=0))
d2l.set_figsize()
bbox_scale = torch.tensor((w, h, w, h))
fig = d2l.plt.imshow(img)
show_bboxes(fig.axes, boxes[250, 250, :, :] * bbox_scale,['s=0.75, r=1', 's=0.5, r=1', 's=0.25, r=1', 's=0.75, r=2','s=0.75, r=0.5'])
SSD目标检测的个人总结(1)—— 锚框的生成相关推荐
- 基于Grad-CAM与KL损失的SSD目标检测算法
基于Grad-CAM与KL损失的SSD目标检测算法 人工智能技术与咨询 来源:<电子学报>,作者侯庆山等 摘 要: 鉴于Single Shot Multibox Detector (SSD ...
- Pytorch搭建SSD目标检测平台
学习前言 什么是SSD目标检测算法 源码下载 SSD实现思路 一.预测部分 1.主干网络介绍 2.从特征获取预测结果 3.预测结果的解码 4.在原图上进行绘制 二.训练部分 1.真实框的处理 2.利用 ...
- SSD目标检测算法原理(上)
目录 一.目标检测概述 1.1 项目演示介绍 1.2 图片识别背景 1.3 目标检测定义 二.目标检测算法原理 2.1 任务描述 2.2 目标检测算法必备基础 2.3目标检测算法模型输出 目标检测 - ...
- 睿智的目标检测23——Pytorch搭建SSD目标检测平台
睿智的目标检测23--Pytorch搭建SSD目标检测平台 学习前言 什么是SSD目标检测算法 源码下载 SSD实现思路 一.预测部分 1.主干网络介绍 2.从特征获取预测结果 3.预测结果的解码 4 ...
- 基于神经网络的目标检测论文之目标检测方法:改进的SSD目标检测算法
4.2 改进的SSD 上一章我们了解到,物体识别检测算法是在传统CNN算法基础上加上目标区域建议策略和边框回归算法得到的.前辈们的工作主要体现在目标区域建议的改进策略上,从最开始的穷举建议框,到划分图 ...
- 【目标检测】SSD目标检测
导语 PaddlePaddle提供了丰富的运算单元,帮助大家以模块化的方式构建起千变万化的深度学习模型来解决不同的应用问题.这里,我们针对常见的机器学习任务,提供了不同的神经网络模型供大家学习和使用. ...
- 华为开源自研AI框架昇思MindSpore应用案例:SSD目标检测
目录 一.环境准备 1.进入ModelArts官网 2.使用CodeLab体验Notebook实例 二.环境准备 三.数据准备与处理 数据采样 数据集创建 四.模型构建 五.损失函数 六.Metric ...
- (20)目标检测算法之YOLOv5计算预选框、详解anchor计算
目标检测算法之YOLOv5计算预选框.详解anchor计算 单节段目标检测算法中:预选框的设定直接影响最终的检测精度 众所周知,yolov5中采用自适应调整预选框anchor的大小,但万事开头难,配置 ...
- 2021-01-24过去十年十大AI研究热点,分别为深度神经网络、特征抽取、图像分类、目标检测、语义分割、表示学习、生成对抗网络、语义网络、协同过滤和机器翻译。
专利申请量全球第一!清华人工智能发展报告:国内215所高校成立相关本科专业 发布时间:01-2415:20万象大会年度获奖创作者,东方财富网官方帐号 1月20日,清华大学人工智能研究院.清华-中国工程 ...
最新文章
- php behaviors,详解在PHP的Yii框架中使用行为Behaviors的方法_php技巧
- VTK:插值相机用法实战
- c语言定义小数无穷小,OC中常用的数学函数以及浮点处理函数
- 读取Webpage表中的内容
- Android简单调用相机Camera功能,实现打开照相功能
- Orleans 知多少 | Orleans 中文文档上线
- 我的世界javamod怎么装_装暖气片,10个有8个人都想知道的这点事儿!
- java 与 xml_xml与java对象转换
- vscode安装live server
- linux下scrapy安装教程,linux centos7安装scrapy
- java td背景色_jQuery:无法更改表格单元格的背景颜色
- insert时调用本身字段_java中子类调用父类构造方法注意事项
- [蛋蛋四格漫画]-贺沪江日语四周年版庆
- Java对泛型的支持(二)- 高级语法
- Sum nyoj 欧拉定理简单运用(数论入门)
- opencv实现超像素分割(slic实现)
- 计算机械效率的公式四种,物理计算公式.doc
- 防火门行业研究及十四五规划分析报告
- 如何在Windows 10上不用鼠标使用文件资源管理器
- java复制屏幕文本内容_网页上的文字内容不给复制?电脑老司机教你输入一串代码,轻松复制...