☰
让启元 T1 Pro 认出点赞、V 字、布和石头:一次从相机到模型的二次开发实录
2026/11/4 2:26:47 网站建设 项目流程

让启元 T1 Pro 认出点赞、V 字、布和石头:一次从相机到模型的二次开发实录

  • 让启元 T1 Pro 认出点赞、V 字、布和石头:一次从相机到模型的二次开发实录
    • 一、第一步不是训练模型,而是让电脑真正读到机器人
    • 二、120 帧里没有手,问题出在镜头而不是模型
    • 三、392 张图片怎么分?关键是不能让连续帧互相“串门”
    • 四、三种做法都试了,效果差距比预想中大
    • 五、成绩单:正确识别、误判和拒识一起看
    • 六、真机开发的三个小经验
    • 七、复现这次实验:先从已有照片跑起
    • 写在最后

🌌你好!这里是 晓雨的笔记本
在所有感兴趣的领域扩展知识,感谢你的陪伴与支持~
👋 欢迎添加好友 is_yu_ei,不定期掉落福利资讯

原创技术实践,转载请注明作者和出处。本文配图包含技术流程图、实验统计图及 T1 Pro 真实右目完整画面与自动手部 ROI 对照。

让启元 T1 Pro 认出点赞、V 字、布和石头:一次从相机到模型的二次开发实录

关键词:启元 T1 Pro|ROS 2|PrimeConsole|MediaPipe|MobileNetV3|手势识别|真机实测

为什么要教机器人认手势?比如机器人在展厅讲解,用户想继续下一步,没必要每次都喊口令;在嘈杂现场或不方便讲话时,手势也能成为快捷输入。点赞可以约定为确认,V 字切换步骤,张开手掌暂停,握拳结束。T1 Pro 本身就有摄像头,如果能看懂这些简单动作,就多了一种不依赖手机遥控器的交互方式。

第一次对着 T1 Pro 比手势,我觉得应该很简单:张开手掌、跑一下模型、屏幕上显示OpenPalm,这不就通了?结果程序读了 120 帧,连一只手都没找到。换成点赞和 V 字之后,又遇到了另一种情况:明明拍到了手,模型却认错了。

先看一组真机实拍:T1 Pro 右目摄像头看到的是完整的室内场景,手只占画面的一小块。我们让程序先自动找手、再裁剪局部识别。下面每一行的左右两张图来自同一帧,并非分别摆拍。

图 1|真实场景下的自动手部定位与 ROI 识别。左侧保留 2592 × 1944 的完整取景范围,绿色框是自动检出的手部;右侧为对应帧的模型 ROI。四行依次是点赞、V 字、布和石头。图中为已有数据中筛选出的识别成功样例,人物面部已做隐私处理。

更有意思的是,我们原来的 MobileNetV3-Small 在公开测试图片上能答对35/40 张(87.5%)。一接上真实机器人,问题却接二连三。于是这次我没有急着换更大的网络,而是从相机、手部定位、裁剪、特征和数据集这几个环节往下查。最后把此前采集的真机照片与公开手势图片整理在一起,一共392 张,完整跑了一遍训练、验证和测试。

这次先用四种容易辨认的手势验证视觉识别链路:👍 点赞(ThumbsUp)、✌️ V 字(PeaceSign)、🖐️ 布(OpenPalm)、✊ 石头(Fist)。手从镜头里消失后,还需要及时返回“无手”,避免继续报告上一帧的姿势。

一、第一步不是训练模型,而是让电脑真正读到机器人

我们这次用的是 T1 Pro 的右目摄像头。设备端负责拍照,Windows 电脑负责解码和推理;我先把两个部分分开调通。

开始时,电脑上的 PrimeConsole 已经安装好,但输入设备 SN 后依然无法直接进入开发流程。后来在手机 PrimeBOT App 里检查并开启了二次开发相关功能,再回到电脑端确认连接。接着改为有线连接,通过独立开发网段检查两块板卡和 ROS 2 通信。

这一步花的时间比想象中多。网线松动时,控制台看起来还在,ROS 2 的相机调用却会超时。最后我把排查顺序固定下来:网卡状态 → 设备连通 → 摄像头 Service → JPEG 数据 → 模型推理。以后遇到“识别不动了”,先看哪一层断了,少走很多弯路。

在本次 SDK 环境中,右目 JPEG 抓拍的核心调用是:

