2026-06-26 17:55:15 +08:00

8.5 KiB
Raw Blame History

libstereo_bolt 交付说明(.so + 头文件)

你拿到的是预编译的 aarch64 动态库 + C 头文件,不含算法源码。 OpenCV 4.5.4、RKNN runtime 及全部传递依赖(约 131 个 .so已随包内置于 lib/ 无需在目标板上安装任何软件包NPU 内核驱动由固件提供,不在用户态包内)。

本包标定 = 12MP 生产相机4096×3000 喂进来的左右图必须是该相机的 4096×3000configimage.width=4096 / height=3000 已配好,指向 calib/stereo_calib_20260607_211135.xml)。 包内不含测试图 —— 请用你自己这套 12MP 相机拍的左右图。 已在板上实测:本 12MP 标定加载 + rectify 通过4096×3000stereo_rms=0.373、baseline=200.19、f_rect=3330⚠️检测 + 测量在该相机上还没用真实螺杆图验过(包内无螺杆图)。 ⚠️ 本标定单相机 RMS=0.3735MP 那套是 0.19),已把 calibration.max_single_rms 放宽到 0.40 才放行; 0.373 偏松会折损测量精度,建议后续重标到 <0.20 再收回此闸。首次上机务必用真实螺杆图核对结果。

包内容

