# Vision Anti-Pinch — use-can ## 编译与运行 目标环境:Jetson AGX Orin、JetPack 5.1.2 / L4T R35.4.1、CUDA 11.4、TensorRT 8.5.x、OpenCV 4.5.4。 源码编译另需 CMake 3.24+ 和相应开发库。 ```bash ./scripts/build.sh # 或 make ./scripts/initialize_camera.sh # 开机后摄像头尚未初始化时执行 ./run_camera.sh # 执行 build/camera_risk ./run_camera.sh --visualize # 可选 OpenCV 本地窗口 ``` 预编译 Orin 包: ```bash cd orin ./scripts/initialize_camera.sh ./run.sh # 脚本直接 exec C++ ELF 程序 # 也可以直接执行: ./build/camera_risk --config config/camera.json ``` 默认无窗口、不保存文件;Ctrl+C / SIGTERM 停止。`--visualize` 使用 Orin 的图形桌面,关闭窗口仅停止显示、推理继续。没有桌面环境时保持无窗口推理。 ## 流水线与结果变量 ``` V4L2 MMAP 采集 / NPP UYVY 转换(线程 1) → YOLO TensorRT 检测(线程 2) → RTMW TensorRT / 隔离推理 / C++ 时序融合(线程 3) → 前后门多特征归属 / 因果中值 / mask 风险 / CAN 过滤 → shared_ptr 最新结果变量 ``` 摄像头使用有界队列并丢弃积压旧帧;可视化独立读取最新结果。 下游直接链接 `camera_risk_core`,在自己的线程中读取: ```cpp #include "camera_pipeline.hpp" #include "config.hpp" cms::CameraPipeline pipeline(cms::loadConfig("config/camera.json")); pipeline.start(); // 下游自己的循环中读取;首帧前 result 为空。 auto result = pipeline.latest(); if (result) { const auto& risk = result->risk; const auto& front = result->door_risks.at("front"); const auto& rear = result->door_risks.at("rear"); const auto& people = result->persons; // 每人 selected/smoothed/temporal 各 133 点 const auto& assignments = result->door_assignments; const auto& can = result->can; // risk.risk_type / risk.risk_level / risk.risk_score(std::optional) } // 退出时: pipeline.requestStop(); pipeline.join(); ``` `latest()` 返回拥有数据的只读快照,读者互不消费结果,旧引用不会被新帧修改。慢读者可以跳过中间帧;异常通过 `join()` 传播。停止后的快照只代表最后结果,持续控制应检查运行状态和时间戳。 公共结构定义见 `include/frame_result.hpp`,接口见 `include/camera_pipeline.hpp`。 ## CAN 与风险 - 0x391 的 data[0..3]:左前、右前、左后、右后。 - 默认左侧,`--can-side right` 切到右侧;值为 0 时对应门活跃。 - 缺失或过期(默认 1000 ms)报文输出 `CAN_UNKNOWN`,分数为空,不能解释为 clear。 - `--no-can --active-door both` 显式模拟门状态;也可选择 front/rear/none。 - 优先使用有效手部凸包,无有效手部时用人体框兜底;transition 保留 unknown 语义。 - 最终使用 `risk` 或 `door_risks`;`ungated_risk` 仅用于诊断。当前只接收门状态,不发送执行器指令。 - mask 和前后门参数来自研发机位,默认 calibration_verified=false;装车后需要重新标定。 配置位于 `config/camera.json`,模型位于 `orin/models/engines/`。详细参数: ```bash ./run_camera.sh --help ./run_camera.sh --duration 30 ./run_camera.sh --save-results /path/results.jsonl ``` 显式保存时每帧写一行 JSON,核心字段保留 frame_index、track_ids、boxes、skeletons、door_assignments、door_risks、risk、ungated_risk、can;文件由用户指定路径管理。`--video` 可使用同一 C++ 流程处理视频文件,尺寸需匹配配置。 ## 目录与打包 - `src/`:C++ / CUDA 源文件及 main.cpp。 - `include/`:头文件及下游数据结构。 - `third_party/nlohmann/`:C++ JSON 依赖及许可证。 - `config/`、`annotations/`:运行配置与标定。 - `scripts/`:编译、摄像头初始化、打包。 - `orin/`:可单独复制的 ELF 程序、模型、驱动、CAN 库和配置。 修改源码后,在 Orin 重新编译并执行 `./scripts/package_orin.sh`,或执行 `make package`。运行、打包均不使用 Python。打包后可在 orin 目录运行 `sha256sum -c SHA256SUMS`。 ## 可选保存(默认全部关闭) 三个独立参数可以单独使用,也可以组合: ```bash ./run_camera.sh --save-original --save-annotated --save-results # 独立包:./orin/run.sh --save-original --save-annotated --save-results ``` 开启任一项时,程序自动创建可执行文件所属工程的 `output/` 及三个子目录: - `original/`:`--save-original` 保存未叠加的原图,JPEG 质量 95。 - `annotated/`:`--save-annotated` 保存带框、关键点及风险文字的 JPEG,无需开启可视化窗口。 - `results/`:`--save-results` 每个完成推理的帧保存一个 JSON,包含帧号、检测框、跟踪 ID、关键点及置信度、风险和耗时;有 CAN 的分支还包含相应状态。 同一帧三类文件同名(扩展名不同),文件名包含运行标识和帧号,多次运行不覆盖。JSON 的 `images` 提供相对于 `output/` 的图片路径,未选择保存的图片为 null。源码入口写入工程 `output/`;独立包入口写入 `orin/output/`。默认不创建目录、不保存文件。 保存对象是完成推理的帧;惰性分支暂停时不新增文件。开启保存会增加编码和磁盘 I/O 开销。写入失败时报告错误并停止,不静默丢失文件。