避免运行中改变 HHD 测量配置,并明确部分标定时各轴单位。已通过 SDK 与共享层测试。
22 KiB
title, description
| title | description |
|---|---|
| API Reference | Orisys SDK Python API 中文参考 |
API Reference
本文件提供 orisys 套件的 Python API 中文参考。安装、CUDA、CuPy 与运行示例的基础步骤请参考 快速开始。
Sensor API
Sensor 类别
描述
orisys套件的核心类,用于从视频文件或实时摄像头中读取传感器图像,创建一个具体的传感器对象(实例)。并完成形变、光流及力信息的计算与管理。
输入参数
- vid_src (
int | str, 必填): 传感器 ID、相机编号或视频路径。默认为0。 - config_name (
str,可选): 传感器配置文件名称或json文件路径,用于加载对应的参数配置;例如box或./config/box.json。 - cal_path (
str,可选): 显式的force_calibration.json路径;传入后优先于sensors/<type>/force_calibration.json。不传时按config_name自动加载产品包中的标定文件。 - backend (
str,可选): 光流场解耦计算后端,默认为auto,可选cupy,opencl,cpu。 - verbose (
bool,可选): 是否输出初始化及运行过程中的详细日志信息,默认为False。
返回
Sensor实例,用于后续图像采集、形变计算和数据读取操作。
示例
# Example 1: 用相机编号创建
from orisys import Sensor
sensor = Sensor(0)
# Example 2: 用视频文件创建
sensor = Sensor("/data/data.mp4")
Sensor.get_img 方法
描述
采集并预处理一帧图像并存到Sensor 类别中。
返回
bool:是否成功读取图像。
状态更新
- 成功时更新
sensor类里面的sensor.img。处理后的BGR格式图像(uint8,尺寸为json文件中resolution_stitch对应分辨率)。
示例
sensor.get_img()
Sensor.compute_deformation 方法
描述
基于当前帧图像计算光流/形变向量场,并通过 HHD 分解将形变场分解为法向/切向分量,同时估计法向力、切向力与扭矩等标量输出。该方法会更新
sensor的形变场与力相关状态,并返回当前帧的光流场。
调用前置条件:需要先通过get_img()成功更新图像。
输入参数
- decompose (
bool,可选): 是否在计算光流后继续执行 HHD 分解,默认True。 - check_motion (
bool,可选): 是否启用运动检测门控。当前不推荐依赖该功能;新代码建议显式传入False,让每帧都执行 HHD 分解。为兼容旧代码,函数默认值仍为True。
兼容参数(暂不推荐)
以下参数只在 check_motion=True 时生效。由于运动检测门控目前不稳定,建议在新代码中暂时不要使用:
- threshold (
float,可选): 运动检测阈值,默认6。 - tail_frames (
int,可选): 运动低于阈值后继续解算多少帧,默认10。
返回
None: 当check_motion=False时返回。推荐用法下不要依赖该返回值判断接触状态。bool: 仅当check_motion=True时返回运动检测结果;该模式目前暂不推荐。
示例
sensor.get_img()
sensor.compute_deformation(check_motion=False)
sensor.compute_contact()
Sensor.compute_contact 方法
描述
基于已计算的法向形变场进行接触区域分析,输出接触质心与轮廓等信息,并生成接触深度图,默认配置在json文件中,可按需调节。
调用前置条件:需先执行compute_deformation()。
返回
dict为接触分析结果字典,至少包含以下键:
- expansion_mask: 扩张区域掩码(
np.ndarray)。 - contraction_mask: 收缩区域掩码(
np.ndarray)。 - divergence_map: 散度图(
np.ndarray)。 - centroid: 质心坐标(单点模式为
(x, y);多点模式为列表)。 - centroid_found: 是否检测到接触区域(
bool)。 - contour: 最大轮廓或轮廓列表(可选字段,存在时返回)。
状态更新
- sensor.centroid: 接触质心(单点为
(x, y),多点为列表)。 - sensor.centroid_found: 是否找到质心(
bool)。
示例
sensor.compute_contact()
centroid, contour, depth = sensor.read_info(
sensor.info.CENTROID,
sensor.info.CONTOUR,
sensor.info.DEPTH,
)
Sensor.read_info 方法
描述
按指定的信息类型(sensor.info枚举值)批量读取传感器状态数据,并按传入顺序返回对应值的元组。
该方法通常用于在完成形变计算后,读取光流场、分量场、力、帧率等信息。
输入参数
- args: 任意数量的
Sensor.info枚举,用于指定需要获取的数据类型。支持的枚举值及对应数据如下:
支持的 info keys
向量/图像类
- VRAW: 原始光流场,
np.ndarray,shape=(H, W, 2) - VNORMAL: 法向光流场,
np.ndarray,shape=(H, W, 2) - VSHEAR: 切向光流场,
np.ndarray,shape=(H, W,2) - DEPTH: 深度场(可选), 未启用/未生成时返回空数组
np.array([])。
标量类
- FNORMAL: 法向力,
float。 - FSHEARX: X切向力,
float。 - FSHEARY: Y切向力,
float。 - FNORMAL_RAW: 未经过低通滤波的原始法向力,
float。 - FSHEARX_RAW: 未经过低通滤波的原始 X 切向力,
float。 - FSHEARY_RAW: 未经过低通滤波的原始 Y 切向力,
float。 - FPS: 输出帧率,
float。 - CENTROID: 触碰点的坐标,(x, y)。
- CONTOUR: 触碰区域轮廓,
np.ndarray, shape=(H, W), 未生成时返回np.empty
时间戳
- TIMESTAMP: 时间戳字符串(HH:MM:SS),
str。
注:H/W 由当前json文件中的resolution_stitch配置分辨率决定。
返回
Tuple
按传入的 sensor.info 参数顺序返回一个元组,
返回值数量与有效参数数量一致。
- 向量/图像类数据:
np.ndarray- 若当前流程中尚未生成该数据,返回空数组
- 标量类数据:
float - 时间戳:
str(TIMESTAMP,格式为HH:MM:SS)
示例
# Example 1:读取标量数据
fps, fn, fx, fy = sensor.read_info(
sensor.info.FPS,
sensor.info.FNORMAL,
sensor.info.FSHEARX,
sensor.info.FSHEARY,
)
# Example 2: 读取单个向量场(注意解包方式)
flow = sensor.read_info(sensor.info.VRAW)
Sensor.disconnect 方法
描述
释放传感器相关资源并停止后台异步线程。 调用后将关闭视频/摄像头输入源,并销毁所有 OpenCV 窗口。
建议在程序退出前调用以确保资源被正确释放。
Sensor.configure 低通滤波设置
描述
运行时更新传感器设置,无需重新连接相机。常用于开启力信号低通滤波,降低 FNORMAL、FSHEARX、FSHEARY 的高频噪声。
默认采样率按 30 fps 计算,推荐低通截止频率为 5 Hz:
sensor.configure(lowpass_cutoff_hz=5.0, lowpass_sample_rate_hz=30.0)
注意:lowpass_cutoff_hz 必须小于 Nyquist 频率,即 lowpass_sample_rate_hz / 2。例如 30 fps 时,截止频率必须小于 15 Hz。
输入参数
- lowpass_cutoff_hz (
float,可选): 力信号低通截止频率,单位 Hz。0表示关闭滤波;正数默认开启滤波。 - lowpass_sample_rate_hz (
float,可选): 力信号采样率,默认30.0。 - lowpass_order (
int,可选): Butterworth 滤波器阶数,默认2。 - lowpass_enabled (
bool,可选): 显式开启或关闭低通滤波。
读取结果
开启低通滤波后,read_info() 读取的力输出会被滤波:
fn, fx, fy = sensor.read_info(
sensor.info.FNORMAL,
sensor.info.FSHEARX,
sensor.info.FSHEARY,
)
原始力输出仍可通过 FNORMAL_RAW、FSHEARX_RAW、FSHEARY_RAW 读取,便于调试或对比。
Signal Processing API
orisys.signal_processing.lowpass_filter 函数
描述
对一维、等间隔采样数据执行零相位 Butterworth 低通滤波,适合示例程序或图表中对历史数据做平滑处理。
默认参数为 cutoff_hz=5.0、sample_rate_hz=30.0、order=2。这表示在 30 fps 数据上使用 5 Hz 低通滤波。
输入参数
- data: 一维数据序列。
- cutoff_hz (
float,可选): 截止频率,默认5.0。传入0时不做滤波并返回数据副本。 - sample_rate_hz (
float,可选): 采样率,默认30.0。 - order (
int,可选): Butterworth 滤波器阶数,默认2。
返回
np.ndarray: 滤波后的float64数组。
示例
from orisys.signal_processing import lowpass_filter
filtered_force = lowpass_filter(force_values, cutoff_hz=5.0, sample_rate_hz=30.0)
orisys.signal_processing.LowpassFilter 类别
描述
有状态的因果 Butterworth 低通滤波器,适合逐帧处理实时数据。它会保留上一帧的滤波状态,并通过 process() 一次处理一个多通道样本。
Sensor.configure() 内部使用该类来滤波力信号。构造时默认 cutoff_hz=0.0,表示关闭滤波;若要按 30 fps 使用推荐滤波,设置 cutoff_hz=5.0、sample_rate_hz=30.0。
输入参数
- cutoff_hz (
float,可选): 截止频率,默认0.0,表示关闭滤波。 - sample_rate_hz (
float,可选): 采样率,默认30.0。 - order (
int,可选): Butterworth 滤波器阶数,默认2。 - n_channels (
int,可选): 每个样本的通道数,默认3。
常用方法
- configure(...): 运行时更新
cutoff_hz、sample_rate_hz或order。 - reset(x0=None): 清除滤波器状态;传入
x0时会用该样本初始化稳态。 - process(values): 滤波一个多通道样本,返回 shape 为
(n_channels,)的np.ndarray。
示例
from orisys.signal_processing import LowpassFilter
filt = LowpassFilter(cutoff_hz=5.0, sample_rate_hz=30.0, n_channels=3)
filtered = filt.process([fnormal, fshearx, fsheary])
Finger Pipeline API
orisys.finger 手指 UV pipeline
examples/finger_pipeline.py 展示了一个更适合手指/单相机场景的高层 API:
- 使用
FingerRuntime.open()打开视频源、加载 Blender 导出的资产,并构建 UV 展开映射。 - 用
grab_and_process()或read_source() + process_frame()获取一帧展开后的触觉图像。 - 通过
runtime.tactile(TactileProcessor)调用compute_deformation()、compute_contact()、read_info()。 - 退出前调用
runtime.close()释放视频源和内部Sensor资源。
相比直接使用 Sensor,FingerRuntime 已封装了视频读取、相机尺寸设置、UV 展开和有效区域掩码传递,更适合作为手指 2D/3D 示例与上层应用的入口。
FingerRuntime.open 方法
描述
创建一个可复用的手指 UV runtime。该方法会完成以下初始化:
- 解析
export_dir下的mesh.npz、camera_intrinsics.npz、world_to_cam.npy - 根据配置和标定信息构建/加载
unroll_map_uv.npz - 打开相机或视频文件
- 创建内部
Sensor("external", ...) - 创建
FrameUnwarper与TactileProcessor
输入参数
- export_dir (
str,可选): 手指导出资产目录,默认值来自orisys.finger.DEFAULT_FINGER_EXPORT_DIR。目录下通常需要包含mesh.npz、camera_intrinsics.npz、world_to_cam.npy。 - config (
str,可选): Orisys 配置文件名称或路径,默认finger。 - map_cache (
str,可选): UV 展开缓存文件路径,默认值来自orisys.finger.DEFAULT_FINGER_MAP_CACHE。 - source_scale (
float,可选): 输入相机分辨率缩放比例;未提供时根据配置自动推断。 - calib (
str | None,可选): 外部相机标定文件路径;未提供时优先使用导出资产中的内参。 - video (
int | str,可选): 相机编号、数字字符串或视频路径,默认0。 - camera_id (
int | None,可选):video的别名;若提供则优先使用。 - flip_source_vertical (
bool,可选): 是否在 UV 展开前垂直翻转输入源,默认True。 - verbose (
bool,可选): 是否输出初始化日志。 - mirror (
bool,可选): 是否对内部触觉图再做镜像,默认False。
返回
FingerRuntime实例。
示例
from orisys.finger import FingerRuntime
runtime = FingerRuntime.open(
config="finger",
video=0,
verbose=True,
)
FingerRuntime 常用属性
- runtime.geometry:
FingerGeometry,包含输入/输出分辨率、导出资产路径、相机内参、缓存路径等一次性初始化结果。 - runtime.domain: UV 展开域对象,内部包含 remap、valid mask 以及可选 surface 数据。
- runtime.tactile:
TactileProcessor,用于执行形变、接触和数据读取。 - runtime.capture: OpenCV
VideoCapture对象。 - runtime.valid_mask: 当前 UV 域有效像素掩码。
FingerRuntime.read_source 方法
描述
仅读取一帧原始视频源,等价于对内部 cv2.VideoCapture 调用 read()。适合需要把采集和 UV 展开分别计时的场景。
返回
(ok, frame):- ok (
bool): 是否成功读取。 - frame (
np.ndarray | None): 原始 BGR 帧。
- ok (
FingerRuntime.process_frame 方法
描述
对一帧原始输入执行源图预处理、UV 展开,并把展开后的结果送入内部 TactileProcessor。这是 examples/finger_pipeline.py 中 profile 模式使用的方法。
输入参数
- frame (
np.ndarray,必填): 原始输入帧。 - color (
bool,可选): 为False时走灰度展开流程;为True时保留 BGR 颜色展开。默认False。
返回
np.ndarray: 展开后的触觉图像。color=False时通常为单通道灰度图;color=True时为 BGR 图。
FingerRuntime.grab_and_process 方法
描述
先读取一帧视频源,再调用 process_frame() 完成 UV 展开并推入内部触觉处理器。非 profile 模式下,examples/finger_pipeline.py 使用该方法作为主循环入口。
输入参数
- color (
bool,可选): 是否保留颜色,默认False。
返回
(ok, unrolled):- ok (
bool): 是否成功读取并处理。 - unrolled (
np.ndarray | None): 展开后的触觉图像。
- ok (
FingerRuntime.get_img 方法
描述
Sensor.get_img() 风格的别名:内部执行一次采集和 UV 展开,并在成功时返回当前展开图,否则返回 None。
输入参数
- color (
bool,可选): 是否保留颜色,默认False。
返回
np.ndarray | None
FingerRuntime.warmup 方法
描述
先执行一次采集与 UV 展开,然后调用 runtime.tactile.warmup() 预热内部光流/HHD 相关缓存。examples/finger_pipeline.py 在进入主循环前会先执行一次 warmup。
输入参数
- color (
bool,可选): 是否保留颜色,默认False。
返回
(ok, unrolled):- ok (
bool): 是否成功完成 warmup 前的采集。 - unrolled (
np.ndarray | None): warmup 时得到的展开图。
- ok (
FingerRuntime.close 方法
描述
释放内部 VideoCapture 并调用 runtime.tactile.disconnect() 清理 Sensor 资源。程序退出前应调用。
TactileProcessor 类别
描述
TactileProcessor 是对内部 Sensor("external", ...) 的窄封装。它保留了 compute_deformation()、compute_contact()、read_info()、reset() 等常用接口,同时屏蔽了视频采集与 UV 展开细节。
常用属性
- raw_sensor: 底层
Sensor对象。 - info: 与
Sensor.info相同的枚举入口。 - img / flow / vnormal / vshear / depth_map: 当前帧处理结果。
- mask_stats: 有效 UV 区域统计信息;
examples/finger_pipeline.py会读取mask_stats["coverage"]输出当前掩码覆盖率。 - valid_mask: 当前有效区域掩码。
说明
除 push_frame() / warmup() 之外,TactileProcessor 的 compute_deformation()、compute_contact()、read_info()、reset() 调用方式与 Sensor 基本一致,因此可直接复用前文 Sensor 章节中的参数说明。
最小手指 pipeline 示例
下面的流程与 examples/finger_pipeline.py 一致:
import time
import cv2
import orisys
from orisys.finger import FingerRuntime
runtime = FingerRuntime.open(
config="finger",
video=0,
verbose=True,
)
runtime.warmup(color=False)
tactile = runtime.tactile
try:
while True:
ok, unrolled = runtime.grab_and_process(color=False)
if not ok:
break
tactile.compute_deformation(check_motion=True, threshold=0)
tactile.compute_contact()
fps, flow, vnormal, img, contour, centroid, depth_map, fnormal, fshearx, fsheary = tactile.read_info(
tactile.info.FPS,
tactile.info.VRAW,
tactile.info.VNORMAL,
tactile.info.IMG,
tactile.info.CONTOUR,
tactile.info.CENTROID,
tactile.info.DEPTH,
tactile.info.FNORMAL,
tactile.info.FSHEARX,
tactile.info.FSHEARY,
)
arrows = orisys.util.draw_arrows(
unrolled,
flow,
threshold=0.4,
grid_spacing=10,
arrow_scale=1.0,
)
cv2.imshow("UV Unrolled", arrows)
print(
f"FPS={fps:.2f} normal={fnormal:.2f} "
f"shear=({fshearx:.2f}, {fsheary:.2f}) "
f"mask={tactile.mask_stats['coverage']:.2f}",
end="\r",
)
key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
break
if key == ord("r"):
tactile.reset()
finally:
runtime.close()
cv2.destroyAllWindows()
关于 profile 模式
examples/finger_pipeline.py 中的 --profile / --profile-every 是示例脚本参数,不属于 orisys SDK 核心 API。本质上它只是把主循环拆成:
runtime.read_source()runtime.process_frame(...)tactile.compute_deformation(...)tactile.compute_contact()tactile.read_info(...)
并对各阶段做耗时统计。因此在业务代码中,也可以按同样方式自行插入计时逻辑。
可视化相关
util.draw_arrows 方法
输入参数
- frame:背景图像
- optical_flow:光流场
- threshold:光流箭头显示阈值
- grid_spacing:光流箭头间距(pixel)
- arrow_scale:箭头大小
- margin:箭头最大长度/间距的比例
- colormap:色图,如
cv2.COLORMAP_JET - below_threshold_color:RGB格式的
uint8颜色,如(0, 0, 255) - edge_margin: 不显示箭头边距(pixel)
返回
np.ndarray :箭头光流可视化图像
util.draw_contact 方法
输入参数
- image:背景图像
- contour:轮廓
- centroid:触碰点
- point_color:触碰点的颜色 (BGR)
- region_color:轮廓的颜色 (BGR)
返回
np.ndarray :箭头光流可视化图像
配置标定相关
list_config 方法
描述
列出内置传感器配置参数字典。
返回
list: 内置传感器配置参数字典的名字列表。
export_config 方法
描述
导出当前传感器实例使用的配置参数字典。
输入参数
- config_name: 需要导出的配置参数字典名字,
str - path: 导出的路径,默认
"./config/exported_config.json"
返回
dict: 导出的配置参数字典。
保存
- 导出内置的
config_name配置参数字典至path
export_sensor_bundle / export_sensor_bundles 方法
描述
将已安装的 sensors/<name>/ 传感器包复制到目标目录,供下游应用(如桌面 App)做本地可编辑配置,无需硬编码 wheel 路径。解析顺序与 resolve_sensor_bundle 相同(含 importlib.resources 打包布局)。
输入参数
- name / names: 单个名字,或名字列表;
export_sensor_bundles省略names时导出所有可解析的产品包(box/mini/finger) - dest_dir: 目标根目录;实际写入
dest_dir/<name>/ - include_assets: 默认
False,仅复制sensor.json以及存在的force_calibration.json/manifest.json;为True时复制完整目录树(含assets/) - overwrite: 默认
True;为False且目标已存在时抛出FileExistsError
返回
Path或list[Path]:导出后的包目录路径
CLI
python -m orisys.export_sensors --dest ./out/sensors --names box,mini
python -m orisys.export_sensors --dest ./out/sensors --include-assets
常见问题解答 (FAQ)
Q1:为什么必须先调用get_img(),再调用compute_deformation()?
A:compute_deformation()依赖最近一次获取并拼接的图像数据进行形变与力计算。
在调用该方法前,必须先通过get_img()更新当前帧图像,否则无法进行有效计算。
Q2:为什么调用了read_info(),但读到的数据是空的?
A:read_info()仅用于读取当前已计算的数据状态,不会触发任何计算。
部分字段依赖特定计算步骤生成,例如:
VRAW / VNORMAL / VSHEAR依赖compute_deformation();DEPTH / CENTROID / CONTOUR依赖compute_contact()。
Q3:compute_contact()为一定要调用吗?什么时候需要?
A:当需要接触相关信息(如接触质心、轮廓或深度/散度图)时,必须调用compute_contact()。
若仅关注形变场或力信息(如光流、法向力、切向力),则无需调用该方法。
Q4:read_info()的返回值顺序是如何确定的?
A:read_info()按传入的sensor.info参数顺序返回一个元组。
返回值顺序与参数顺序一一对应,与内部存储顺序无关。
Q5: 运行报错:“AttributeError: 'Stitcher' object has no attribute 'pos_default'”
A: 请检查视频源的编号是否正确,以及是否能正常打开视频源。在linux 使用v4l2-ctl --list-devices 或 Windows使用Get-PnpDevice -PresentOnly | Where-Object { $_.Class -match '^Camera' } 列出摄像头设备。