fromaimdk_msgs.msgimportCommonRequestfromaimdk_msgs.srvimportCaptureJpegImage client=node.create_client(CaptureJpegImage,"/aima/hal/camera/CaptureJpegImage")assertclient.wait_for_service(timeout_sec=5.0)req=CaptureJpegImage.Request()req.request=CommonRequest()req.request.header.stamp=node.get_clock().now().to_msg()req.camera_id="head_stereo_right"req.timeout_ms=3000future=client.call_async(req)rclpy.spin_until_future_complete(node,future,timeout_sec=5.0)res=future.result()ifresisNoneorres.response.header.code!=0:raiseRuntimeError("相机抓拍失败")jpeg_bytes=bytes(res.jpeg.image.data)

这里截取的是关键接口,完整运行还需要创建 ROS 2 节点、初始化与清理资源。把jpeg_bytes验证并解码成图片之后,才进入下一步手势识别。

还有一个实际踩过的坑:ROS 2 和模型推理最好使用隔离的 Python 环境。我们碰到过 NumPy 的_multiarray_umathDLL 加载失败,原因是推理进程继承了 ROS 2 环境的PYTHONPATH,把两套库混在了一起。分开运行通信与推理进程,问题就解决了。

二、120 帧里没有手,问题出在镜头而不是模型

第一次正样本测试没检测到手,我马上检查了右目的抓拍照片:画面里大部分是桌子下面、地面和鞋子。人确实站在机器人前摆了手势,但手根本没处于所选摄像头的有效视野里。

于是先写了一个很简单的采集窗口:可以看右目预览,按“点赞 → V 字 → 布 → 石头”倒计时采图,并把每一轮照片单独保存下来。这样模型错了,至少可以回头确定:究竟是手没入镜、手太小,还是分类器真的判断错了。

解决视野后,第二个问题才浮出来。右目 JPEG 约为2592 × 1944,手掌可能只占画面很小一块。直接把整张图缩到分类器输入大小,手指细节就丢了不少。

我后来把流程换成了“先找手,再识别手势”:MediaPipe 先定位手;如果下一帧整图漏检,就借助上一帧的手部位置,在附近的 ROI 重新检测;拿到关键点后,再看五指伸展、弯曲以及相对位置。

图 2|当前视觉处理链路。真机连续帧与公开静态图片采用不同的识别路径,82 维关键点分类器另作固定数据集对照。

这项改动的效果很直观:第二轮真机 64 张图,整图检手只有42/64;加上前帧 ROI 补检后,这轮离线回放检出了64/64。这里提升的是手部检出率,后面的四类分类仍需单独测试。

三、392 张图片怎么分?关键是不能让连续帧互相“串门”

采到足够的手势图后,接下来是训练。最省事的办法是把所有图片随机打散,比如 8:1:1。但同一次摆手连续拍出的十几张照片几乎一模一样,随机划分很容易把同一个动作和背景同时送进训练集、测试集。

我们最后把采集轮次当作一个整体:第一轮真机用于训练,第二轮用于验证,最后一轮留作测试。原来的公开 train / validation / test 也保持原有划分。

图 3|固定划分:Train 183 张、Validation 110 张、Test 99 张。颜色区分公开手势、真机手势和无手图片。

数据集数量组成
训练集 Train183公开训练 120 + 第一轮真机 63
验证集 Validation110公开验证 40 + 第二轮真机 64 + 无手 6
测试集 Test99公开测试 40 + 最新真机 47 + 无手 12

先核验图片哈希,确认没有跨集合重复文件;再只用验证集选前端阈值和分类方案。MediaPipe 手部检测门限从0.65调到0.35,公开验证图的检出由25/40提高到31/40;这次的 T1 Pro 验证图仍为64/64,6 张无手背景没有触发手部检测。

接着,我们提取三种手部特征:5 维手指关节角、19 维局部几何距离,以及82 维归一化关键点姿态。与把整张室内照片送进网络相比,这些特征更直接地描述“手是怎么摆的”。

四、三种做法都试了,效果差距比预想中大

方案 A:原 MobileNetV3 直接识别整张图片。它仍然很适合原来的公开图片,公开测试集得到35/40。但机器人画面有桌椅、衣物、地面,手还经常只占很小一块。最早一轮真机 63 张图片,直接整图分类甚至没有一张与采集提示类别一致。

方案 B:检测手后,把关键点交给小分类器。我们在训练集上比较了 Logistic Regression、SVM、RandomForest,以及 5 / 19 / 82 维特征。验证集选出的组合是82 维归一化关键点 + Logistic Regression(C=1),置信度低于0.60就暂不输出手势。随后合并 Train 和 Validation 的可检测手部特征,固定参数重新训练,再评估 Test。

