25 YOLOv8中Bin的偏移量是相对于谁的——网格、乘数与框大小的关系
YOLOv8中Bin的偏移量是相对于谁的——网格、乘数与框大小的关系
前置文档:本文承接 第24篇,假设你已经理解"bin值固定、概率可变、加权求和"的机制。本文聚焦一个24篇没讲透的问题:bin的偏移量是相对于谁的?
一句话总结:Conv(dfl) 权重
[0, 1, 2, ..., 15]是一把固定尺子上的刻度编号,每个刻度代表 1 特征图像素。l/t/r/b 四条边的偏移量都相对于网格中心点(grid + 0.5),分别向左/上/右/下展开。大框和小框的区别不在于尺子更长,而在于概率峰值落在尺子的哪个刻度上。
目录
- YOLOv8中Bin的偏移量是相对于谁的——网格、乘数与框大小的关系
- 目录
- 一、bin 的乘数是尺子上的刻度,不是像素值
- 1.1 最容易误解的地方
- 1.2 实际含义
- 1.3 尺子类比
- 二、四条边都相对于网格中心点
- 2.1 参照系
- 2.2 left/top/right/bottom 各自的含义
- 三、坐标解码:从中心偏移到真实坐标
- 四、为什么 Sub 步骤要减去网格坐标
- 五、16 个 bin 能覆盖整个框吗
- 5.1 不能,也不需要
- 5.2 框的宽高不靠 bin 来覆盖
- 六、不同检测头的覆盖范围
- 七、大框和小框——bin 值一样,概率不同
- 7.1 核心问题
- 7.2 区别在于概率分布,不是 bin 值
- 7.3 框的宽高怎么来的
- 7.4 尺子类比
- 八、一句话总结
- 自测
一、bin 的乘数是尺子上的刻度,不是像素值
1.1 最容易误解的地方
看到 Conv(dfl) 权重[0, 1, 2, ..., 15],很容易以为 15 就是 15 个像素,大框能到 15,小框只能到 3。
不是这样的。
1.2 实际含义
Conv(dfl) 的权重[0, 1, 2, ..., 15]是固定乘数,含义是尺子上的刻度编号。加权求和后的结果(见第24篇)就是偏移量,单位是特征图像素:
bin 权重: [0, 1, 2, ..., 15] ← 固定乘数(尺子上的刻度编号) 加权结果: 0.991 ← 偏移 0.991 特征图像素(第24篇已讲)bin₁₅ 最多偏移 15 像素——这只是一个网格内的偏移距离,不是整个框的大小。
1.3 尺子类比
一把固定尺子,上面有 16 个刻度: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 尺子本身不会变长变短。 大框和小框的区别在于:概率峰值落在尺子的哪个刻度上。二、四条边都相对于网格中心点
2.1 参照系
YOLOv8 的 DFL 解码,四条边(left/top/right/bottom)的偏移量全都相对于网格中心点——而不是有的从左上角、有的从右下角。
一个网格(以 P3 为例,1×1 特征图像素 = 8×8 输入像素): ┌──────────────────────────┐ │ │ │ ◉ ← 网格中心 │ │ (grid+0.5) │ │ │ │ │ ←l← cx →r→ │ │ │ │ │ ↑t / ↓b │ │ │ └──────────────────────────┘- 网格中心点 =
grid + 0.5(grid 是网格的整数坐标) - l(left):框左边界到中心的距离,向左量
- t(top):框上边界到中心的距离,向上量
- r(right):框右边界到中心的距离,向右量
- b(bottom):框下边界到中心的距离,向下量
2.2 left/top/right/bottom 各自的含义
| 边 | 相对于 | 偏移方向 | 含义 |
|---|---|---|---|
| l(left) | 网格中心 | 向左 | l=3 → 框左边在中心左边 3 特征像素 |
| t(top) | 网格中心 | 向上 | t=3 → 框上边在中心上边 3 特征像素 |
| r(right) | 网格中心 | 向右 | r=3 → 框右边在中心右边 3 特征像素 |
| b(bottom) | 网格中心 | 向下 | b=3 → 框下边在中心下边 3 特征像素 |
四条边都从网格中心点算起,向四个方向对称展开。
三、坐标解码:从中心偏移到真实坐标
l/t/r/b 是相对网格中心的偏移,最终要乘上 stride 变成输入图像上的像素坐标:
中心坐标:cx = grid_x + 0.5,cy = grid_y + 0.5 x1 = (cx - l) × stride ← 框左边界:中心向左 l 再乘 stride y1 = (cy - t) × stride ← 框上边界:中心向上 t 再乘 stride x2 = (cx + r) × stride ← 框右边界:中心向右 r 再乘 stride y2 = (cy + b) × stride ← 框下边界:中心向下 b 再乘 stridet ┌──────────────┐ │ │ l │ ◉ 中心 │ r ←───────┤ (cx,cy) ├──────→ │ │ └──────────────┘ b 框宽 = (l + r) × stride 框高 = (t + b) × stride详细推导见 第26篇。
四、为什么 Sub 步骤要减去网格坐标
l/t/r/b 是相对网格中心的偏移。ONNX 图里接着的 Sub 步骤,把"相对网格中心的偏移"换算到"相对网格整数坐标的偏移":
网格中心 = grid + 0.5 相对网格中心的偏移 = (以 left 为例)grid + 0.5 - l Sub 步骤(部分实现里减去 grid 后 + 0.5)就是在做这个网格坐标到中心的换算。注意:不同导出版本(ultralytics 新旧版本)的 ONNX 图里 Sub/Add 的组合略有差异,但物理含义一致——最终得到的就是第 3 节公式里的框坐标。详细结构见 第26篇。
五、16 个 bin 能覆盖整个框吗
5.1 不能,也不需要
16 个 bin 覆盖的是"一个网格"的偏移范围,不是"整个框"的大小。
一个大目标框可能跨多个网格: ┌──────┬──────┬──────┐ │ │ │ │ │ G1 │ G2 │ G3 │ │ │ │ │ ├──────┼──────┼──────┤ │ │ 🐱🐱 │ │ │ G4 │ 🐱🐱 │ G5 │ ← 猫占了 4 个网格 │ │ │ │ ├──────┼──────┼──────┤ │ │ │ │ │ G6 │ G7 │ G8 │ │ │ │ │ └──────┴──────┴──────┘但实际检测中,一个框由它中心所在的那个网格负责完整预测——该网格输出 l/t/r/b 四条边,组合起来就是完整的框(详见 7.3)。框非常大时,l/r 偏移可能超过一条边的"覆盖范围"也没有关系,因为 l、r 各自从中心向两边延伸,框的宽度就是 l+r,可以覆盖整个目标。
5.2 框的宽高不靠 bin 来覆盖
框的宽高 = l + r(宽)、t + b(高),直接由 DFL 链的四条边组合而来,不受某个方向上 bin 数量的限制。l 和 r 各自独立预测,可以一个很小、一个很大,加起来就是完整的框宽。
六、不同检测头的覆盖范围
这里的"网格宽度"指的是输入图像上的物理像素,不是特征图像素:
P3 (stride=8): 网格宽度 = 8 输入像素, 16 个 bin 覆盖 0~15 特征像素 → 对应 0~120 输入像素(×8) P4 (stride=16): 网格宽度 = 16 输入像素, 16 个 bin 覆盖 0~15 特征像素 → 对应 0~240 输入像素(×16) P5 (stride=32): 网格宽度 = 32 输入像素, 16 个 bin 覆盖 0~15 特征像素 → 对应 0~480 输入像素(×32)在特征图上,P3/P4/P5 的网格都只有 1×1 特征像素,而 bin 覆盖 0~15,都能完全覆盖一个网格。区别在于乘上 stride 之后:
- P3:每个 bin 代表 8 输入像素,覆盖 0~120 输入像素
- P5:每个 bin 代表 32 输入像素,覆盖 0~480 输入像素
同一个 bin 编号在不同检测头上代表的物理距离不同——P5 上 bin₁₅ 是 480 输入像素,能覆盖大框;P3 上 bin₁₅ 只有 120 像素,适合中小框。这就是为什么大目标主要由 P5/P4 负责、小目标由 P3 负责。
七、大框和小框——bin 值一样,概率不同
7.1 核心问题
Conv(dfl) 权重[0, 1, 2, ..., 15]对所有框都一样,那大框和小框的区别在哪?
7.2 区别在于概率分布,不是 bin 值
加权求和的过程见第24篇,这里直接给结果:
小框(框边离网格中心近,比如 l 很小): bin₃ 概率 70%, bin₄ 概率 25% → 加权求和 ≈ 3.2 → l = 3.2 特征图像素 大框(框边离网格中心远,比如 r 很大): bin₇ 概率 60%, bin₈ 概率 30% → 加权求和 ≈ 7.3 → r = 7.3 特征图像素同一个[0,...,15]的尺子,小框的概率峰值落在小刻度,大框的峰值落在大刻度。
7.3 框的宽高怎么来的
框的宽高 = 四条边的偏移量组合:
框宽 = (l + r) × stride 框高 = (t + b) × stride由框中心所在的那个网格负责预测:它输出 l/t/r/b 四条边,各自走 DFL 链(4 条边 × 16 bin = 64 个 logits),四个偏移量组合起来就是完整的框。
7.4 尺子类比
一把固定尺子,16 个刻度: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 小框: 概率峰值在刻度 3 附近 → 加权平均 ≈ 3.2 → 偏移 3.2 特征像素 大框: 概率峰值在刻度 7 附近 → 加权平均 ≈ 7.3 → 偏移 7.3 特征像素 尺子没变,是概率峰值移动了。八、一句话总结
Conv(dfl) 的权重
[0, 1, ..., 15]是固定尺子上的刻度编号,每个刻度代表 1 特征图像素。l/t/r/b 四条边的偏移量都相对于网格中心点(grid+0.5),分别向左/上/右/下展开,乘上 stride 后得到输入图像上的框坐标。大框和小框的区别在于概率峰值落在尺子的哪个刻度上——尺子不变,票型变了。
自测
Q1:bin 的权重[0, 1, ..., 15]是像素值吗?
不是。它们是乘数(刻度编号),每个乘数代表 1 个特征图像素。bin₁₅ 的偏移量是 15 特征像素,不是 15 个输入图像像素——还需要乘以 stride 才对应输入图像距离。
Q2:bin 的偏移量是相对于谁的?left 和 right 的参照系一样吗?
点击查看答案l/t/r/b 四条边的偏移量都相对于网格中心点(grid + 0.5)。l 向左、t 向上、r 向右、b 向下,对称展开。四条边参照系一致,都是网格中心,区别只是方向不同。
解码时:x1 = (cx - l) × stride,x2 = (cx + r) × stride,cx = grid_x + 0.5。
Q3:16 个 bin 能覆盖整个检测框吗?
点击查看答案能。一个框由框中心所在的那个网格负责,它输出的 l/t/r/b 四条边各自走 DFL 链,框宽 = (l+r)×stride、框高 = (t+b)×stride。l 和 r 可以一个很小、一个很大,组合起来就是完整框宽,不受单个方向 bin 数量的限制。
Q4:为什么 P4/P5 的 bin 覆盖范围和 P3 不同,这有问题吗?
点击查看答案在特征图上三个检测头的 bin 都能覆盖整个网格(网格只有 1×1 特征像素,bin 覆盖 0~15)。区别在于乘上 stride 后:P3 每个 bin 代表 8 输入像素(覆盖 0~120),P5 每个 bin 代表 32 输入像素(覆盖 0~480)。
所以同一个 bin 编号在 P5 上覆盖更大的物理距离,P5 适合大目标、P3 适合小目标。这是设计,不是 bug。
Q5:大框和小框的 bin 值一样(都是 [0,1,…,15]),区别在哪?
点击查看答案区别在于概率分布。bin 值是固定尺子,大框和小框的区别在于概率峰值落在尺子的哪个刻度上。大框(如 r 较大)的概率峰值在更远的 bin(如 bin₇),小框的峰值在更近的 bin(如 bin₃)。
