
简介这是一套面向计算机、电子信息等专业学生及初学者的交警指挥手势识别项目源码包可作为课程设计、期末大作业或毕业设计的参考方案也适合希望入门计算机视觉与深度学习实战的开发者练手。资源共34个文件以31个Python脚本为核心辅以readme说明文档、gitignore配置与演示gif压缩包约4.42MB体量轻便易于本地运行调试。代码围绕手势识别任务展开涵盖数据预处理、关键点提取、姿态估计网络、手势分类模型以及训练与预测评估等模块目录划分清晰便于按流程理解从视频骨架提取到手势结果输出的完整链路。目前已有190人学习关注说明该方向具备一定实用价值。读者可借助完整源码与配套手势数据集快速复现训练与推理流程并在此基础上尝试替换网络结构或扩展识别类别积累项目调试与算法优化经验。1. 交警指挥手势识别从一份 Python 源码和数据集说起路口摄像头拍到的画面里交警抬手、摆臂、转身动作幅度大、背景却乱光照还随时间段剧烈变化。想把这类手势实时识别出来靠传统图像处理基本没戏主流做法是用深度学习做骨架关键点或目标检测。这份「基于 Python 的交警指挥手势识别算法源码 手势数据集」正好切中两个最费时间的环节一是标注好的手势数据集二是能直接跑通的训练与推理代码。它适合两类人想入门手势识别但卡在数据准备上的新手以及需要快速搭一个可演示原型的在职工程师。下面我按「数据长什么样 → 模型怎么选 → 代码怎么跑 → 坑在哪」的顺序把这条链路拆开讲清楚能抄的地方直接给命令和参数。2. 手势数据集与算法选型先看清原料再定模型2.1 交警手势数据集通常包含什么交警指挥手势一般有八种标准动作停止、直行、左转弯、左转弯待转、右转弯、变道、减速慢行、靠边停车。数据集的组织方式直接决定你后面用哪种模型。常见做法是两种格式并存一种是按类别分文件夹的原始图像另一种是标注了边界框的 YOLO 格式 txt或者标注了手部关键点的坐标文件。拿到数据集先别急着训练先跑一遍统计确认类别是否均衡、图像分辨率和标注质量。下面这段脚本用来快速盘点数据集结构是每次拿到新数据我都会先跑的一步。import os from collections import Counter # 数据集根目录按类别分子文件夹 root dataset/train counter Counter() for cls in sorted(os.listdir(root)): cls_dir os.path.join(root, cls) if not os.path.isdir(cls_dir): continue imgs [f for f in os.listdir(cls_dir) if f.lower().endswith((.jpg, .png, .jpeg))] counter[cls] len(imgs) total sum(counter.values()) for cls, n in counter.items(): # 打印每类数量和占比占比过低说明该类需要补充或做增强 print(f{cls:12s} {n:5d} {n/total*100:5.1f}%) print(total:, total)逻辑说明遍历每个类别文件夹统计图片数输出占比。参数上root指向你的训练集路径如果数据集是 YOLO 格式图片和标签通常分开放这时要改成同时检查images和labels两个目录确认每张图都有对应 txt。占比低于 5% 的类别训练时容易被模型忽略需要过采样或针对性增强。2.2 骨架关键点还是目标检测两条路线的取舍手势识别落地主要有两条技术路线选错了后面全是返工。第一条是目标检测路线用 YOLO 系列直接把手势当成一个类别框出来。优点是实现简单、推理快、对背景不敏感缺点是只能给出「这是什么手势」给不出手指和手臂的姿态细节遇到相似手势比如左转弯和左转弯待转容易混。第二条是骨架关键点路线先用 MediaPipe 或类似方案提取手部和手臂的关键点再把关键点序列送进分类网络。优点是能刻画动作细节对相似手势区分度更高缺点是对遮挡和关键点检测精度依赖大摄像头角度一变关键点抖动会直接拉低准确率。我的建议是如果只是做一个能演示的原型优先走 YOLO 检测路线出结果快如果要做精细动作区分再上关键点方案。两者也可以结合检测框定位手部区域再在框内做关键点提取这样能减少背景干扰。2.3 用 YOLO 训练手势检测模型的最小流程确定走检测路线后第一步是把数据集整理成 YOLO 要求的目录结构然后写数据配置文件。下面是训练的核心命令和配置。# data.yaml path: ./dataset train: images/train val: images/val nc: 8 names: [stop, straight, left, left_wait, right, change_lane, slow, pull_over]# 安装依赖并启动训练 pip install ultralytics yolo detect train modelyolov8n.pt datadata.yaml epochs100 imgsize640 batch16逻辑说明data.yaml里nc是类别数必须和names长度一致写错会直接报维度不匹配。imgsize640是输入分辨率手势目标通常占画面比例不大分辨率太低会丢细节太高显存吃紧。batch16是常见起点显存不够就往下调到 8 或 4。epochs100对几百到几千张图的数据集通常够用但要看验证集 loss 是否还在下降别死守这个数。训练完在runs/detect/train/weights/下会得到best.pt这是后面推理要用的权重。验证时重点看混淆矩阵相似手势之间的误判是最需要盯的地方。3. 推理与部署把训练好的模型跑成可用接口3.1 单张图片和视频流的推理代码模型训练完只是第一步真正要用起来得能处理图片和视频流。下面这段代码同时覆盖单图和摄像头两种输入是部署前必跑通的验证。from ultralytics import YOLO import cv2 model YOLO(runs/detect/train/weights/best.pt) # 单张图片推理 results model(test.jpg, conf0.5) for r in results: # boxes 里含类别、置信度、坐标 for box in r.boxes: cls_id int(box.cls[0]) conf float(box.conf[0]) print(model.names[cls_id], round(conf, 3)) # 摄像头实时推理 cap cv2.VideoCapture(0) while cap.isOpened(): ok, frame cap.read() if not ok: break res model(frame, conf0.5, verboseFalse) annotated res[0].plot() # 把框和标签画回画面 cv2.imshow(gesture, annotated) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()逻辑说明conf0.5是置信度阈值低于它的框会被丢弃。手势识别里这个值很关键调高会漏检调低会误检建议在验证集上从 0.3 到 0.7 扫一遍找平衡点。verboseFalse关掉每帧的日志输出实时推理时能明显降低控制台开销。res[0].plot()直接返回画好框的图像省去手动画框的代码。3.2 关键点方案MediaPipe 提取手部骨架如果走关键点路线MediaPipe 是目前上手最快的选择它能在 CPU 上实时跑出手部 21 个关键点。下面是把关键点提取出来并做简单分类输入的骨架代码。import cv2 import mediapipe as mp import numpy as np mp_hands mp.solutions.hands hands mp_hands.Hands( static_image_modeFalse, max_num_hands1, # 交警手势通常单手限制数量能提速 min_detection_confidence0.5, min_tracking_confidence0.5, ) cap cv2.VideoCapture(0) while cap.isOpened(): ok, frame cap.read() if not ok: break rgb cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) result hands.process(rgb) if result.multi_hand_landmarks: for hand in result.multi_hand_landmarks: # 把 21 个点展平成 42 维特征喂给下游分类器 pts np.array([[lm.x, lm.y] for lm in hand.landmark]).flatten() print(pts.shape) # (42,) cv2.imshow(hand, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()逻辑说明max_num_hands1是性能关键交警手势基本单手完成限制数量能显著降低计算量。min_detection_confidence和min_tracking_confidence都设 0.5 是稳妥起点画面抖动大就调高检测置信度。输出的 42 维特征可以直接喂给一个全连接分类网络也可以按时间序列送进 LSTM 做动态手势识别。注意关键点坐标是归一化的换分辨率不影响但换摄像头角度会明显影响精度。3.3 从脚本到接口用 FastAPI 包一层演示脚本能跑通后下一步是包成接口供前端或其他服务调用。FastAPI 是轻量首选下面是最小可用的推理服务。from fastapi import FastAPI, UploadFile from ultralytics import YOLO import numpy as np import cv2 app FastAPI() model YOLO(runs/detect/train/weights/best.pt) app.post(/predict) async def predict(file: UploadFile): data await file.read() img cv2.imdecode(np.frombuffer(data, np.uint8), cv2.IMREAD_COLOR) res model(img, conf0.5, verboseFalse) out [] for box in res[0].boxes: out.append({ label: model.names[int(box.cls[0])], conf: round(float(box.conf[0]), 3), }) return {results: out}逻辑说明UploadFile接收上传的图片字节流cv2.imdecode把字节转成图像数组避免落盘。返回结构里只保留标签和置信度坐标按需再加。启动命令是uvicorn main:app --host 0.0.0.0 --port 8000。生产环境要注意模型加载只做一次放在模块顶层别写进请求函数里否则每次请求都重新加载权重延迟会高得离谱。4. 避坑与排查手势识别落地最常见的五个翻车点4.1 类别不均衡导致模型只认多数类现象训练完发现模型几乎只输出「停止」和「直行」两个类别其他手势基本不识别。原因这两类样本数远多于其他类损失被多数类主导。解决先跑 2.1 的统计脚本确认分布对少数类做过采样或在训练时给类别加权YOLO 里可以通过调整数据集采样比例实现实在不行就补数据。4.2 关键点抖动让动态手势识别崩掉现象MediaPipe 提取的关键点逐帧跳动分类器在连续帧上输出反复横跳。原因手部快速移动或部分遮挡时关键点检测不稳定。解决对关键点序列做滑动平均或卡尔曼滤波平滑再送分类器同时把min_tracking_confidence调高到 0.6 以上牺牲一点召回换稳定。4.3 置信度阈值设错导致漏检或误检现象路口画面里手势明明很明显模型却不框或者背景里的手臂被误判成手势。原因conf阈值一刀切没按场景调。解决在验证集上画 precision-recall 曲线找 F1 最高的阈值。实际部署时如果更怕漏检就调低到 0.3更怕误报就调到 0.6。4.4 训练和推理的图像预处理不一致现象训练时准确率很高部署后效果断崖式下跌。原因训练用了归一化或特定尺寸推理时没做同样处理。解决YOLO 内部会处理尺寸但如果你自己写了预处理务必保证训练和推理用同一套参数。用model.predict时别手动改尺寸交给框架。4.5 显存不足导致训练中途崩现象训练跑几十个 epoch 后报 CUDA out of memory。原因batch或imgsize设太大或者验证阶段同时加载了过多数据。解决先把batch减半再考虑降imgsize。也可以用梯度累积模拟大 batch但要注意学习率同步调整。显存实在紧张就换更小的模型比如从yolov8m降到yolov8n。5. 进阶技巧用时序信息把静态识别升级成动作识别单帧识别只能判断「这一帧像什么手势」但交警指挥是连续动作单帧容易在过渡姿态上误判。一个实用技巧是把连续多帧的检测结果做时序投票或送进轻量时序模型。我一般会维护一个长度为 N 的滑动窗口窗口内多数类别一致才输出这样能过滤掉过渡帧的抖动。from collections import deque, Counter window deque(maxlen10) # 10 帧窗口 def smooth_predict(label): window.append(label) # 取窗口内出现次数最多的类别作为稳定输出 most, count Counter(window).most_common(1)[0] # 占比超过 60% 才认为稳定否则维持上一结果 if count / len(window) 0.6: return most return None逻辑说明maxlen10控制窗口长度帧率 30 时约等于 0.3 秒太短过滤不掉抖动太长会引入延迟。0.6是稳定阈值可按实际抖动程度调。这个技巧几乎零成本但能明显降低输出跳变是我在演示和实际部署里都会加的一层。验证这套方案是否真的有效别只看训练集的准确率。我习惯的做法是录一段真实路口的视频人工标出每个手势的起止时间然后跑推理统计每段的识别正确率和响应延迟。只有在这段真实视频上表现稳定才算能拿出去用。最后说个血泪教训手势识别项目里数据质量的重要性远大于模型选型。我见过太多人花一周调模型结构结果发现数据集里有一半标注是错的。拿到数据先花半天做清洗和统计比后面调参省下的时间多得多。希望帮到你。本文还有配套的精品资源点击获取