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

167 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# libstereo_bolt 交付说明(.so + 头文件)
你拿到的是**预编译的 aarch64 动态库 + C 头文件**,不含算法源码。
OpenCV 4.5.4、RKNN runtime 及全部传递依赖(约 131 个 `.so`**已随包内置于 `lib/`**
无需在目标板上安装任何软件包NPU 内核驱动由固件提供,不在用户态包内)。
> **本包标定 = 12MP 生产相机4096×3000。** 喂进来的左右图必须是该相机的 **4096×3000** 帧
> `config` 里 `image.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.373**5MP 那套是 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.so`RKNN 运行时) | ❌ | ✅ **已随包 `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`
```bash
ldd lib/libstereo_bolt.so | grep "not found"
```
---
## 板子上需要准备的
| 依赖 | 状态 |
|---|---|
| OpenCV 4.5.4 + 传递依赖131 个 .so | ✅ **已随包 `lib/`**,无需 apt |
| `librknnrt.so`RKNN 运行时 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`。有**两个**喂帧入口,生产用内存版:
**① 生产路径 —— 内存版(不落盘,直接喂相机帧):**
```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` **必须等于标定分辨率**(`config` 的 `image.width`/`image.height`),否则返回 `SB_ERR_IO`。
> 内存版**全程不碰磁盘**(已实测:删掉源文件后内存版照常出结果)。
**② 离线/测试路径 —— 文件版(读磁盘图,用你自己的 12MP 左右图):**
```c
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_create``config/config.rk3588.yaml`(内部指向 `calib/*.xml``weights/best.rknn`)。
- 每帧(生产用 `sb_process_bolt_module_buffers`):左/右 Mono8 内存缓冲 + 宽/高/stride、通道数、期望螺栓数(int)、`&out`
- 每帧(离线用 `sb_process_bolt_module_files`):左图路径、右图路径、期望螺栓数(int)、`&out`
**输出**`StereoBoltModuleResultC out` + 返回码)
- 成功 `out.success==1``out.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_plane``model[4]`(ax+by+cz+d=0)、`rms_mm``inlier_count`
- 失败 `out.success==0``out.failure``reason` + `left_rois[]`/`right_rois[]` + `pairs[]`(配对诊断)
**单位 / 坐标系**:高度、间距 = **mm**3D 坐标(foot/top/centerline) = **mm校正后左相机坐标系**
x 右 / y 下 / z=深度,典型 z≈16002200mm`score`=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 中心轴 + 相邻间距 + 地平面,或失败原因 + 诊断。**
---
## 编译你自己的调用程序 + 运行(**都在包根目录执行**
```bash
# 在包根目录(与 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
```