带图讲解,深度学习YOLO里面的anchors的进阶理解

article/2025/11/5 16:35:23

如果有了解过yolo网络,那肯定也听说过anchors,当然anchors这个概念布置在YOLO里面才有,在其他的目标检测中也存在anchors这个概念。对于anchors计算的一些公式这篇文章就不进行讲解了,这篇文章主要是讲在训练网络模型过程中anchors执行的流程,并将这个抽象的概念具体化,便于更深的理解yolo。

  • 1.  anchors是什么?

答:anchors其实就是在训练之前人为设定的先验框,网络输出结果的框就是在anchors的基础上进行调整的。所以说先验框设定的好坏对于模型的输出效果影响还是挺大的。在yolo中一般设定一个物体的先验框的个数一般是9个,例如:

anchors = np.array([[27., 183.], [87., 31.], [51., 62.], [139., 95.], [53., 50.], [60., 54.5], [87., 55.], [161., 41.], [49.5, 44.]])

这个先验框anchors一共有9个元素,每一个元素代表一个先验框的宽高。例如【27,183】就表示第一个先验框的宽为27,高为183。

  • 2.一张图片有多少个先验框?

答:先验框的个数与图片是哪个的物体的个数有关系,一个物体默认会设定9个先验框。

在标注的时候会用一个矩形框来将物体标注出来,这样子我们可以根据标注信息来获取物体的左上角(x1, y1)和右下角(x2,y2)坐标,然后计算出物体的中心坐标[(x2-x1)/2, (y2-y1)/2]。 这样子就可以把ancors表示出来了。下面就是原图与画了先验框的图片的对比:

 3.先验框在哪一步会进行调整?

答:在YOLO网络里面,一张图片进入模型编码之后会输出三个feature map(特征层),分别用

小特征层(20,20)、中特征层(40,40)和大特征层(80,80)来表示。其中小特征层用于检测大物体,中特征层用于检测中等物体,大特征层用于检测小物体。(因为小特征层的尺寸比较小,也就是压缩的倍数多,小物体经过多次压缩的话在小特征层上面可能就不明显甚至没有,所以小特征用于检测大的物体)。anchors是在特征层上进行调整的,但最开始的anchors是相对于原图的,我们需要将anchors的大小以及物体的中心也对应到feature map上。我们可以从feature map上获取到物体中心以及框的宽高的偏移量offset_x, offset_y, offset_w, offset_h, 然后根据偏移量对先验框进行调整。

下面是先验框的可视化展示:

原图上:

 特征层上:一共9个anchors,有3层特征层, 所以每层3个先验框

左边的红框是先验框没调整之前在特征层上的位置,黑点表示中心位置

右边的绿框是中心点和先验框调整之后在特征层上的位置

opt:懒得打字但又想记录一下的部分。

在训练过程中,对anchors的调整是在求loss前会对anchors进行调整,然后用调整后的anchors和真实框来计算loss_iou。

yolo过了模型之后有三个feature map,所以每个feature map上一个物体有三个anchor,在对anchors进行调整的时候会吧feature map的值调整到0~1之间,这是因为在feature map上每个网格的长度默认为1.

Last:代码实现部分:

代码引用到的YoloDataset, yolo_dataset_collate这两个函数在:

YoloDataset, yolo_dataset_collate:

YoloBody是网络结构,可以用YOLO系列的网络

