hand_detection
TensorFlow SSD 实时手部检测:从 Egohands 数据集训练到实时推理的完整 CV
加载项目详情…
本应用为开源项目,仅供学习研究,请遵守其开源协议。
TensorFlow SSD 实时手部检测:从 Egohands 数据集训练到实时推理的完整 CV
加载项目详情…
本应用为开源项目,仅供学习研究,请遵守其开源协议。
想象一下:你坐在咖啡馆里,戴着 Google Glass,想要让设备精准识别你正在翻阅的书页——前提是它得知道你的手在哪。这种「第一人称视角下精准追踪手部位置」的需求,催生了一个在 GitHub 上获得 277 颗星、至今仍被开发者持续关注的开源项目——molyswu/hand_detection。该项目作者 vyKthour(Twitter @vykthur)并非来自任何大厂,而是一位独立开发者,他用 TensorFlow Object Detection API 完整走完了从数据集构建、模型训练到实时推理的全流程,并慷慨地将所有代码和预训练模型开源。
这个项目的价值不只是「能检测手」,而是完整还原了一个计算机视觉工程师做自定义目标检测项目的真实工作流:从爬取公开数据集、格式转换、配置训练管道,到推理优化——每一步都有可直接复用的脚本。对于想用 TensorFlow Object Detection API 训练自定义目标检测器的人来说,这个仓库几乎是教科书式的参考模板。
作者在 README 中坦率分享了踩坑过程:最早尝试 Oxford Hands Dataset,但检测效果不理想——原因在于该数据集的拍摄视角和采集场景与作者的 Egocentric(第一人称)实际需求不匹配。这是计算机视觉项目中的常见陷阱:模型容易受到训练数据和目标场景之间「域偏移」(domain shift)的影响。
转而使用的是 Egohands Dataset——由印第安纳大学发布,包含 4800 张来自 Google Glass 拍摄的高质量图像,每张图像都有像素级的手部标注,总计超过 15000 个标注框。数据集覆盖 48 种不同场景(室内室外均有),包含玩扑克牌、下棋、叠积木、拼图等活动,极大程度模拟了真实生活场景中的手部交互情况。
为了让 TensorFlow 能够加载训练,项目提供了 egohands_dataset_clean.py 脚本,负责:下载 Egohands 数据集 zip 包 → 按文件夹结构重新组织图片 → 读取每张图对应的 polygons.mat 标注文件并生成 CSV 格式的边界框坐标 → 将数据集按 80/10/10 比例划分为训练/测试/验证集。该脚本最终生成 train.record 和 test.record(TFRecord 格式),即可供 TensorFlow Object Detection API 直接消费的训练数据。
值得注意的是,Egohands 数据集原本有四个手部类别(自己的左手/右手、对方的左手/右手),但作者为了简化任务,统一合并为单一的 hand 类别。如果需要做更细粒度的手部区分,项目代码也支持修改为四个类别的训练。
在训练阶段,项目使用 TensorFlow Object Detection API 提供的预训练模型 ssd_mobilenet_v1_coco 作为起点,执行迁移学习(transfer learning)。作者的选择理由很实际:速度优先。
SSD(Single Shot MultiBox Detector)是一种单阶段目标检测算法,在速度和精度之间取得了良好的平衡。配合 MobileNet v1 作为骨干网络,大幅降低了计算量,非常适合需要实时处理摄像头流的应用场景。项目中 ssd_mobilenet_v1_coco.config 配置文件记录了所有训练超参数,而训练好的检查点保存在 model-checkpoint/model.ckpt-200002(200002 步)。
作者在 MacBook Pro(i7 2.5GHz,16GB)上对比了 CPU 和 GPU 的训练速度:CPU 每步约 5 秒,GPU(云端)每步约 0.5 秒——差了整整 10 倍。完整 200000 步训练在 CPU 上需要约 12 天,而 GPU 仅需约 5 小时。最终在 200k 步后停止训练,总 Loss 降至 2.575,作者事后认为 50k 步左右其实已经收敛得差不多了。
最终模型的评测指标:mAP@0.5 IOU = 0.9686(满分 1.0),意味着当预测框与真实框的交并比超过 50% 时,模型有近 97% 的精度。这个成绩相当出色,说明 Egohands 数据集和 SSD Mobilenet 的组合对手部检测任务非常有效。
训练完成后,通过 TensorFlow Object Detection API 的 export_inference_graph.py 脚本将检查点导出为冻结推理图 frozen_inference_graph.pb(约 22MB),保存在 hand_detection/hand_inference_graph/ 目录下。
推理端提供了两套脚本,分别对应不同的使用场景:
detect_single_threaded.py —— 单线程版本,适合处理本地视频文件(如 videos/chess.mov)。代码结构简单,通过 cv2.VideoCapture 读取视频帧,逐帧送入检测器。该脚本支持 --source 参数指定视频路径,--scorethreshold 调节置信度阈值,--display 控制是否可视化结果,--width/--height 调节输入图像分辨率。
detect_multi_threaded.py —— 多线程版本,专为实时摄像头流设计。作者借鉴了 Adrian Rosebrock(pyimagesearch)的多线程优化方案,将视频帧读取(I/O 密集)与模型推理(计算密集)分离到独立线程,通过 Queue 队列通信。这样可以避免 cv2.VideoCapture.read() 的 I/O 阻塞拖慢整个推理 pipeline,实测 FPS 提升约 5 帧。
核心检测逻辑封装在 utils/detector_utils.py 的 detect_objects 函数中,返回边界框坐标、置信度分数、类别 ID 和检测数量;draw_box_on_image 函数负责在图像上绘制检测结果。
作者给出了在不同分辨率下的实测性能数据:
| 分辨率 | 设备 | 条件 | FPS |
|---|---|---|---|
| 320×240 | MacBook Pro i7 | 不可视化 | 21 |
| 320×240 | MacBook Pro i7 | 可视化 | 16 |
| 640×480 | MacBook Pro i7 | 可视化 | 11 |
这个性能意味着:在普通笔记本 CPU 上,用 320×240 分辨率处理摄像头流,可以做到实时(>16fps)的流畅检测。
项目中还记录了几个非常实用的避坑经验:
BGR 转 RGB:OpenCV 读取的图像默认是 BGR 格式,而 TensorFlow/预训练模型通常期望 RGB 输入。如果不转换,检测精度会显著下降(这是新手常见错误)。正确做法是在推理前执行 cv2.cvtColor(image_np, cv2.COLOR_BGR2RGB)。
分辨率与速度权衡:将输入图像缩小到 320×240,比原生的 1280×720 提速约 16 倍(分辨率面积差了 16 倍),但检测精度几乎不受影响。这对于追求实时性的场景非常重要。
8 位量化:模型当前为 32 位浮点,量化到 8 位定点后内存占用可减少 4 倍,结合 TensorFlow Lite 可以在移动端或边缘设备上部署。这是作者提到的未来优化方向。
作者也坦诚地指出了项目的局限性:训练数据全部来自 Egocentric(第一人称)视角,因此非第一人称视角的检测效果会明显下降。此外,在背景复杂(大量手部重叠,如「手海」场景)或特殊肤色条件下的表现也会有所退化。
对于想复用的开发者来说,最关键的限制是TensorFlow 版本锁定:项目明确在 TensorFlow 1.4.0-rc0 下开发和测试。升级到 TF2.x 会遇到 API 不兼容问题,虽然有预训练的 frozen graph 可以直接使用,但如果你需要从 checkpoint 重新训练,就得使用兼容版本。
从代码结构来看,整个项目的技术栈非常清晰:
.mat 标注文件解析)、scikit-image.pb 文件)代码组织方面,hand_detection/ 是核心推理目录,utils/detector_utils.py 封装了图加载、推理执行、可视化绘制等通用工具,utils/label_map_util.py 来自 TensorFlow Object Detection API,protos/ 目录包含 protobuf 协议定义文件(编译为 .pb2.py)。model-checkpoint/ 保存了训练中间检查点,可用于恢复训练或导出其他格式。
这个项目没有 Web UI,也没有 Docker 支持,需要通过命令行运行。最大的门槛是正确安装 TensorFlow Object Detection API——这本身就需要先安装 TensorFlow、下载 models 仓库、编译 protobuf 文件、配置 PYTHONPATH 等一系列步骤。
如果你只是想使用预训练模型做推理(而不是重新训练),流程相对简单:
hand_detection 目录python detect_multi_threaded.py --display 即可启动摄像头实时检测如果你想训练自己的检测器,就需要额外安装 TensorFlow Object Detection API,并准备好符合 VOC/Pascal 格式的自定义数据集,整个流程需要数小时到数天不等。
molyswu/hand_detection 虽然聚焦于「手部检测」这个具体任务,但其方法论和代码模板具有极强的可扩展性。同样的流程稍作修改,即可训练出检测人脸、车辆、工业零件等任何自定义目标。GitHub 上数百个 fork 和持续的关注度,证明了它在开源计算机视觉教育领域的标杆地位。
该项目代表了 2017-2018 年间深度学习目标检测从学术走向应用的一个缩影:用 SSD 做速度,用迁移学习弥补数据不足,用多线程榨干 CPU 性能——每一个工程决策都透着「在有限算力下追求实用」的务实精神。对于今天已经进入 Transformer 和 Foundation Model 时代的从业者来说,这种从零构建完整 CV pipeline 的经验依然值得学习。