YOLO 目标检测中的特征是如何流动的:从 RGB 图像到 FPN 多尺度特征
一、yolo的"特征流动"
YOLO 的整体流程可以简化为:
text
输入图像
↓
Backbone:提取不同层级的特征
↓
Neck:使用 FPN/PAN 融合多尺度特征
↓
Detect Head:预测类别和边界框
↓
NMS:去除重复框
↓
最终检测结果
本文重点解释下面这组常见尺寸:
text
640 × 640 × 3
↓
320 × 320 × 64
↓
160 × 160 × 128
↓
C3:80 × 80 × 256
↓
C4:40 × 40 × 512
↓
C5:20 × 20 × 1024
如果你有下面的问题是,那么这篇文章正好是你的答案:
20 × 20是不是像素?1024是什么?- 为什么输入只有 3 个通道,卷积后会变成 64 个通道?
- 为什么特征图越来越小,通道数却越来越多?
- FPN 如何使用这些特征?
二、如何理解 H × W × C
卷积神经网络中的一层特征通常写成:
text
H × W × C
其中:
H:特征图高度;W:特征图宽度;C:特征通道数。
例如:
text
20 × 20 × 1024
表示:
- 高度为 20;
- 宽度为 20;
- 有 1024 个特征通道。
它既可以理解为:
text
1024 张大小为 20 × 20 的特征图
也可以理解为:
text
20 × 20 = 400 个空间位置
每个位置保存一个 1024 维特征向量
即:
text
第 i 行、第 j 列的特征
=
[f1, f2, f3, ..., f1024]
这些数值不再表示 RGB 颜色,而是网络提取出的抽象视觉特征。
三、输入图像为什么是 640 × 640 × 3
一张普通彩色图像有三个颜色通道:
text
R:红色
G:绿色
B:蓝色
因此,输入图片:
text
640 × 640 × 3
表示:
- 图像高度为 640 像素;
- 图像宽度为 640 像素;
- 每个像素包含 R、G、B 三个颜色值。
原始图像中的一个像素可以表示为:
text
[R, G, B]
例如:
text
[125, 86, 43]
这三个数只是在描述该像素的颜色。
目标检测需要的不只是颜色,还需要边缘、纹理、轮廓、物体部件和类别语义,所以网络需要把 RGB 信息转换为更丰富的特征表达。
四、为什么 640 × 640 × 3 会变成 320 × 320 × 64
假设第一层卷积配置为:
text
卷积核大小:3 × 3
步长 stride:2
填充 padding:1
输出通道 out_channels:64
那么输入输出关系为:
text
输入:640 × 640 × 3
↓
输出:320 × 320 × 64
这里包含两种不同的变化:
text
640 → 320:由 下采样stride = 2 造成
3 → 64:由 64 个卷积核造成
五、为什么宽高从 640 变成 320
当卷积步长为:
text
stride = 2
卷积核每次在图像上移动两个像素,而不是一个像素。
因此空间尺寸大约缩小一半:
text
640 ÷ 2 = 320
这叫作下采样。
连续下采样时:
text
640
↓ stride=2
320
↓ stride=2
160
↓ stride=2
80
↓ stride=2
40
↓ stride=2
20
因此从 640 到 20,总下采样倍数是:
text
640 ÷ 20 = 32
所以 20 × 20 这一层也常称为:
text
stride = 32 的特征层
六、为什么通道数从 3 变成 64
核心原因是:
这一层卷积设置了 64 个输出卷积核。
对于一个 3 × 3 卷积,输入有 3 个通道,所以每个卷积核的完整尺寸是:
text
3 × 3 × 3
最后一个 3 表示该卷积核会同时观察输入图像的 R、G、B 三个通道。
一个卷积核的结构可以理解为:
text
卷积核 1
├── R 通道对应的 3 × 3 权重
├── G 通道对应的 3 × 3 权重
└── B 通道对应的 3 × 3 权重
一个卷积核扫描整张图片后,会输出一张:
text
320 × 320
的特征图。
如果有 64 个不同的卷积核:
text
输入:640 × 640 × 3
│
├── 卷积核 1 → 320 × 320 特征图 1
├── 卷积核 2 → 320 × 320 特征图 2
├── 卷积核 3 → 320 × 320 特征图 3
│
├── ...
│
└── 卷积核 64 → 320 × 320 特征图 64
将这 64 张特征图叠在一起,就是:
text
320 × 320 × 64
因此有一个重要关系:
输出通道数等于该卷积层的卷积核数量。
七、一个输出位置是怎么计算出来的
假设卷积核大小为:
text
3 × 3
输入通道数为:
text
3
那么计算一个输出值时,卷积核会读取:
text
3 × 3 × 3 = 27
个输入数值。
计算过程可以简化为:
text
输出值
=
输入区域与卷积权重逐项相乘后求和
+
偏置
对于同一个空间位置:
text
卷积核 1 → 得到特征值 f1
卷积核 2 → 得到特征值 f2
卷积核 3 → 得到特征值 f3
...
卷积核 64 → 得到特征值 f64
最终,该位置会得到一个 64 维特征向量:
text
[f1, f2, f3, ..., f64]
因此:
text
320 × 320 × 64
还可以理解为:
共有
320 × 320个空间位置,每个位置由 64 个特征值描述。
八、64 个通道分别表示什么
输入的 3 个通道有明确含义:
text
R、G、B
但卷积后的 64 个通道不再对应固定颜色。
浅层通道可能分别对以下信息产生较强响应:
text
通道 1:某种横向边缘
通道 2:某种纵向边缘
通道 3:某种斜向边缘
通道 4:红色与周围颜色的变化
通道 5:局部明暗变化
通道 6:某种纹理
通道 7:某种角点
...
通道 64:另一种局部特征组合
这些功能不是人工提前规定的,而是模型在训练过程中自动学习出来的。
不能机械地认为:
text
第 1 个通道一定检测横向边缘
第 20 个通道一定检测车轮
实际网络中,一个通道可能同时响应颜色、边缘和纹理;一个高级语义也可能由多个通道共同表达。
九、通道数为什么要不断增加
典型卷积网络会采用下面的结构:
text
空间尺寸越来越小
通道数量越来越多
例如:
text
640 × 640 × 3
↓
320 × 320 × 64
↓
160 × 160 × 128
↓
80 × 80 × 256
↓
40 × 40 × 512
↓
20 × 20 × 1024
原因可以概括为:
网络不断压缩目标的空间位置表示,同时使用更多特征维度描述图像内容。
1. 浅层特征:位置多,描述简单
例如:
text
320 × 320 × 64
共有:
text
320 × 320 = 102400
个空间位置,每个位置有 64 个特征值。
浅层主要学习:
- 边缘;
- 颜色变化;
- 简单纹理;
- 角点;
- 局部方向。
可以概括为:
看得细,但理解得浅。
2. 深层特征:位置少,描述丰富
例如:
text
20 × 20 × 1024
共有:
text
20 × 20 = 400
个空间位置,但每个位置有 1024 个特征值。
深层可能综合表达:
- 是否存在车辆轮廓;
- 是否具有车头结构;
- 是否存在车轮组合;
- 是否像行人;
- 目标可能属于哪个类别;
- 目标与背景之间的关系。
可以概括为:
空间分辨率降低了,但语义理解更强。
十、20 × 20 是像素吗
可以把它称为"特征图上的像素",但更准确的说法是:
20 × 20表示 20 行、20 列的特征位置。
它不是一张普通的 RGB 小图片。
原始图像经过 32 倍下采样后:
text
640 ÷ 32 = 20
所以相邻两个特征位置在原图上的中心间隔约为 32 像素。
这被称为:
text
stride = 32
但是要区分两个概念:
步长
text
相邻特征点在原图中的中心间隔
对于 20 × 20 特征图:
text
stride ≈ 32
感受野
text
一个特征点实际能够看到的原图范围
由于深层特征经历了多次卷积,一个特征点的感受野通常远大于 32 × 32。
它可能已经看到了:
- 一辆完整汽车;
- 一个行人;
- 目标周围的道路和背景;
- 更大范围的上下文信息。
因此:
text
32 × 32 是特征点之间的采样间隔
不是该特征点只能看到的图像范围
十一、1024到底是什么
1024 是通道数。
text
20 × 20 × 1024
可以画成一摞特征图:
text
┌──────────────┐
通道 1024 │ 20×20 │
├──────────────┤
通道 1023 │ 20×20 │
├──────────────┤
│ ... │
├──────────────┤
通道 2 │ 20×20 │
├──────────────┤
通道 1 │ 20×20 │
└──────────────┘
每个通道都可以看作网络对图像的某一种观察方式。
换一个角度:
text
20 × 20 = 400 个空间位置
每个位置:
┌────────────────────────────┐
│ 1024 个特征值 │
│ 描述边缘、纹理、形状、部件、 │
│ 上下文和类别语义等信息 │
└────────────────────────────┘
因此:
text
20 × 20 × 1024
=
400 个空间位置
×
每个位置 1024 维特征
十二、为什么不一直使用 640 × 640 × 1024
因为计算量和显存占用会非常大。
假如特征尺寸为:
text
640 × 640 × 1024
元素数量为:
text
640 × 640 × 1024
=
419,430,400
如果使用 FP32,每个数占 4 字节,仅这一层特征大约需要:
text
419,430,400 × 4
≈ 1.68 GB
而:
text
20 × 20 × 1024
只有:
text
409,600
个元素,FP32 下约占:
text
409,600 × 4
≈ 1.64 MB
因此,下采样可以显著降低:
- 计算量;
- 显存占用;
- 推理时间;
- 数据传输开销。
与此同时,增加通道数可以提高网络的特征表达能力。
十三、通道增加后,数据量一定增加吗
不一定。
比较两层:
text
320 × 320 × 64
20 × 20 × 1024
元素数量分别为:
text
320 × 320 × 64
=
6,553,600
text
20 × 20 × 1024
=
409,600
虽然通道从 64 增加到 1024,是原来的 16 倍,但宽和高都缩小了 16 倍,面积缩小了:
text
16 × 16 = 256 倍
因此,深层特征的总元素数量反而更少。
十四、40 × 40 × 512 如何变成 20 × 20 × 1024
假设使用一个卷积层:
text
卷积核大小:3 × 3
输入通道:512
输出通道:1024
stride:2
输入为:
text
40 × 40 × 512
由于 stride = 2,空间尺寸减半:
text
40 × 40
↓
20 × 20
由于设置了 1024 个输出卷积核,输出通道数变为:
text
1024
最终得到:
text
20 × 20 × 1024
每个卷积核的完整尺寸为:
text
3 × 3 × 512
一共有 1024 个这样的卷积核:
text
512 个输入通道
↓
卷积核组 1 → 输出通道 1
卷积核组 2 → 输出通道 2
卷积核组 3 → 输出通道 3
...
卷积核组 1024 → 输出通道 1024
十五、从浅层到深层,特征发生了什么变化
可以将整个过程概括为:
text
原始图像
640 × 640 × 3
描述:颜色
↓
浅层特征
320 × 320 × 64
描述:边缘、明暗、颜色变化
↓
中浅层特征
160 × 160 × 128
描述:纹理、角点、简单局部形状
↓
C3
80 × 80 × 256
描述:小目标细节、局部部件
↓
C4
40 × 40 × 512
描述:目标部件与局部轮廓组合
↓
C5
20 × 20 × 1024
描述:完整目标、高级语义和上下文
一句直观的总结是:
浅层知道目标"长什么样",深层逐渐知道目标"是什么"。
十六、为什么深层特征不适合直接检测所有目标
深层特征:
text
20 × 20 × 1024
语义很强,适合判断:
- 这是汽车;
- 这是行人;
- 这是大型障碍物。
但它的空间分辨率较低。
对于原图中的小目标,经过 32 倍下采样后可能只占很小的特征区域。
例如原图中一个宽度为 12 像素的小目标:
text
12 ÷ 32 = 0.375
在 20 × 20 特征层中,它连一个完整特征格都占不到,因此容易丢失。
而 80 × 80 特征层的步长为 8:
text
12 ÷ 8 = 1.5
小目标仍然可以占据多个特征位置,更容易被检测。
十七、FPN 为什么要融合不同层级的特征
Backbone 通常输出三层重要特征:
text
C3:80 × 80 × 256
C4:40 × 40 × 512
C5:20 × 20 × 1024
它们各有优势:
| 特征层 | 空间分辨率 | 语义能力 | 更适合 |
|---|---|---|---|
| C3 | 高 | 较弱 | 小目标、细节定位 |
| C4 | 中 | 中等 | 中等目标 |
| C5 | 低 | 强 | 大目标、类别判断 |
如果只使用 C3:
text
细节丰富
但可能不知道这些细节属于什么目标
如果只使用 C5:
text
知道目标是什么
但可能丢失小目标的位置和细节
FPN 的核心思想是:
将深层特征的高级语义传递给高分辨率的浅层特征。
十八、FPN 中的特征如何流动
Backbone 输出:
text
C3:80 × 80 × 256
C4:40 × 40 × 512
C5:20 × 20 × 1024
FPN 从最深层开始。
1. C5 生成 P5
text
C5:20 × 20 × 1024
│
▼ 卷积调整
P5:20 × 20 × 256
P5 保留强语义信息,适合大目标。
2. P5 上采样并与 C4 融合
text
P5:20 × 20 × 256
│
▼ 上采样 ×2
40 × 40 × 256
│
├──────── 与 C4 融合
▼
P4:40 × 40 × 256
P4 同时具有:
- C4 的空间细节;
- C5 的高级语义。
3. P4 上采样并与 C3 融合
text
P4:40 × 40 × 256
│
▼ 上采样 ×2
80 × 80 × 256
│
├──────── 与 C3 融合
▼
P3:80 × 80 × 256
P3 同时具有:
- C3 的高分辨率;
- C4、C5 传递下来的高级语义。
因此,P3 更适合检测小目标。
完整流动方向为:
text
C5 / P5
20 × 20
│
▼ 上采样
C4 / P4
40 × 40
│
▼ 上采样
C3 / P3
80 × 80
这条路径称为:
text
Top-down Path
自顶向下路径
十九、现代 YOLO 中为什么还有 PAN
很多 YOLO 的 Neck 不只是 FPN,而是:
text
FPN + PAN
FPN 的方向是:
text
深层 → 浅层
20 × 20 → 40 × 40 → 80 × 80
主要作用:
text
把高级语义传递给高分辨率特征
PAN 的方向相反:
text
浅层 → 深层
80 × 80 → 40 × 40 → 20 × 20
主要作用:
text
把浅层较精确的定位信息重新传递给深层特征
完整过程可以简化为:
text
Backbone:
提取 C3、C4、C5
↓
FPN:
深层语义向浅层传递
↓
PAN:
浅层定位信息向深层传递
↓
Detect Head:
在三个尺度上进行检测
二十、三个检测尺度分别负责什么
以输入图片 640 × 640 为例:
P3:80 × 80
text
stride = 640 ÷ 80 = 8
相邻特征位置对应原图约 8 像素间隔,适合检测:
- 远处行人;
- 小汽车;
- 小石块;
- 小型目标。
P4:40 × 40
text
stride = 640 ÷ 40 = 16
适合检测:
- 中等大小车辆;
- 较近行人;
- 中等障碍物。
P5:20 × 20
text
stride = 640 ÷ 20 = 32
适合检测:
- 大型车辆;
- 近距离目标;
- 占据图像面积较大的物体。
需要注意:
P3、P4、P5 并不是严格地只能检测小、中、大目标,而是各自更擅长对应尺度的目标。
二十一、特征图可视化时为什么像热力图
一层特征通常有很多通道。
例如:
text
80 × 80 × 256
表示有 256 张 80 × 80 的特征图。
进行可视化时,常见方式包括:
方式一:单独显示某个通道
text
feature[0]
feature[1]
feature[2]
...
不同通道可能分别对:
- 车身边缘;
- 轮胎;
- 车窗;
- 道路边缘;
- 行人轮廓;
- 背景纹理
产生不同响应。
方式二:对所有通道求平均
text
heatmap(x, y)
=
所有通道在位置 (x, y) 的平均响应
得到一张二维热力图,用于观察模型总体关注区域。
方式三:对通道取最大值
text
heatmap(x, y)
=
max(feature[x, y, :])
用于观察每个空间位置最强的特征响应。
因此,可视化出来的图像通常不是正常 RGB 图片,而是颜色较亮或较暗的响应图。
二十二、常见误区
误区一:20 × 20 就是把原图缩成 20 × 20
不完全正确。
它确实具有 20 × 20 的空间尺寸,但其中每个位置不是普通 RGB 像素,而是一个 1024 维特征向量。
误区二:一个 20 × 20 特征点只对应原图 32 × 32
不正确。
32 是该特征层的步长,表示相邻特征点在原图上的中心间距。
由于多层卷积,一个特征点的实际感受野通常远大于 32 × 32。
误区三:1024 个通道分别对应 1024 种固定目标
不正确。
通道表示模型学习到的特征维度,不等于类别数量。
某些通道可能关注边缘,某些关注纹理,某些关注目标部件,多个通道共同组合成目标语义。
误区四:通道越多,模型一定越好
不正确。
通道增加可以提高表达能力,但也会增加:
- 参数量;
- 计算量;
- 显存占用;
- 过拟合风险。
因此,实际模型需要在速度和精度之间折中。
误区五:所有 YOLO 都固定使用 64、128、256、512、1024
不正确。
这些数字只是便于理解的典型示例。
实际通道数取决于:
- YOLO 版本;
- n、s、m、l、x 模型规模;
- width multiplier;
- Backbone 结构;
- 模型 YAML 配置。
二十三、完整特征流动总结
text
输入图像
640 × 640 × 3
描述 RGB 颜色
│
▼
第一层卷积
64 个卷积核,stride = 2
│
▼
320 × 320 × 64
提取边缘、颜色变化、简单纹理
│
▼
160 × 160 × 128
提取更复杂纹理与局部形状
│
▼
C3:80 × 80 × 256
保留较多空间细节,适合小目标
│
▼
C4:40 × 40 × 512
兼顾空间细节和语义
│
▼
C5:20 × 20 × 1024
空间分辨率低,但高级语义最强
│
▼
FPN
深层语义向浅层传递
│
▼
PAN
浅层定位信息向深层传递
│
▼
P3 / P4 / P5 多尺度检测
│
▼
输出边界框、类别和置信度
二十四、最核心的几个结论
结论一
text
640 × 640 × 3
表示一张 640 × 640 的 RGB 图像。
结论二
text
320 × 320 × 64
中的 64 来自 64 个输出卷积核:
text
一个卷积核产生一个输出通道
结论三
text
20 × 20 × 1024
表示:
text
400 个空间位置
每个位置由 1024 个特征值描述
结论四
空间尺寸减小是为了:
- 降低计算量;
- 扩大感受野;
- 提取更高级的语义。
通道数量增加是为了:
- 保存更多类型的特征;
- 提高特征表达能力;
- 描述更复杂的目标结构。
结论五
FPN 的核心作用是:
将深层的高级语义与浅层的高分辨率细节融合,使模型同时具备目标分类能力和精确定位能力。
一句话总结
YOLO 使用多个卷积核把 RGB 图像转换为多通道特征,随着网络加深,特征图空间尺寸逐渐减小、通道数逐渐增加;深层特征负责理解目标是什么,浅层特征负责保留目标在哪里,FPN 和 PAN 再将不同层级的语义与定位信息融合,最终完成多尺度目标检测。