import os
import randomimport cv2
import torch
import numpy as np
from torch.utils.data import DataLoader
import matplotlib.pyplot as pltfrom algorithm_code.yolov6.yolo_net import YoloBody
from algorithm_code.yolov6.yolo_dataloader import YoloDataset, yolo_dataset_collateimport osos.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"def sigmoid(x):s = 1 / (1 + np.exp(-x))return sdef get_anchors_and_decode(feats, anchors, center, num_classes, j):feat1 = feats.new(feats.shape)feats = feat1.cpu().numpy()x, y = centerplt_w, plt_h = feats.shape[1:3]# feats     [batch_size, h, w, 3 * (5 + num_classes)]num_anchors = len(anchors)grid_shape = np.shape(feats)[1:3]#   获得各个特征点的坐标信息。生成的shape为(h, w, num_anchors, 2)grid_x = np.tile(np.reshape(np.arange(0, stop=grid_shape[1]), [1, -1, 1, 1]), [grid_shape[0], 1, num_anchors, 1])grid_y = np.tile(np.reshape(np.arange(0, stop=grid_shape[0]), [-1, 1, 1, 1]), [1, grid_shape[1], num_anchors, 1])grid = np.concatenate([grid_x, grid_y], -1)#   将先验框进行拓展,生成的shape为(h, w, num_anchors, 2)anchors_tensor = np.reshape(anchors, [1, 1, num_anchors, 2])anchors_tensor = np.tile(anchors_tensor, [grid_shape[0], grid_shape[1], 1, 1])#   将预测结果调整成(batch_size,h,w,3,nc+5)feats = np.reshape(feats, [-1, grid_shape[0], grid_shape[1], num_anchors, num_classes + 5])box_xy = sigmoid(feats[..., :2]) + gridbox_wh = np.exp(feats[..., 2:4]) * anchors_tensorfig = plt.figure(figsize=(10., 10.,))ax = fig.add_subplot(121)plt.ylim(-2, plt_h)plt.xlim(-2, plt_w)plt.scatter(grid_x, grid_y)plt.scatter(x, y, c='black')plt.gca().invert_yaxis()anchor_left = grid_x - anchors_tensor / 2anchor_top = grid_y - anchors_tensor / 2print(np.shape(anchor_left))rect1 = plt.Rectangle([anchor_left[y, x, 0, 0], anchor_top[y, x, 0, 1]], anchors_tensor[0, 0, 0, 0],anchors_tensor[0, 0, 0, 1], color="r", fill=False)rect2 = plt.Rectangle([anchor_left[y, x, 1, 0], anchor_top[y, x, 1, 1]], anchors_tensor[0, 0, 1, 0],anchors_tensor[0, 0, 1, 1], color="r", fill=False)rect3 = plt.Rectangle([anchor_left[y, x, 2, 0], anchor_top[y, x, 2, 1]], anchors_tensor[0, 0, 2, 0],anchors_tensor[0, 0, 2, 1], color="r", fill=False)ax.add_patch(rect1)ax.add_patch(rect2)ax.add_patch(rect3)ax = fig.add_subplot(122)plt.ylim(-2, plt_h)plt.xlim(-2, plt_w)plt.scatter(grid_x, grid_y)plt.scatter(x, y, c='black')plt.scatter(box_xy[0, y, x, :, 0], box_xy[0, y, x, :, 1], c='r')plt.gca().invert_yaxis()pre_left = box_xy[..., 0] - box_wh[..., 0] / 2pre_top = box_xy[..., 1] - box_wh[..., 1] / 2rect1 = plt.Rectangle([pre_left[0, y, x, 0], pre_top[0, y, x, 0]], box_wh[0, y, x, 0, 0], box_wh[0, y, x, 0, 1],color="g", fill=False)rect2 = plt.Rectangle([pre_left[0, y, x, 1], pre_top[0, y, x, 1]], box_wh[0, y, x, 1, 0], box_wh[0, y, x, 1, 1],color="g", fill=False)rect3 = plt.Rectangle([pre_left[0, y, x, 2], pre_top[0, y, x, 2]], box_wh[0, y, x, 2, 0], box_wh[0, y, x, 2, 1],color="g", fill=False)ax.add_patch(rect1)ax.add_patch(rect2)ax.add_patch(rect3)plt.savefig(r"C:\Users\HJ\Desktop\demo\%s_%s.jpg" % (i, j))plt.close()anchors = np.array([[27., 183.], [87., 31.], [51., 62.], [139., 95.], [53., 50.], [60., 54.5], [87., 55.], [161., 41.], [49.5, 44.]])
anchors_mask = [[6, 7, 8], [3, 4, 5], [0, 1, 2]]
data_line = ['E:/私人文件/V3软件标注/定位/tags/1/1/1_00000001.jpg 42,74,113,289,0 228,236,306,308,1']
train_dataset = YoloDataset(data_line, [512, 512], 10, anchors, False, False)
gen_train = DataLoader(train_dataset, shuffle=True, batch_size=1, num_workers=0, pin_memory=True, drop_last=False,collate_fn=yolo_dataset_collate)
model = YoloBody(num_classes=10).to("cuda")for iteration, batch in enumerate(gen_train):images, targets, y_trues = batch[0], batch[1], batch[2]print("image shape:", images.shape)boxes = targets[0].cpu().numpy()boxes_center = [((box[0] + box[2]) / 2, (box[1] + box[3]) / 2) for box in boxes]print("boxes:", boxes_center)img_h, img_w = images.shape[2:4]print("img_wh:", img_w, img_h)with torch.no_grad():images = images.to("cuda")targets = [ann.to("cuda") for ann in targets]y_trues = [ann.to("cuda") for ann in y_trues]outputs = model(images)for i, feat in enumerate(outputs):input_anchor = anchors[anchors_mask[i]]# print("input anchor:", input_anchor)feat = feat.permute(0, 2, 3, 1)print("feat.shape:", feat.shape)# 1.获取feat 的高和宽feat_h, feat_w = feat.shape[1:3]# 2.有了原图大小和feat大小,就可以求出步长stride_h, stride_w = img_h / feat_h, img_w / feat_wprint("stride:", stride_h, stride_w)# 3.anchors是相对于原图的,而我们读取数据的到的image是经过resize之后得到的图片,所以我们要先把anchors对应到resize之后的图片,然后再映射到feature map# 由于我这里原图是512,512. resize的大小也是512,512所以就不需要将anchor从原图映射到resize之后的图片,也就是少做了一个除法feat_anchors = input_anchor / np.array([stride_w, stride_h])  # 把anchors从热size之后的图映射到feature map上# 4.根据原图的坐标信息我们可以求出物体的中心位置,有了步长之后局可以求出物体在feature map上面的位置for j, center in enumerate(boxes_center):feat_x, feat_y = int(center[0] / stride_w), int(center[1] / stride_h)print("第%s特征的x, y:" % i, feat_x, feat_y)# 5.现在feature map,中心,anchors都有了,就可以画出anchors的图片了get_anchors_and_decode(feat, feat_anchors, (feat_x, feat_y), 10, j)print("==============================")