路径 说明
lib/libstereo_bolt.so 预编译共享库aarch64
lib/librknnrt.so 等(共 ~131 个) OpenCV 4.5.4 + 全部传递依赖(已随包,无需 apt
include/stereo_bolt/c_api.h C ABI 头文件(唯一对外接口)
weights/best_1280_20260621.rknn NPU 模型(精测 + 测距共用imgsz 1280
calib/stereo_calib_20260621_202857_ascii.xml 出厂标定0621 装配baseline 482 mm
config/config.rk3588.12mp.yaml 配置文件(兼容 sb_create 接口用)
example/ 最小 C 示例(精测 + 测距) + CMakeLists
INSTALL_3588.md 安装与运行说明(从这里开始
DEPENDENCIES.md 依赖库详细清单及说明
ABI_FINGERPRINT.txt 二进制 ABI 指纹

你什么时候需要什么(编译期 vs 运行期)

重点:你不需要重编这个库(它是预编译好的成品,你也没有源码)。你只编译你自己 调用它的小程序那一步几乎零依赖。OpenCV / librknnrt 是运行那一刻才需要的。

东西 编译你自己的调用程序 在板上运行
c_api.h
libstereo_bolt.so (链接,带 --allow-shlib-undefined
OpenCV 4.5.4 不需要C ABI 不暴露 cv 类型) 已随包 lib/,无需安装
librknnrt.soRKNN 运行时) 已随包 lib/
NPU 驱动 + /dev/rknpu 必须(内核态)
.rknn 模型 + 标定 XML + config 必须(已在本包 weights/ config/ calib/

“YOLO 依赖”在板上很轻:就是 librknnrt.so + NPU 驱动 + .rknn 文件。 不需要 Python / PyTorch / ultralytics / ONNXRuntime / rknn-toolkit2 —— 那些是 PC 上把 .onnx 转成 .rknn 用的,转完板上就用不到。


⚠️ 必须匹配的 ABI 指纹(动态链接的硬约束)

这个 .so 在某个具体环境里编出来,二进制里写死了它依赖的 so 名字和 glibc 版本。 “自己准备 OpenCV” 不等于随便哪个 OpenCV 都行——必须是指纹里那个 major.minor。

打开 ABI_FINGERPRINT.txt,确保你的板子满足:

  • CPU 架构 = aarch64
  • glibc ≥ 指纹里的版本(低于它,加载即 GLIBC_x.xx not found
  • OpenCV soname 与指纹一致(本包指纹 = libopencv_core.so.4.5d ⇒ 装 OpenCV 4.5.x;其它版本 soname 不通用)
  • librknnrt 版本 = 转换 .rknn 所用 toolkit 版本(2.3.x

一条命令自检(应当没有任何 not found

ldd lib/libstereo_bolt.so | grep "not found"

板子上需要准备的

依赖 状态
OpenCV 4.5.4 + 传递依赖131 个 .so 已随包 lib/,无需 apt
librknnrt.soRKNN 运行时 2.3.2 已随包 lib/
.rknn 模型 + 标定 XML + config 已随包 weights/ calib/ config/
NPU 内核驱动 + /dev/rknpu ⚠️ 板子固件提供,出厂 RK3588 一般已有
glibc ≥ 2.32Ubuntu 22.04 自带 2.35 系统自带,无需操作

完整依赖说明见 DEPENDENCIES.md


怎么用C ABI

完整示例见 example/main.c。有两个喂帧入口,生产用内存版:

① 生产路径 —— 内存版(不落盘,直接喂相机帧):

StereoBoltCtx* ctx = sb_create("config/config.rk3588.yaml");   // 一次:载配置/标定/RKNN 模型
while (抓帧) {
    const uint8_t* L = camera_left_frame();    // 相机 SDK 给的 Mono8 缓冲(W*H 字节,在内存)
    const uint8_t* R = camera_right_frame();
    StereoBoltModuleResultC out;
    sb_process_bolt_module_buffers(ctx,
        L, W, H, 0,        // stride=0 表示行紧凑排列(每行 W 字节)
        R, W, H, 0,
        1,                 // channels: 1=Mono8(灰度), 3=BGR 也接受(内部转灰度)
        8, &out);          // 8 = 期望螺栓数
    /* out.success==1: out.data.bolts[i].height_mm / foot_xyz / top_xyz + adjacent_distances + ground_plane
       out.success==0: out.failure.reason + left_rois/right_rois/pairs(诊断用) */
    sb_free_bolt_module_result(&out);
}
sb_destroy(ctx);                                               // 一次

W/H 必须等于标定分辨率(configimage.width/image.height),否则返回 SB_ERR_IO。 内存版全程不碰磁盘(已实测:删掉源文件后内存版照常出结果)。

② 离线/测试路径 —— 文件版(读磁盘图,用你自己的 12MP 左右图):

sb_process_bolt_module_files(ctx, "your_left.bmp", "your_right.bmp", 8, &out);

图必须是本套 12MP 相机的 4096×3000(灰度或彩色均可),格式 .bmp/.tiff/.png。本包不含测试图。

错误码: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 不是崩溃,是算法判定该帧不可测,out.failure 里有原因 + ROI + 配对状态。


输入 / 输出(契约)

输入

  • 一次性(sb_createconfig/config.rk3588.yaml(内部指向 calib/*.xmlweights/best.rknn)。
  • 每帧(生产用 sb_process_bolt_module_buffers):左/右 Mono8 内存缓冲 + 宽/高/stride、通道数、期望螺栓数(int)、&out
  • 每帧(离线用 sb_process_bolt_module_files):左图路径、右图路径、期望螺栓数(int)、&out

输出StereoBoltModuleResultC out + 返回码)

  • 成功 out.success==1out.data
    • bolts[] 每颗:bolt_id / left_roi,right_roi(x,y,width,height,score) / height_mm / foot_xyz,top_xyz(底/顶 3D 点) / centerline(3D 轴 = point+direction)
    • adjacent_distances[]bolt_id_i,bolt_id_j,distance_mm
    • ground_planemodel[4](ax+by+cz+d=0)、rms_mminlier_count
  • 失败 out.success==0out.failurereason + left_rois[]/right_rois[] + pairs[](配对诊断)

单位 / 坐标系:高度、间距 = mm3D 坐标(foot/top/centerline) = mm校正后左相机坐标系 x 右 / y 下 / z=深度,典型 z≈16002200mmscore=YOLO 置信度。

输出格式示例(仅示意字段结构,数值来自早先 5MP 验证机,非本包 12MP 相机):

success=1  bolts=8  distances=8
bolt 0 height=151.2mm  top=(-191.9,-122.9,1995.3)  foot=(-204.3,2.9,2078.3)
...
dist 0-1=268.3mm   dist 1-2=254.4mm   ...   dist 7-0=335.8mm

一句话:入 = 一对左右图 + 期望螺栓数(配置/标定/模型初始化时给一次); 出 = 每颗螺栓 高度 + 顶/底 3D + 3D 中心轴 + 相邻间距 + 地平面,或失败原因 + 诊断。


编译你自己的调用程序 + 运行(都在包根目录执行

# 在包根目录(与 lib/ config/ calib/ 同级)编译
cmake -S example -B example/build -DSB_ROOT="$(pwd)"
cmake --build example/build

# 在包根目录运行(config 里 calib/、weights/ 是相对路径,按当前目录解析)
# example 走【内存接口】: 读 raw Mono8 裸数据(W*H 字节)喂 sb_process_bolt_module_buffers,
# 库全程不见文件路径。your_left/right.raw = 你 12MP 相机帧 dump 的 Mono8(4096*3000 字节)
LD_LIBRARY_PATH=lib:/usr/lib:$LD_LIBRARY_PATH \
    ./example/build/bolt_demo config/config.rk3588.yaml your_left.raw your_right.raw 4096 3000 8