14 KiB
libstereo_bolt 交付说明(.so + 头文件)
你拿到的是预编译的 aarch64 动态库 + C 头文件 + 模型 + 标定 + 示例,不含算法源码。
运行时依赖中 libstereo_bolt.so、OpenCV 4.5.0 .so、librknnrt.so 均已随包 lib/;无需 apt 安装 OpenCV。NPU 驱动由板子系统提供。
本库导出两个独立的产品接口(同一个
.so、同一个StereoBoltCtx):
- 精测(PRECISE)
sb_process_bolt_module_buffers/_files—— 12MP 高精度测量, 每颗螺栓高度 / 相邻间距 / 地平面 / 3D 中心轴 / 顶底 3D 坐标。触发式"测得准"路径(板上约 400ms/帧,依输入和 QC 耗时波动)。- 测距(RANGING)
sb_range_bolt_binned—— 2×2 binned(3MP) 实时测距, 输出相机→螺栓代表直线距离。无人机实时路径(统一用 OBB@1024,当前 distance_153304_403 复测约 153ms/帧)。创建上下文推荐用内存接口
sb_create_ex(见下节):标定、模型、参数全部经接口/buffer 传入, 库零文件 IO、无路径假设、无安装目录读权限问题。旧的sb_create(config.yaml)仍保留作向后兼容。
★ 创建上下文:sb_create_ex(推荐)vs sb_create(兼容)
两个产品接口共用同一个 StereoBoltCtx。创建它有两种方式:
推荐:sb_create_ex —— 全参数经接口传入,零文件 IO
StereoBoltCtx* sb_create_ex(const StereoBoltCalibC* calib,
const StereoBoltModelC* model,
const StereoBoltParamsC* params);
StereoBoltParamsC sb_default_params(void); /* 预填默认值,再覆盖你关心的 */
StereoBoltCalibC:标定 —— 左右K[9]/D[5]+R[9]/T[3]+baseline_mm+ 图像尺寸。替代标定 XML。StereoBoltModelC:模型 ——.rknn字节流data+size+backend(rk3588 用SB_YOLO_BACKEND_RKNN) +imgsz/conf/iou。替代 weights 文件路径。StereoBoltParamsC:算法数值参数 —— 视差带(wd_z_min/max_mm物理带,或sgbm_min/num_disparities固定带,二选一必填)、rectification、measurement.foot_rim、ranging.*。替代 config.yaml 数值键。 带struct_size做前向兼容。
这条路径库不碰磁盘:标定/模型从哪来由你决定(你的标定流程、资源文件、相机 SDK);本包提供的 calib/*.xml 与 weights/*.rknn 只是给你读进来填结构体的现成数据。
兼容:sb_create(const char* config_yaml_path)
读 config.rk3588.12mp.yaml(其内部再按相对路径找标定 XML + 模型)。有两文件依赖 + 工作目录/读权限要求——正是 sb_create_ex 要规避的。仅在离线/快速测试时用。
sb_create/sb_create_ex只调一次(载配置+标定+模型进 NPU,慢),之后每帧复用同一个ctx。sb_destroy/sb_last_error两接口共用。线程安全:同一ctx别多线程并发。
交付边界(职责划分)
本交付物是一个"算法模块",不是完整软件系统。 软件总体集成由你(接入方)负责。
| 项 | 由谁负责 |
|---|---|
双目螺栓测量/测距算法(.so + .h + 模型 + 标定 + 示例 + 文档) |
算法方(本包提供) |
板子运行时环境:aarch64 + glibc、NPU 驱动;算法依赖的 OpenCV 与 librknnrt.so 已随包 lib/ |
接入方 |
| 取图(相机驱动 / Mono8 buffer 喂入)、上层业务、UI、调度、与上位机/无人机通信 | 接入方 |
标定数据来源(填入 StereoBoltCalibC)、按 c_api.h 调用、对 height/distance/confidence 做业务决策 |
接入方 |
算法方只交付"喂进左右图 → 返回螺栓高度/距离"的纯算法能力(C ABI)。本库不碰相机、不碰网络、 不碰磁盘(
sb_create_ex+ buffer 接口)、不做悬停/对中等业务决策。逐颗confidence(trusted/suspect) +status由接入方取舍。
包内容
| 路径 | 说明 |
|---|---|
lib/libstereo_bolt.so |
预编译共享库(aarch64,含 sb_create_ex 内存接口) |
include/stereo_bolt/c_api.h |
C ABI 头文件(唯一对外接口) |
weights/best_obb_1024_0703_20260702.rknn |
NPU 模型 —— OBB 检测(精测+测距共用,imgsz 1024,FP16) |
calib/stereo_calib_20260621_202857_ascii.xml |
12MP 双目标定(0621 装配 baseline 482mm,Halcon 位姿已修正) |
config/config.rk3588.12mp.yaml |
仅 sb_create(兼容)用 + 作参数参考;sb_create_ex 不需要它 |
lib/*.so |
算法库、OpenCV 4.5.0 运行库、RKNN 运行时(aarch64 2.3.2),运行时通过 LD_LIBRARY_PATH=./lib 加载 |
INSTALL_3588.md / ABI_FINGERPRINT.txt |
板上装环境说明 / .so 二进制指纹(你的环境必须匹配) |
example/ |
C 调用示例(main.c 精测,sb_create + buffer 接口)+ CMakeLists |
编译期 vs 运行期
你不需要重编这个库(预编译成品,无源码)。你只编译你自己调用它的程序。
| 东西 | 编译你的调用程序 | 板上运行 |
|---|---|---|
c_api.h |
✅ | — |
libstereo_bolt.so |
✅(链接,带 --allow-shlib-undefined) |
✅ |
| OpenCV | 你的程序:❌ 不需要(C ABI 不暴露 cv 类型,相机直接给 Mono8 buffer) 本包 example:❌ 运行不需要系统 OpenCV |
✅ 已随包 lib/,无需 apt |
librknnrt.so |
❌ | ✅ 已随包 lib/,LD_LIBRARY_PATH=./lib |
NPU 驱动 + /dev/rknpu |
❌ | ✅ 必须(内核态) |
| 模型 / 标定 | ❌ | ✅(已在本包;sb_create_ex 由你读进来传,sb_create 由库读) |
example 用 OpenCV 只是为了独立跑(读本包的标定 XML + 测试图)。你的产品里相机直接给 Mono8 buffer、 标定来自你自己的来源,调用端无需 OpenCV,库也始终零文件 IO。
⚠️ 必须匹配的 ABI 指纹
.so 二进制里写死了依赖的 so 名字和 glibc 版本。打开 ABI_FINGERPRINT.txt 确保板子满足:
- CPU = aarch64;glibc ≥ 指纹版本(GLIBC_2.32);
- 运行时优先使用本包
lib/(内含标准 SONAMElibopencv_*.so.4.5,无需系统 OpenCV); - librknnrt 版本 = 转
.rknn的 toolkit 版本(2.3.x)。 - 指纹应列出 9 个导出符号,含
sb_create_ex/sb_default_params。
自检(应无任何 not found):ldd lib/libstereo_bolt.so | grep "not found"
公共错误码
SB_OK=0 / SB_ERR_INVALID_CONFIG=-1 / SB_ERR_IO=-2 / SB_ERR_ALGORITHM_REJECTED=-3 / SB_ERR_INTERNAL=-99。
SB_ERR_ALGORITHM_REJECTED不是崩溃,是算法判定该帧不满足expected颗(仅精测返回);仍返回已测出的部分螺栓(见下)。
接口 1 —— 精测(PRECISE)
用途:12MP 逐颗高精度测量。触发式"测得准"路径,板上 ~2.5Hz@1024。
输入:内存 Mono8 buffer(生产首选)或文件路径(离线)。buffer 尺寸必须等于标定尺寸,否则 SB_ERR_IO。
sb_status_t sb_process_bolt_module_buffers(
StereoBoltCtx* ctx,
const uint8_t* left_data, int left_width, int left_height, int left_stride_bytes,
const uint8_t* right_data, int right_width, int right_height, int right_stride_bytes,
int channels, int expected_bolt_count, StereoBoltModuleResultC* out);
sb_status_t sb_process_bolt_module_files(StereoBoltCtx*, const char* left, const char* right,
int expected_bolt_count, StereoBoltModuleResultC* out);
void sb_free_bolt_module_result(StereoBoltModuleResultC* out); /* 用完必须释放 */
输出 StereoBoltModuleResultC —— 每颗 data.bolts[i]:
height_mm(高度)top_xyz/foot_xyz(顶 / 底 3D 坐标)centerline(3D 中心轴:point+direction)left_roi/right_roi(左右图 2D 框 x,y,w,h,score)confidence(0=trusted / 1=suspect)+status另含adjacent_distances[](相邻distance_mm)、ground_plane(model[4]/rms_mm/inlier_count)。
坐标系/单位:高度、间距、3D 坐标 = mm,校正后左相机坐标系(x 右 / y 下 / z=深度,典型 z≈1600–2200mm)。
★ 部分输出契约(但不导出假高度):即使 success==0(数量不符 count_mismatch,无论检到的多还是少于 expected),
data.bolts[] 只包含完整右目配对且测量干净的螺栓(各带 height/top/foot/confidence)。idx_R < 0 的 left-only fallback 不作为产品高度输出,避免误导。failure(reason + 完整 ROI + 配对状态)始终填充,能看出缺哪颗、为何缺。
最简用法(sb_create_ex):
StereoBoltCalibC calib = {...}; /* 填 K/D/R/T/size/baseline */
StereoBoltModelC model = {.data=rknn_bytes, .size=n, .backend=SB_YOLO_BACKEND_RKNN, .imgsz=1024, .conf=0.5f};
StereoBoltParamsC p = sb_default_params(); p.wd_z_min_mm=1200; p.wd_z_max_mm=2800;
StereoBoltCtx* ctx = sb_create_ex(&calib, &model, &p); /* 一次 */
StereoBoltModuleResultC out;
sb_process_bolt_module_buffers(ctx, L,w,h,0, R,w,h,0, 1, /*expected=*/6, &out);
/* 遍历 out.data.bolts[i].height_mm / top_xyz / foot_xyz ... */
sb_free_bolt_module_result(&out); sb_destroy(ctx);
完整示例见 example/main.c。imgsz 首选 1024(OBB 模型,自动检测旋转框);交付权重 FP16(INT8 检出全废,不可用)。
高度测量模式(measurement.height_from_plane)
精测接口支持两种高度计算方式,通过 config 中 measurement.height_from_plane 切换:
| 模式 | config 值 | 高度定义 | 是否需要平面拟合 | 板上耗时(8颗场景) |
|---|---|---|---|---|
| 顶到底(默认) | height_from_plane: false |
螺杆顶端到可见底端沿拟合轴的长度 | 不需要(自动跳过) | ~400ms |
| 顶到平面 | height_from_plane: true |
螺杆顶端到支撑平面的法向距离 | 需要(StereoBM 拟合) | ~800ms |
默认关闭平面测量(height_from_plane: false),此时平面计算完全跳过,节省 300-550ms。
开启平面测量:在 config.rk3588.12mp.yaml 中修改:
measurement:
height_from_plane: true # 开启:高度 = 螺杆顶端到支撑平面的法向距离
sb_create_ex 用户:当前 StereoBoltParamsC 不含此字段,默认为 false(顶到底)。如需平面模式,使用 sb_create(config.yaml) 并在 config 中设置。
接口 2 —— 测距(RANGING)sb_range_bolt_binned
用途:实时回答"左目光心→螺栓多远"。容忍部分可见:绝不要求螺栓数,≥1 颗即给距离。当前板上约 153ms/帧(~6.5Hz)@1024。 输入:2×2 binned 内存 buffer(12MP→3MP=2048×1500),Mono8/BGR。binned 内参内部推导,无需单独 binned 标定。
typedef struct { double distance_mm; int left_x,left_y,right_x,right_y; double ncc_score,lrc_px; int confidence; } StereoBoltRangeBoltC;
typedef struct { int found; double distance_mm; int bolt_count; char status[32]; } StereoBoltRangeSummaryC;
sb_status_t sb_range_bolt_binned(
StereoBoltCtx* ctx,
const uint8_t* left_data, int left_width, int left_height, int left_stride_bytes,
const uint8_t* right_data, int right_width, int right_height, int right_stride_bytes,
int channels, StereoBoltRangeSummaryC* out, StereoBoltRangeBoltC* bolts, int max_bolts);
输出:主用 out.distance_mm(可见杆代表距离);out.found 每帧轮询;bolts[] 给出每颗候选的左右匹配点。OBB 轴路线下 ncc_score 为检测/匹配分数、lrc_px 为轴视差自洽度(字段名保留用于 ABI 兼容);NCC 回退路线下为 NCC/LRC 指标。精度目标 ±50mm(稳定区 1.3–2.4m)。
可选 ranging.* 参数(StereoBoltParamsC 里 rng_*,都有默认):z_min/max_mm 视差带、lrc_max_mm/lrc_trusted_mm 物理同根门 等。完整示例见 example/range_example.cpp。
注:
sb_create_ex即使只做测距也要求提供精测视差带(wd_z_*或sgbm_*),因为同一ctx两接口共用。
该用哪个 + 板上实测吞吐
精测 sb_process_bolt_module_* |
测距 sb_range_bolt_binned |
|
|---|---|---|
| 问题 | 每颗螺栓高度/间距/地平面/3D 坐标 | 相机离螺栓多远(代表距离) |
| 输入 | 12MP 原图(Mono8 buffer / 文件) | 2×2 binned 3MP buffer |
| 螺栓数 | 要 expected(不符=部分输出+count_mismatch) |
不要,≥1 颗即 found |
| 板上吞吐@1024 | 约 400ms/帧 | 约 153ms/帧 ≈ 6.5Hz |
| 定位 | 触发式"测得准" | 无人机实时定位反馈 |
测距历史基准于 RK3588(v4 旧模型 best_obb_1024.rknn,distance_153304_403,21 帧):均值 153.146ms,距离均值 1652.360mm,跨度 0.491mm。 v5(0703 模型)板上测距复核 0702-12mp:8/8 螺杆 status=ok,逐杆距离 1.5–2.2m 连贯;整帧 ~450–475ms。 本交付为单模型 OBB@1024(精测+测距共用)。
编译你的调用程序 + 运行
示例用 C/C++,运行时库从本包 lib/ 加载:
cd example
cmake -S . -B build -DSB_ROOT="$(cd .. && pwd)"
cmake --build build # -> bolt_demo(精测)+ range_demo(测距)
# ../lib 含 libstereo_bolt.so + OpenCV 4.5.0 + librknnrt.so
# 精测:传标定 XML + 模型 + 左右图 + 期望螺栓数
LD_LIBRARY_PATH=../lib:$LD_LIBRARY_PATH \
./build/bolt_demo ../calib/stereo_calib_20260621_202857_ascii.xml \
../weights/best_obb_1024_0703_20260702.rknn L.bmp R.bmp 6
# 测距:传标定 + 模型 + 左右图(demo 内部 2×2 binning;生产直接喂相机 binned buffer)
LD_LIBRARY_PATH=../lib:$LD_LIBRARY_PATH \
./build/range_demo ../calib/stereo_calib_20260621_202857_ascii.xml \
../weights/best_obb_1024_0703_20260702.rknn L.bmp R.bmp