http://chatgpt.dhexx.cn/article/Xt9yTxXu.shtml

相关文章

Linux终端的网易云音乐——musicbox

网易云音乐是听歌的不错的选择,如果能够在命令行听歌就更cool了。特来推荐musicbox。 网易云音乐的musicbox是网易云音乐命令行版本,这款命令行的客户端使用 Python 构建,以 mpg123 作为播放后端。提供了很多使用的功能,如&#x…

MusicStore-2

1.按照MusicStore-1步骤创建mvc项目,并初始化数据库 2.修改HomeController using Chapter8.Models; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc;namespace Chapter8.Controllers {public class…

音乐i网站

开发工具(eclipse/idea/vscode等): 数据库(sqlite/mysql/sqlserver等): 功能模块(请用文字描述,至少200字) :

musicbox(暂停/启动,停止,下一曲上一首)

主界面 按下开始 按下暂停 按下停止 下一首 上一首 代码 activity_main.xml <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:orientation"vertical&…

node-webkit-MusicBox 基于nwjs ,html5 ,制作的音乐盒子

太长&#xff1f;单击目录直接去看最终效果&#xff0c;在最下边 文件下载地址&#xff1a;http://download.csdn.net/detail/u013934914/9180053 1.思路&#xff08;简单设想&#xff09; index.html 实现 对页面的显示&#xff0c;并调用绑定ymusic.js中的方法 需要&…

算数计算机音乐模拟器,Musicalculator

musicalculatorapp它是一个音乐旋律软件&#xff0c;在这上面你可以随时随地的记录你有灵感时创作出来的乐谱&#xff0c;还可以放好听的音色包进行自动的弹奏&#xff0c;还可以根据自己的想法设定速度音长&#xff0c;这一款非常的适合喜爱音乐的用户。该应用只是一款音乐计算…

HTML5 CSS3实战——自定义音乐播放器(一)

前几天才刚开始接触HTML5和CSS3。学习了一下里面的一些炫酷的新特性。不过&#xff0c;对于原生的HTML5的媒体播放器&#xff0c;真的不得不吐槽&#xff1a;就三个按钮 界面还那么丑。所以觉得自己整一个好看的播放器。老话说&#xff1a;说不如干&#xff0c;纸上谈兵终觉浅。…

NetEase MusicBox —— Linux系统里的网易云音乐(转载)

功能特性 320kbps的高品质音乐 歌曲&#xff0c;艺术家&#xff0c;专辑检索 网易 22 个歌曲排行榜 网易新碟推荐 网易精选歌单 网易 DJ 节目 私人歌单&#xff0c;每日推荐 随心打碟 本地收藏&#xff0c;随时加 ? 播放进度及播放模式显示 Vimer 式快捷键让操作丝般顺滑 可使…

MusicBox - 仿千千静听

大学毕业时业余之作 最新下载地址&#xff1a; 匿名提取文件连接 http://pickup.mofile.com/5412819180446197 或登录Mofile&#xff0c;使用提取码 5412819180446197 提取文件 MusicBox 停止开发&#xff01;&#xff01; 淘宝开卖源代码 有意者 http://item.taobao.co…

音乐播放器

用HTML做了个音乐播放器&#xff0c;可以循环播放&#xff0c;选择歌曲&#xff0c;以及自动播放下一首&#xff0c;运用了js和json知识&#xff0c;下面是效果图和源码&#xff0c;有兴趣的可以试试哦 效果图&#xff1a; 源码&#xff1a;html <span style"color:#9…

MusicPlay播放器

文章目录 一丶前端布局二丶Activity三丶Service实验演示 一丶前端布局 Layout的框架 一个自定义的音乐播放器&#xff0c;页面布局大致如下 二丶Activity 首先定义控件 // 获取界面中显示歌曲标题、作者文本框TextView title, author;// 喜欢&#xff0c;播放&#xff0c;暂…

MusicPlay 音乐播放器(纯前端)

纯Css,js前端音乐播放器,界面UI比较好。我特别喜欢,适合二次开发,调用了网易云第三方接口以及将歌曲链接导出可以访问的歌曲链接,实现了异步歌曲搜索播放,以及异步显示歌词等.结合html5 新特性实现歌曲暂停,下一首,快进等等.为大二前端练手项目.采用渐变质背景 是前端练手的好…

HTML5+JS实现简易的音乐播放器

HTML5JS实现简易的音乐播放器 播放器实现的功能 播放/暂停音乐切换歌曲&#xff0c;上/下一首歌音量最大或静音音乐播放时间实时变化进度条拖拽歌曲图片切换 播放器效果展示 代码展示 html <div class"musicBox" id"musicBox"><audio src"…

音乐播放器MusicBox

音乐播放器MusicBox 功能界面分析 界面要求较为简洁&#xff0c;仅需两个TextView&#xff0c;用于输出音乐名称及歌手姓名&#xff0c;下方三个ImageButton&#xff0c;用于播放&#xff0c;暂停或切换上一首&#xff0c;下一首歌曲。 实现 总体规划 在MainActivity中&a…

索尼音乐应用android,Sony Music Center

Sony Music Center是全新的索尼音乐中心也是原来的songpal应用&#xff0c;作为sony手机上面的专业播放器的软件&#xff0c;它能够为用户播放各种音乐上面的内容&#xff0c;它可以直接的为用户解析各种音乐的内容&#xff0c;让用户能够随时的在手机上面收听到自己所喜欢的无…

MusicLibrary:一个丰富的音乐播放封装库

code小生,一个专注 Android 领域的技术分享平台 作者&#xff1a;lizixian18链接&#xff1a;https://github.com/lizixian18/MusicLibrary声明&#xff1a;本文是 lizixian18 投稿,转载等请联系作者获得授权。 MusicLibrary 一个丰富的音乐播放封装库&#xff0c;针对快速集成…

MusicBox

MusicBox 编写音乐盒代码&#xff0c;并添加音乐播放的 上一首 和 下一首 控制。 1.添加所需的图片以及音乐文件&#xff1b; 2.编写xml文件&#xff0c;上一首、下一首、暂停、播放按钮以及歌曲的名字和作者 <?xml version"1.0" encoding"utf-8"?&…

Musicplayer

Musicplayer Python 音乐播放器 功能&#xff1a; 首先可以实现本地音乐的播放&#xff0c;能够打开电脑端的文件&#xff0c;文件中进行多选&#xff0c;实现暂停、上一曲、下一曲的功能。在此基础上&#xff0c;完成随机播放列表和网络端下载的功能。 设计方法&#xff1a; 本…

MusicBox(音乐播放器)

这两天做了一个小型的音乐播放器&#xff0c;基本功能都已实现&#xff0c;同时也让我对CSliderCtrl&#xff0c;MCI_OPEN_PARMS以及控件之间的消息映射&#xff0c;数据转换等有了更深入的理解&#xff0c;下面是自己编程的详细过程&#xff1a; 1 首先将控件的位置都摆好&a…

musicbox使用方法_使用Pi MusicBox收听流音乐

musicbox使用方法 在用Raspberry Pi 控制圣诞树灯的项目完成之后&#xff0c;下一个项目是什么&#xff1f; 我最终开始尝试使用Pi Musicbox进行修补&#xff0c;这是Mopidy的Raspbian的一种版本 &#xff0c;它允许用户在“无头”的Raspberry Pi上播放各种流媒体服务&#xff…