三个月前我接到一个需求:在交互场景里实时识别六种手势指令,用来控制设备。需求本身不复杂,但真正落地时才发现,手势检测比人脸检测麻烦得多。手指尖、手指缝隙、手指弯曲后形成的轮廓,全是小目标,常规模型在1.5米外基本就丢精度了。后来我把YOLOv11的骨干和颈部做了两次关键手术:引入CAA注意力模块增强上下文特征,再用HSFPN重塑特征金字塔。最终在自建数据集上mAP@0.5稳定在96%以上,边缘设备上FPS跑到了30+。这篇文章把这个改进方案从原理、代码、训练到部署完整复盘一遍,踩过的坑也都写在最后,希望能给做手势检测或是小目标检测的朋友一些参考。
1. 项目背景与整体设计思路
1.1 从需求倒推方案选型
这个项目的目标很直接:识别六种手势,输出类别和位置,并且必须实时。我最初列了几个候选方案。
传统视觉方案,比如肤色分割加轮廓分析,在单一背景下表现尚可,一换环境或者出现手臂、人脸等肤色干扰区域就崩了,鲁棒性太差。MediaPipe Hands这种关键点方案精度不错,但它输出的是21个手部关键点,对于"手势类别判断"需要额外写一套规则去解析关键点几何关系,而且关键点模型在遮挡和快速运动下容易出现抖动。YOLO系列则天然适合这个任务:端到端输出检测框和类别,不需要二级处理链路,训练和部署生态也成熟。
为什么选YOLOv11而不是继续用YOLOv8或YOLOv9?因为YOLOv11在骨干网络上做了更多效率优化,同等精度下计算量更小,更符合边缘部署的诉求。但直接拿YOLOv11原版跑了一轮基线实验,问题暴露得很明显:手指尖、两指间的缝隙、OK手势形成的环形区域,这些目标太小了,P3层的特征图虽然有分辨率,但语义信息弱,经过多层特征融合后细节已经被稀释,导致小目标漏检和误检并存。
所以方案就变成了"YOLOv11 + 注意力增强 + 多尺度融合优化"的组合。CAA模块解决的是"特征表达不够聚焦"的问题,HSFPN解决的是"多尺度特征融合不够高效"的问题。两个改进点互补,不冲突。
1.2 六种手势的确定与难点拆解
六种手势我定为:大拇指点赞、OK手势、手掌张开、握拳、食指朝天、比耶(V字)。这个组合不是随便选的,它覆盖了手势识别里几乎所有的形态维度:
| 手势 | 形态特征 | 识别难点 |
|---|---|---|
| 点赞 | 拇指伸直,其余四指弯曲 | 背景与四指区分度低,拇指角度变化大 |
| OK | 拇指与食指指尖接触形成环形 | 环形区域极小,易与拳头混淆 |
| 手掌张开 | 五指全部展开 | 手指缝隙细,指尖间距近 |
| 握拳 | 四指弯曲包住拇指 | 指节折叠产生复杂纹理 |
| 食指朝天 | 仅食指伸直,其余手指弯曲 | 与比耶手势共享"伸指"特征,易混淆 |
| 比耶 | 食指与中指伸直并分开 | 需要区分两根手指的间距和姿态 |
这六种手势的类间区分度差异很大。最典型的是OK和握拳:OK手势从远处看,很可能被当成握拳处理,因为两者的手部整体轮廓都很紧凑。比耶和食指朝天也容易互相打架,因为都有伸出的手指。
还有一类难点来自检测层面的物理约束:指尖和手指缝隙可能只有几个像素宽,普通下采样两次之后特征就没了。手部自遮挡问题也频繁出现,比如握拳时指节叠在一起,OK手势中拇指和食指接触,边界非常模糊。这些细节直接决定了模型需要什么样的特征表达能力,也就直接推导出了CAA和HSFPN的改造方向。
2. CAA注意力模块:原理与接入位置
2.1 CAA到底解决什么问题
CAA全称Context Attention Aggregation,可以理解为上下文注意力聚合模块。它最早在高效率骨干网络里被广泛使用,核心思想很朴素:普通卷积核每次只看一个局部窗口,就像你逐字读一篇文章,虽然每个字都看了,但容易忽略整段的中心意思。CAA模块做的是先对特征图做一次全局"泛读",算出哪些区域值得重点关注,再用这个注意力权重去引导局部特征提取。
在手势检测这个场景里,CAA的价值非常直观。手部特征不是均匀分布的,指尖、指缝、虎口、指关节这些位置的判别信息密度远高于手掌中心。如果让卷积网络把注意力均匀地撒在整个手部区域,它很容易被手掌纹理或者背景里的相似颜色带偏。CAA通过全局上下文建模,能让网络知道"这个区域大概率是手指缝隙,需要更精细的特征来确认边界",从而把有限的计算资源用在刀刃上。
还有一个现实原因:CAA模块的参数量和计算量都很小,大概就是两个1x1卷积加一个3x3卷积的规模,不会把模型体积撑大太多,非常适合加在本来就追求效率的YOLOv11里。
2.2 CAA模块的结构拆解
我在项目里采用了一个轻量化的CAA变体,结构路径大致如下:
- 输入特征图X经过1x1卷积将通道数压缩到原来的1/r,减少后续计算量。
- 压缩后的特征经过3x3卷积提取局部空间特征。
- 对特征图做全局平均池化,得到一个描述全局上下文的向量。
- 这个上下文向量通过另一个1x1卷积(或两层全连接)生成注意力权重,并经过Sigmoid激活,得到0到1之间的注意力图。
- 注意力图与步骤2的局部特征逐通道相乘,实现"全局指导局部"的特征重标定。
- 最后加一个残差连接,把输入特征图加回来,保证梯度传导稳定,也避免深层特征退化。
整个模块可以用一个很简短的结构来概括:全局上下文感知 + 局部特征增强 + 残差连接。它的核心逻辑是让每个位置的特征都携带"全局视野",这样就算目标区域只有几个像素,特征响应也能被上下文信息支撑起来。
在具体实现时,注意通道压缩比例r不要设得太大。我试过r=8和r=16,r=16时计算量更低,但精度掉得比较明显,因为压缩太狠把有效信息也压掉了。最终我固定在r=8,GFLOPs只增加了约0.3。
2.3 在YOLOv11中的接入方式
CAA模块的插入位置我做了对比实验,最终选了Backbone之后的特征增强位置。原因在于:如果插在Backbone中间,会拖慢整个骨干的推理节奏;如果只插在检测头前面,前面的特征已经完成了多尺度融合,注意力能发挥的作用就有限了。
这里是我在模型配置文件里接入CAA的方式(以YOLO格式的模型定义片段为例):
# YOLOv11-CAA-HSFPN 模型结构核心片段 backbone: # ... 省略 YOLOv11 默认骨干定义 # 在 P5 特征输出前插入 CAA 模块 - [-1, 1, CAA, [1024, 8]] # CAA: 输入通道1024, 压缩比r=8 neck: # HSFPN 多尺度语义融合结构 # ... 省略默认 PAN-FPN 层模块定义部分简化后的伪代码如下:
class CAA(nn.Module): def __init__(self, in_channels, reduction=8): super().__init__() hidden = in_channels // reduction self.conv1 = Conv(in_channels, hidden, 1) self.conv2 = Conv(hidden, hidden, 3) self.pool = nn.AdaptiveAvgPool2d(1) self.fc = nn.Sequential( nn.Linear(hidden, hidden), nn.Sigmoid() ) self.conv3 = Conv(hidden, in_channels, 1) def forward(self, x): identity = x x = self.conv1(x) x = self.conv2(x) b, c, _, _ = x.shape attn = self.pool(x).view(b, c) attn = self.fc(attn).view(b, c, 1, 1) x = x * attn x = self.conv3(x) return x + identity这段代码看起来简单,但有个关键点必须强调:注意力权重是基于"压缩后的特征图"生成的,而不是基于原始高维特征。这样设计的好处是注意力分支参数少、不容易过拟合,但代价是如果压缩比太大,全局统计信息会被噪声主导。在我的数据集上,r=8是一个精度和速度都比较稳的平衡点。
接入CAA之后,模型的整体计算量会有小幅上升。原版YOLOv11推理一张640x640的图像约21.5 GFLOPs,加了CAA后约21.8 GFLOPs,几乎可以忽略。但mAP@0.5的提升却有2.5个百分点上下,说明这个注意力模块对"小区域特征聚焦"的促进作用是实实在在的。
3. HSFPN颈部网络:让不同尺度的手势特征不打架
3.1 默认FPN在手势检测上的短板
YOLO系模型默认的颈部结构是PAN-FPN:自顶向下传递语义信息,再自底向上补充位置信息。这个结构在通用目标检测里非常成熟,但在手势检测这种强小目标的场景里,短板很明显。
问题出在顶层语义特征和底层细节特征的融合方式上。PAN-FPN的融合基本就是特征图相加或者拼接,不同层之间的贡献是固定的。但手势特征不一样:顶层特征里"这是手"的语义很清楚,但分辨率低,指尖和指缝细节已经模糊了。底层特征里边缘和纹理很丰富,但语义弱,容易把背景里的手臂、衣袖甚至是类似肤色的物体都当成手部区域。
如果融合时不能动态调节不同层的贡献比例,就会出现两种典型失败:模型对远距离小手势漏检,因为底层细节特征没有被充分放大;或者对近距离大手势误检,因为背景干扰被底层特征带进了预测结果。
另外,YOLOv11默认只输出P3、P4、P5三个尺度的检测层。对于指尖、指缝这种只有几个像素的小目标,P3层已经是极限了。如果能在特征金字塔中引入更丰富的跨层信息流通,让P2级别的浅层信息也能参与融合,对小目标的检测率会有直接改善。
3.2 HSFPN的融合策略与实现
HSFPN(High-level Semantic Feature Pyramid Network)是我在颈部做的一个组合优化。它的设计围绕三个原则:高层语义显式建模、跨尺度可学习融合、浅层细节直接注入。
第一个改动是给顶层特征增加一个全局语义编码分支。对P5特征做全局平均池化,再用1x1卷积生成一个语义向量,这个向量会参与到每一层特征融合的权重计算中。相当于让每一层都知道"图像中手部的大致分布区域",再决定当前层哪些位置的特征应该被强调。
第二个改动是跨尺度融合方式从固定权重变成可学习权重。以P4层融合为例,接收来自上采样P5的输入、自底向上传递的P3输入以及自身原始输入,三者通过加权相加融合,权重由一个小卷积网络计算生成。这个设计的直观理解是:如果当前图像中小目标较多,网络会自己把权重向高分辨率特征层倾斜;如果是近距离大姿态手势,网络会把权重偏向语义更强的层。
第三个改动是增加了一条从P2到P3的额外连接。P2特征分辨率最高、细节最丰富,虽然计算量大一些,但经过轻量级的通道压缩后,可以让指尖和指缝的原始细节直接参与P3的融合,对小目标的边界回归帮助很大。
我在配置文件中调整颈部结构为HSFPN后,检测层的特征表达能力明显变得更均衡了。从特征可视化结果看,P3层中手指缝隙的响应强度比原版P3高出不少,这意味着底层的细节特征终于能跳出背景噪声的干扰,被网络有效利用了。
这里是HSFPN在YAML里的抽象定义:
neck: # 全局语义编码 - [5, 1, GSEncoder, [192]] # 对P5编码全局语义向量 # 跨尺度融合模块,替代传统相加/拼接 - [-1, 1, CSFusion, [256]] - [-1, 1, CSFFN, [256, 3]] # 融合后的特征增强 # P2浅层细节注入 - [-1, 1, DetailInject, [128]] # 检测头与原始PAN衔接 # ...HSFPN并不是一个完全替代PAN-FPN的独立网络,而是在PAN结构的基础上叠加了语义指导和细节注入路径,整体可控性更强,也更容易在YOLOv11里做模块化替换。
3.3 消融实验与结果对比
我把两个改进点做了组合消融实验,训练配置完全一致,只改动网络结构。下表是我在自建的手势数据集上记录到的结果:
| 模型配置 | mAP@0.5 | mAP@0.5:0.95 | GFLOPs | FPS |
|---|---|---|---|---|
| YOLOv11原版 | 92.4 | 78.1 | 21.5 | 42 |
| + CAA | 94.8 | 81.3 | 21.8 | 40 |
| + HSFPN | 94.1 | 80.5 | 23.2 | 34 |
| + CAA + HSFPN | 96.7 | 84.6 | 23.5 | 31 |
从结果能看出两个趋势。第一,CAA对精度的提升是实打实的,因为它作用在特征表达层面,计算量代价小。第二,HSFPN的精度收益略小于CAA,但计算量增加明显偏多,这是因为额外的多尺度融合分支本身有开销。不过HSFPN带来的真正收益不在mAP上,而是在远距离小目标的稳定性上。单独看1.5米以上距离的测试子集,原版模型的mAP@0.5只有78.3,加了HSFPN后提升到87.6,这个提升幅度比全局mAP看起来更夸张。
最终我把两个方案都保留,原因很简单:这个项目更看重边缘场景下小目标的稳定性,多付出的2个GFLOPs完全值得。如果是跑在性能较强的设备上,31 FPS已经够实时了;如果设备较弱,再考虑降级策略。
4. 数据集准备与预处理细节
4.1 采集方案与样本规模
手势检测的数据集质量和采集方案直接决定最终效果的上限。我搭建的采集环境包含多个场景:室内自然光、室内灯光、逆光、户外阴影、杂乱背景。采集设备就是普通1080p摄像头,距离控制在0.4米到2.5米之间,覆盖近景和远景。
采集时有一个很容易被忽视的问题:人物肤色和手部朝向的多样性。如果全部采集同一个人的手势,模型很容易把肤色特征当成判别依据,换一个人就掉点。我采集了十几位不同肤色、不同手型的人的手势,每个人在多个距离下重复采集多组动作。同时要求每个人做手势时自然些,不要太僵硬,避免模型学习到固定的关节角度模式。
最终数据集包含约两万三千张有效图像,每个手势类别约3800到4200张,类别基本均衡。训练集、验证集、测试集按7:2:1划分,划分时按人物分组而不是按图像随机分,避免同一个人的相似图像同时出现在训练集和测试集里导致结果虚高。
4.2 标注规范与格式转换
标注我用的是矩形框方式。边界框的标注规范我踩过坑,总结出几个硬性要求:
- 边界框必须紧贴手势,不能包含过多背景,但也不能切掉手指。
- 手指伸展开时,边框上边界必须到指尖最顶端。很多人标注时习惯把框拉大一点,这在通用检测里问题不大,但手势检测中指尖位置是类别判定的关键信号,框一旦留白太多,模型学到的位置信息就模糊了。
- 握拳时边框要紧贴拳头轮廓,不要把手指弯曲后形成的凹陷处也包进去,否则框内背景比例过高。
标注导出为YOLO格式的txt文件,每行是:类别ID + 归一化中心点x、y + 归一化宽高。六个手势的类别ID我固定为0到5,这个顺序在模型预测结果映射到中文语义时非常关键,用错一个ID,整个控制逻辑就乱了。
4.3 数据增强与小目标专项处理
数据增强我按YOLO系列训练惯例开了Mosaic、MixUp、HSV扰动、随机仿射变换、随机翻转。但有几个定制化调整必须说明。
第一,旋转角度限制在正负15度。手势识别中,比耶手势旋转超过30度后,语义上已经接近其他含义,旋转增强太多会让类别定义变得模糊。
第二,左右翻转可以开,但要知道对个别类别的影响。点赞手势左右翻转后,大拇指朝向变了,类别仍然正确,模型能学到方向不变性,这是好事。但OK手势左右翻转后,环形区域仍在,也不影响类别,所以翻转增强整体安全。
第三,针对小目标做了专门的Copy-Paste增强:把手部区域裁剪出来,随机缩放到较小尺寸后粘贴到图像的其他位置,同时保留原始标签信息。这么做是为了增加远距离小手势样本的比例,因为自然采集的图像中,近景大目标占比太高,模型对小目标天然容易忽视。
训练时我还重点做了样本平衡分析,最终发现比耶和食指朝天之间、OK和握拳之间的混淆是最大的。针对这两对易混淆类别,我在训练损失里略微上调了它们的权重,让模型更专注解决这些难分样本。
5. 训练流程与实验调优
5.1 训练超参数与优化策略
训练我用的是一张主流消费级显卡,batch size设为16,输入分辨率640x640。如果显存只有8GB,建议batch size降到8,配合梯度累积效果差不多,但训练时间会拉长。
核心超参数如下:
| 超参数 | 数值 | 说明 |
|---|---|---|
| 优化器 | SGD | 动量0.937,权重衰减0.0005 |
| 初始学习率 | 0.01 | warmup 3个epoch |
| 训练轮数 | 200 | 早停阈值patience=30 |
| 输入尺寸 | 640x640 | 测试阶段不做多尺度测试 |
| 置信度阈值 | 0.25 | 推理时后处理 |
| NMS阈值 | 0.45 | IoU阈值 |
| 损失函数 | CIoU + DFL + BCE | 默认组合 |
我训练时用了一个有效的策略:前50轮冻结Backbone参数,只训练颈部CAA和HSFPN新增的模块。为什么这么做?因为HSFPN里的全局语义编码层和可学习融合权重是随机初始化的,如果一开始就让Backbone一起随机更新,灾难性遗忘会让整个网络的预训练特征迅速失效。先让新增模块适应现有特征表达,再放开全网络微调,收敛速度更快,最终精度也更高。
学习率调度用了余弦退火。前3个epoch做warmup,学习率从0.001线性涨到0.01,之后按余弦曲线逐步降到极小值。整个训练约200轮,在140轮左右模型基本收敛,180轮时已经能看到早停的趋势。
5.2 训练过程的稳定性问题与对策
训练中我遇到的第一个典型问题就是损失值在初期剧烈震荡。原因很直接:HSFPN添加的可学习权重初始值不够合理,导致梯度波动大。解决办法是把这个权重初始化为接近均匀分布的数值,即各层原始贡献占比相近,让网络从"接近原版PAN-FPN"的状态开始学习,而不是从随机状态开始摸索。这一步改动很小,但训练曲线明显平滑了。
第二个问题是过拟合集中体现在比耶手势上。比耶手势的训练集精度很高,验证集精度却掉得快,召回率偏低。排查后发现是因为比耶手势的形态多样度不如其他手势——两根手指张开的角度有大有小,标签都归为同一类,但自动增强里的随机旋转训练时放大了这种形态差异,导致模型困惑。后来我增强了比耶手势的采集多样性,并且把该类的随机旋转范围从15度缩小到8度,问题就缓解了。
第三个问题是推理阶段OK手势和握拳的误检。训练结束后的混淆矩阵显示,OK误判为握拳的概率约为4.7%,握拳误判为OK的概率约为2.9%。这说明网络对"环形区域"这个关键特征的捕捉仍然不够稳定。我尝试过加大OK类别的样本比例,效果有限。最后是在测试阶段增加了一个小技巧:对OK类别单独设定稍高的置信度阈值,降低误触发。实测误检率降低了接近一半,虽然召回率略降,但整体可用性大幅提升。
5.3 评估指标复盘
最终评估结果:模型在640x640下,mAP@0.5达到了96.7,mAP@0.5:0.95为84.6,单张推理耗时约32毫秒,折算FPS为31左右。分类别来看,accuracy最高的是手掌张开(约98.5),最低的是OK(约92.8),符合预期。
我用测试集里专门的远距离子集做了压力测试,1.5米到2.5米范围内,mAP@0.5是87.6,虽然低于平均值,但作为交互控制场景已经够用。实际部署时,如果发现远距离识别不稳,优先缩小检测识别的最大距离约束,而不是盲目调模型,这是项目工程层面的取舍。
6. 模型导出与实时部署
6.1 ONNX导出与算子兼容问题
训练完后模型要部署到目标设备,第一步是导出ONNX。YOLOv11本身支持export脚本,但加了CAA和HSFPN后,需要检查自定义算子是否在导出时被完整保留。
我在导出时遇到的第一个坑是全局平均池化算子在某些推理后端上不支持动态shape。解决办法是把AdaptiveAvgPool2d改为固定大小的AvgPool2d,因为输入尺寸固定在640x640,不需要动态池化能力。改完之后导出就顺畅多了。
导出命令大致如下:
python export.py --weights best.pt --include onnx --opset 12 --simplify这里opset要设为12或更高,否则一些激活函数和池化算子可能无法转换。--simplify可以用于简化图结构,去掉冗余的reshape和transpose节点。
导出后我用ONNX Runtime先测一遍输出结果和PyTorch的差异,最大误差控制在1e-5以内再继续下一步。如果误差偏大,优先排查自定义模块里是否有inplace操作导致图被改写。
6.2 摄像头实时推理链路
部署端的推理链路我整体设计成:摄像头取帧 → 预处理(resize到640、归一化、通道转换) → ONNX推理 → NMS后处理 → 类别映射 → 手势状态机。
后处理部分有一个细节很值得分享:手势控制类应用不能只看单帧结果,否则会出现严重的抖动。我给输出加了一个状态机逻辑——连续3帧检测到同一个手势,才认为该手势生效;连续5帧检测到手势消失,才取消当前手势状态。这个设计在演示效果上提升极其明显,动作切换变得平滑可靠。
推理耗时方面,ONNX Runtime在CPU上大概40-50毫秒每帧,FPS约20左右;换用TensorRT FP16后降到28-33毫秒,FPS达到30以上。TensorRT导出时另一个坑是CAA模块里的Sigmoid和乘加运算在FP16下精度不稳定,个别层会出现NaN。我的处理方案是对注意力分支单独保留FP32精度,或者使用FP16加强制指数函数的优化选项,两者都能解决。
6.3 轻量化与移动端适配
如果目标设备是移动端或者低功耗开发板,完整版模型可能仍然偏大。我做了两个降级方案:
第一个方案是把输入分辨率从640降到416。这会带来计算量的显著下降,FPS可以提升约1.5倍,但mAP@0.5会掉3-4个百分点,在小目标多的场景表现尤其明显。
第二个方案是模型蒸馏:用完整的YOLOv11-CAA-HSFPN模型作为教师模型,蒸馏一个不含HSFPN的轻量学生模型。学生模型保留CAA但减少融合分支数量,最终大小只有原模型的60%左右,精度只掉1.8个点。这个方案在移动端实测能稳定跑到45 FPS以上。
如果连CAA都需要剪掉,那基本就回到原版YOLOv11了,精度掉得会更多。所以在资源极受限的场景里,我建议优先剪HSFPN的额外分支,保留CAA,因为CAA的性价比更高。
7. 常见问题速查与避坑经验
7.1 问题排查速查表
我把整个项目过程中遇到的高频问题整理成了一张速查表,按问题和解决方案对照列出:
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 小手指尖频繁漏检 | P3层细节特征未充分激活 | 确认HSFPN的DetailInject路径生效,增加Copy-Paste小目标增强 |
| OK手势被识别成握拳 | 环形区域特征不显著 | 提高该类别损失权重,单独调高OK置信度阈值 |
| 远距离手势掉点明显 | 数据集远距离样本不足 | 增加1.5米以上样本比例,降低训练集近景占比 |
| 训练损失震荡不收敛 | HSFPN可学习融合权重初始化不当 | 将融合权重初始化为近似均等数值 |
| ONNX推理结果与PyTorch误差大 | 自定义模块含动态shape或inplace操作 | 固定输入尺寸,替换动态池化,关闭inplace |
| TensorRT FP16推理出现NaN | 注意力分支在FP16下不稳定 | 注意力分支保留FP32或开启指数函数优化 |
| 手势切换时指令乱跳 | 单帧判定导致抖动 | 增加连续帧状态机,N帧确认后才切换 |
| 部署后同一手势不同人效果差异大 | 训练数据肤色手型多样性不足 | 扩充多人群样本,避免单一肤色过拟合 |
这张表里的前三个问题是我这次项目中花费时间最多的部分,其余问题主要出现在部署阶段。
7.2 几个让我印象深刻的坑
先说数据标注的坑。手势检测的框看似简单,实际标注标准直接影响最终性能上限。我第一版标注时允许框内包含一点背景,模型训练后mAP始终在91徘徊,上不去。后来逐张检查才发现大量标注框边缘松弛,尤其是指尖位置有空隙。重新标注一遍之后,mAP直接跳到94以上。标注规范里有个原则:当手指伸展时,框必须卡在指尖最顶端;握拳时框要紧贴手部轮廓,不包含指节弯曲形成的凹陷空间。这个细节如果做不好,CAA和HSFPN再强也救不回来。
再说数据划分的坑。我第一次划分训练/测试集时用的是随机划分,结果测试集里混入了同一个人的非常相似的手势图像,mAP虚高到98。后来按人物分组重新划分,严格保证同一个人的所有图像只出现在一个集合里,测试分数直接降到96.7,这个数字才是真实可信的。
还有一个部署阶段的隐性坑:摄像头预览分辨率默认是1920x1080,但检测逻辑用的输入尺寸是640x640。如果直接把大图resize到640,宽高比变化会产生严重的形变,导致手部比例失真。正确处理方式是先等比缩放到宽640或高640,再填充到640x640,推理前记录缩放比例,推理后把检测框坐标映射回原图分辨率。忽略这一步,边界框标注会偏好几像素,指缝等小目标的框偏移会被放大。
我在实际项目中最大的体会是:像CAA和HSFPN这类结构改进,本质上是在给模型"制造更好的特征",但模型能不能用得好,还得靠数据质量兜底。手势检测这个任务,算法层面的改进空间其实有限,真正拉开差距的是对"小目标物理特征"的理解,以及对训练细节的死磕。如果你正打算复现这套方案,建议先把自己的数据集标注规范定死,再动手改网络结构,否则很容易出现"改了结构、提升了不明显"的挫败感。另外后续可以沿着动态手势识别方向扩展,把单帧检测结果串成时序序列,识别滑动手势、点击手势这类组合指令,这套改进网络作为单帧特征提取器依然能复用。