先让 T1 Pro 传回一张好用的图:JPEG 抓拍、RTSP 视频与方向校正

@TOC



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


写在最前面

版权声明:本文为原创技术实践稿,遵循 CC 4.0 BY-SA 协议。转载请注明出处。涉及官方 SDK 的接口描述及开源项目代码,请以所链接的官方资料和仓库许可证为准。

准备接入视觉模型时,可以先做一个十秒钟的小检查:保存一帧画面,看人是不是正着、颜色是否正常、取到的是不是新图。模型分数再高,也需要可靠的输入。把这些问题提前放到取图工具里处理,后面调分类、检测或图片问答时,就少了一层猜测。

T1 的公开视觉接口提供 head_stereo_left 和 head_stereo_right 两路相机标识,以及单帧 JPEG 服务和 RTSP 视频入口。本文先让 Python 完成一次"取图---解码---方向处理---保存",再扩展到连续取帧。普通 RGB 分类任务可以先使用其中一路图像。12

图 1|从两个入口得到可用图像:JPEG 服务对应单次抓拍,RTSP 对应连续取帧,后续再交给显示或视觉模型。

这一篇先做两个顺手的小工具

camera_capture.py 负责保存一张图;camera_stream.py 负责读取有限数量的视频帧,并周期性保存采样帧到 latest_frame.jpg。先用合成图片和自己的视频测试处理流程,接入 T1 时再替换服务与视频源。两个入口共享方向配置,便于定位问题。

1 先确认"向谁取图、会收到什么"

设备接口沿用 Ubuntu 22.04 / ROS 2 Humble,消息包按 SDK 入门篇编译。图像脚本需要 requirements-core.txt 中的 Pillow;视频脚本额外安装 requirements-video.txt 中的 OpenCV。下面命令在已经克隆的 t1-pro-sdk-demos 根目录执行。15

bash 复制代码
git clone https://atomgit.com/WTYuong/t1-pro-sdk-demos.git
cd t1-pro-sdk-demos
git checkout 3a62e33
python3 -m pip install -r requirements-core.txt
## 在 Ubuntu 22.04 的 ROS 终端中加载已编译的 SDK:
source /opt/ros/humble/setup.bash
source /path/to/primebot-t1-sdk/install/setup.bash
ros2 interface show aimdk_msgs/srv/CaptureJpegImage
ros2 service list -t

先把 SDK 路径替换为实际构建目录。CaptureJpegImage 的服务名用于找到机器人上的服务器,aimdk_msgs/srv/CaptureJpegImage 则定义 Python 请求和响应。查看一次 interface show,再查看 service list -t,就能把本地类型与远端入口对齐。23

请求字段 本例怎么使用
request.header.stamp 填写当前 ROS 时钟时间戳
camera_id head_stereo_left 或 head_stereo_right
timeout_ms 等待新帧的服务端超时;本例设 1000 ms
客户端等待期限 在服务端超时之外再留通信处理时间

选择 head_stereo_left 或 head_stereo_right 后,把相机 ID 和方向一起作为配置保存。首版沿用机器人当前形态,围绕同一路相机收集样本;这样复查一张图片时,能够知道它来自哪只相机、是否经过旋转。

先把单帧抓拍做成一个可复查的样本,再扩展到连续取帧,问题更容易分层定位。

2 JPEG 字节藏在响应的哪一层?

抓拍返回值可以顺着名字往下读:reply 的 jpeg 保存相机元信息,jpeg.image 是标准 CompressedImage,image.data 才是压缩字节。因此实际取图路径是 reply.jpeg.image.data。先取对这一层,再交给图像解码器。34

python 复制代码
req = CaptureJpegImage.Request()
req.request.header.stamp = node.get_clock().now().to_msg()
req.camera_id = 'head_stereo_left'
req.timeout_ms = 1000
future = client.call_async(req)
## 在 main 中等待,回调内不阻塞等待:
rclpy.spin_until_future_complete(node, future, timeout_sec=4.0)
if not future.done():
    raise TimeoutError('抓拍响应超时')
reply = future.result()
common = reply.response
if common.header.code != 0 or common.status.value != 1:
    raise RuntimeError(common.message)