方案 C:根据输入来源走不同路径。机器人连续相机画面优先走 MediaPipe、时序 ROI 和手指几何判断;普通公开静态图片沿用原 MobileNetV3。机器人画面来自哪一路相机,本来就是系统知道的信息,不必让分类器猜。这个方案不涉及再训练一个统一的大网络,优势在于各取所长。

期间我们也试了裁剪后 MobileNet 特征微调分类头、降低早期真机样本权重、加关键点扰动、多个分类器投票。它们有时能改善局部结果,但在验证集上的整体收益有限,最终没有继续堆这些模块。

五、成绩单:正确识别、误判和拒识一起看

先看固定三分法选出来的 82 维模型。测试集中共有 87 张四手势图,模型正确接受56 张,错误接受7 张,其余24 张拒识;另外 12 张无手图全部拒识。在最新的 T1 Pro 真机手势中,正确接受34/47。

再看后续做的按输入来源路由。把前面保存的同一批图片重新离线回放,T1 Pro 真机44/47正确接受,公开测试35/40正确接受,合计79/87;另外有 6 张误判、2 张拒识,无手 12 张全部拒识。

图 4|两种方案在相同测试图上的结果。绿色为正确接受,红色为误判,灰色为拒识;右侧显示正确数与全分母比例。

测试切片82 维 LR(固定训练)来源路由(离线优化)
T1 Pro 真机,47 张34/4744/47
公开图片,40 张22/4035/40
四手势合计,87 张56/8779/87
无手背景,12 张12/12 拒识12/12 拒识

怎样理解这两组数据?固定训练模型的参数按 Train / Validation 选定后评估;来源路由是在排查既有图片时逐步开发出来的,79/87是这批图片的回顾性回放成绩。图片中的姿势标签主要来自采集时的界面提示,部分测试照片此前也参与过方法排查。我们用这组数据比较方案,不把它当成新用户、新场景的上线准确率。

另外,还有一轮很值得留下的“差成绩”:第一轮真机 63 张图,在后来的路由流程下也只有13 张正确、1 张误判、49 张拒识。当镜头里根本没有完整的手时,后面的分类器很难弥补前端丢失的信息。

六、真机开发的三个小经验

先看相机,再看模型。当检测器输出NoHand,先打开右目图,看看目标是不是在视野里。花十秒确认画面,往往比反复调整网络参数更快。

手离开后,要让跟踪器学会放手。一次五阶段实时测试中,手已移开,旧 ROI 却短暂把衣物背景当成了手。我们在后续回放中加入“小得异常的手部框直接拒绝,并清除追踪锚点”的处理,避免它一路沿着错误位置跟踪下去。

换一轮照片,比在原来的照片上多跑几遍更重要。早期曾出现训练图全部正确、换个采集时段就明显下降的情况。按会话保留数据,再分别看检出、误判和拒识,能更快判断问题出在数据还是模型。

此外,我们在真机 JPEG 试验中观察到约1.96 FPS的短时采样处理速率。对于这样一个原型,这足以做可视化调试;如果以后要做连续交互,还需要专门考虑端到端延迟与姿势切换。

七、复现这次实验:先从已有照片跑起

本机已经保留训练划分清单、模型、原始采集和两条识别路径。下面的命令只读取本地图片:

# T1 Pro 的真实连续右目抓拍python t1pro_optimized_source_router.py `--mode robot `--directory"D:\T1ProDev\gesture_live_runs\live_20261027_193102"`--temporal# 独立的公开静态测试图片python t1pro_optimized_source_router.py `--mode photo `--directory"D:\T1ProDev\benchmark_dataset\test"

--temporal使用前帧手部位置,只适合按时间连续采集的画面。train.csv、val.csv、test.csv和完整测试结果位于D:\T1ProDev\gesture_fixed_split_20261027。要复用基础的 SDK 连接和抓图代码,可以参考 AtomGit:t1-pro-sdk-demos;本次训练图片和实验脚本存放在本机项目目录。

写在最后

这次做 T1 Pro 手势识别,最有收获的反而是一次次“认不出来”。先发现镜头根本没拍到手,再发现全图缩放让手指信息变少,后来又看到时序 ROI 能找回漏检,却也可能把背景误认为手。

真正可复用的经验,是先把相机、检手、手势判断和拒识拆开,每一步都留下原图与结果。这样不管下一次换成别的摄像头,还是增加新的手势,都知道该从哪里开始检查。本文阶段先把视觉识别与结果展示跑通,相关开发文档和社区资源可以从启元机器人开发者社区继续查阅。

资料与代码:启元 T1 Pro 产品资料 · 开发者工具下载 · AtomGit SDK 示例

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询