payload = bytes(reply.jpeg.image.data)
frame = decode_jpeg(payload, rotate=0)

状态检查可以写成一个简单条件:只有 code == 0 且 status.value == SUCCESS,才继续解码。用失败分支表达时,两个条件之间就是 or。配套测试分别构造了两层失败的情况,用来防止将错误响应送入解码器。

检查顺序 处理方式
服务可发现 等待上限明确;服务不存在时给出错误
响应状态成功 同时核对框架码和业务状态
载荷非空且为 JPEG Pillow 实际解码,不仅检查文件后缀
尺寸和方向正确 记录解码尺寸,再做可选的 180° 旋转
写文件成功 保存图像和元信息,便于之后比对

decode_jpeg 位于 camera_capture.py:通过 BytesIO 打开载荷,确认 JPEG 格式后转为 RGB,再按配置旋转和保存。服务响应、图像解码、文件写入因此成为三个清楚的检查点,出错时日志可以直接指向其中一环。

3 画面能打开以后,再检查方向与颜色

T1 文档对左目画面有一条具体提示:双足形态下,head_stereo_left 的原始 RTSP 图像可能倒置,需要在应用层进行 180° 旋转。先看现场画面,再设置 --rotate 0 或 180;将方向校正固定在一个位置,就能避免后续重复处理。2

图 2|用带上下标记的合成图验证 180° 旋转:通过固定标记位置检查处理前后的像素对应关系。

方向、颜色和尺寸最好分成三项配置。OpenCV 读取的视频帧采用 BGR 排列,交给 RGB 模型前做一次颜色转换;PIL.convert("RGB") 得到的图像则沿用 RGB。Resize 再把图像调整为模型尺寸。每一步只做一次,后续接模型就更直接。5

python 复制代码
## OpenCV 视频帧路径:按现场需要旋转,再转换颜色。
if rotate_deg == 180:
    frame = cv2.rotate(frame, cv2.ROTATE_180)
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
## 若已在抓拍脚本旋转并存盘,推理脚本保持 --rotate 0。

与原手势模型衔接时,先保持整图缩放到 224×224 和原来的归一化。下一轮再用同一组 T1 样本比较整图与手部裁剪输入,观察手势尺度和背景变化带来的影响。这样可以看清收益究竟来自输入处理,还是来自模型更新。

4 从一张图,扩展到连续取帧

RTSP 地址由机器人当前 IP、端口和 camera_id 组成:rtsp://:/live_<camera_id>。公开文档的端口示例为 2554。把实际地址传给视频脚本前,可先读取本地视频,确认 FFmpeg 后端和图像保存都正常。25

bash 复制代码
python3 -m pip install -r requirements-video.txt
## 先读取自己的视频,检查取帧与文件输出:
python3 camera_stream.py --input my_clip.mp4 --frames 100
## 设备连接后替换输入地址:
python3 camera_stream.py \
  --input rtsp://ROBOT_IP:2554/live_head_stereo_left \
  --rotate 0 --frames 100

示例先用 --rotate 0 保留原方向;确认左目画面倒置后再改为 180。脚本设置打开和读帧超时,通过 --frames 限定读取规模,每十帧保存一次采样图,并在结束时释放 VideoCapture。现场先看输出文件与 frames_read,便于确认视频路径是否工作。

python 复制代码
cap = cv2.VideoCapture(url, cv2.CAP_FFMPEG, [
    cv2.CAP_PROP_OPEN_TIMEOUT_MSEC, 5000,
    cv2.CAP_PROP_READ_TIMEOUT_MSEC, 3000,
])
if not cap.isOpened():
    raise RuntimeError('视频源未打开')
ok, frame = cap.read()
if not ok or frame is None:
    raise RuntimeError('没有收到可解码帧')

这份脚本是一个便于检查的顺序取帧工具。后续接入较慢的模型时,可以把采集与推理解耦,增加容量为 1 的最新帧缓冲,并记录采集时间。如此一来,推理消费的是新画面,而不是逐帧追赶积压的视频。

5 用回放检查处理,再用设备检查链路

bash 复制代码
## 以下均在 t1-pro-sdk-demos 根目录执行:
python3 camera_capture.py --mock --rotate 180
python3 -m unittest discover -s tests -v
## 已加载 ROS / SDK 环境后:
python3 camera_capture.py --live \
  --camera-id head_stereo_left --rotate 0 --out results/t1.jpg

本次图像用例全部通过:640×360 合成 JPEG 成功解码,旋转后的指定像素与原图对应,空载荷和非 JPEG 载荷被正确处理。结果纳入整套 40 项单元测试。接入设备后,按返回元信息记录实际分辨率、相机 ID、字节数与取图耗时。

现象 排查路径
抓拍失败,视频可用 核对相机服务是否存在、请求类型和响应字段
视频打不开,ROS 正常 检查 RTSP 端口、地址、相机 ID 和 FFmpeg 后端
方向正确但颜色异常 核对 BGR / RGB 是否遗漏或重复转换
视频越来越滞后 检查采集/处理是否积压;接模型时采用最新帧缓冲并记录时间戳

结语

先取一张图,再处理一段视频,最后才把像素交给模型,这是一条容易复查的视觉开发路线。做完这一篇,后续应用可以复用相机选择、解码、方向和颜色处理,把注意力集中到真正需要解决的识别任务上。

源码与复现

公开仓库:WTYuong/t1-pro-sdk-demos | 本文示例版本:3a62e33

复现版本:git checkout 3a62e33(克隆并进入仓库后执行)。

本篇代码:camera_capture.py · camera_stream.py · ros_io.py

复现命令(仓库根目录):python3 camera_capture.py --mock --rotate 180 # 合成 JPEG 与方向校验

连续取帧:python3 camera_stream.py --input rtsp://ROBOT_IP:2554/live_head_stereo_left --rotate 0 --frames 100。将 ROBOT_IP 换成实际地址;需要方向校正时再改 --rotate。

资料与代码来源

1 T1 SDK 快速入门与集成指南 查看原文

2 T1 接口说明:视觉采集与 RTSP 查看原文

3 CaptureJpegImage.srv / JpegImage.msg 查看原文

4 JpegImage:压缩图像载荷层级 查看原文

5 OpenCV VideoCapture 官方文档 查看原文

技术资料核对日期:2026-10-20。配图分别展示接口通路与合成图像的方向回放。

继续开发时,可到启元机器人开发者社区(https://dev.primebot.com/)查阅 SDK、接口文档与开发案例,也欢迎分享自己的复现记录和改进思路。


hello,这里是 晓雨的笔记本。如果你喜欢我的文章,欢迎三连给我鼓励和支持:👍点赞 📁关注 💬评论,我会给大家带来更多有用有趣的文章。

原文链接 👉 【发布后更新】

欢迎大家点开下面名片,添加好友交流。

相关推荐
伞伞悦读1 小时前
【第60期】特征值不是重要性:Python 特征分解与 PCA 的前置判断
python
2601_967980111 小时前
Python之wxPython模块的安装
linux·windows·python·wxpython·gui设计·1024程序员节
云南新人和数采集团1 小时前
DeepSeek Harness 开源贡献手记:从入门到合入主线
python·开源·github
阿明副业观察1 小时前
AI分镜批量生成与画风统一的秘诀
大数据·人工智能·aigc·音视频·ai写作
xierui1231232 小时前
视频Agent的首帧验收:用3秒无声样段检查开场信息与可读性
人工智能·音视频
信誓旦旦的程序猿2 小时前
【Python量化实战宝典 #20】动量、反转择时手册:趋势跟随与均值回归(Python 可跑)
java·python·股票数据api·股票数据api接口·股票api数据接口·股票量化数据api·股票量化数据接口
tianxuanjg2 小时前
采购指南|工业无人机高强度结构件怎么选?
人工智能·经验分享·机器人·无人机·制造
好焊孙辉2 小时前
从六代螺柱焊机到AI质检:鸿栢科技的螺柱焊国产化路径
人工智能·python·科技·fpga开发
美狐美颜sdk2 小时前
直播APP开发中的视频帧处理:美颜SDK接入需要注意哪些细节?
大数据·前端·人工智能·音视频·美颜sdk