新增双目yolo实现python代码
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
# stereo_yolo(Python 版)
|
||||
|
||||
双目 YOLO 检测前端:在左右目图像上**独立运行** YOLO 检测器,输出符合
|
||||
`stereo_ranger` 输入契约的检测框(每目一个 `DetectionFrame`、共用 frame_id)。
|
||||
不做测距、左右目关联与立体校正。
|
||||
|
||||
规格:`docs/双目YOLO目标识别需求说明.md`(接口契约以其为准;几何语义权威
|
||||
`docs/双目测距技术路线.md`)。
|
||||
|
||||
⚠ 全部参数为占位值、demo 素材为 AI 合成图:标定与地面真值验证完成前,
|
||||
仅限台架/回放验证,不得接入实飞控制回路(规格 §7 红线同源)。
|
||||
|
||||
## 接口清单
|
||||
|
||||
| 名称 | 说明 |
|
||||
| --- | --- |
|
||||
| `StereoYoloFrontend(config, detector=None)` | 主入口;`detector` 可注入(接口 `detect(img) -> list[Detection]`,单测用假检测器) |
|
||||
| `.detect(left_img, right_img, frame_id) -> (DetectionFrame, DetectionFrame)` | 单帧检测;BGR ndarray(cv2 约定),输出框位于输入图原生坐标系 |
|
||||
| `.close()` | 释放并发线程池 |
|
||||
| `.config` | 只读配置访问 |
|
||||
| `StereoYoloConfig` / `load_from_json(path)` | 7 项配置;缺项/未知字段/类型错误/非法取值一律 `ValueError`(fail-fast) |
|
||||
| `UltralyticsDetector` | ultralytics YOLO `.pt` 后端(双实例池;`ultralytics` 延迟导入) |
|
||||
| `split_sbs(image) -> (left, right)` | side-by-side 单流裁切(宽须为偶数) |
|
||||
| `Detection` / `DetectionFrame` | 直接复用 `stereo_ranger.types`(纯值语义,§2.1 推荐) |
|
||||
| `WarnThrottle` | 告警节流(第 1 次 + 每满 100 次,带累计计数) |
|
||||
|
||||
`logger` 名称为 `stereo_yolo`,走标准 `logging`。
|
||||
|
||||
## 单帧流程(`detect` 四步)
|
||||
|
||||
1. **形状一致性**:左右图形状不一致 → 整帧拒收输出空 + WARN 节流
|
||||
(§2.2 第 2 条:禁止左右各自缩放/填充);
|
||||
2. **左右推理**:`parallel`(默认,ThreadPoolExecutor(2),§5 硬性要求)或
|
||||
`sequential`(基准对照);单目异常被隔离,该目输出空帧列表(§5 失败处理);
|
||||
3. **出口自检 + 白名单**:丢弃非有限值 / `x2<=x1` / `y2<=y1` 的框
|
||||
(§2.2 第 6 条);`class_whitelist` 非空时过滤类别;
|
||||
4. **封装**:每目一个 `DetectionFrame(frame_id, detections)`,`frame_id`
|
||||
左右共用(§2.3 同帧契约)。
|
||||
|
||||
## 实现决策(v1.0 冻结)
|
||||
|
||||
1. **ultralytics 直跑 `.pt`**(项目拍板口径):letterbox、输出解码、NMS、
|
||||
框映射回原生坐标系全部由库内完成;识别端只负责阈值外置、出口自检与
|
||||
契约封装。
|
||||
2. **双实例池**:ultralytics 单实例非线程安全,左右并发各持一份模型
|
||||
(§4 并发策略的"双实例"形态)。
|
||||
3. **无跨帧状态**:前端不持有任何历史(无追踪、无平滑、无 Coast)——
|
||||
结构性满足"只送本帧原生实测框"(§2.5 第 1 条)。
|
||||
4. **形状不一致不 raise**:按"拒收 + 空帧 + 节流 WARN"处理,与 stereo_ranger
|
||||
非同帧拒收同哲学(不阻塞整体)。
|
||||
5. **几何参数单一来源**:`stereo_yolo.json` 不存内参/原分辨率(输出框天然在
|
||||
输入图坐标系),F/B/cx/cy 唯一来源是 `utils/config/stereo_ranger.json`,
|
||||
避免两处漂移(§4 配置一致性)。
|
||||
6. **`track_id` 留 `None`**:外部追踪器注入属链路后段(§2.1;v1.1 可选)。
|
||||
|
||||
## 移植注记(C++ 侧需自行复现的库内行为)
|
||||
|
||||
本次为 ultralytics 直跑口径,以下行为在库内完成、C++ 实现必须逐项复现
|
||||
(不一致会在视差取点上引入系统性偏差):
|
||||
|
||||
| 库内行为 | C++ 需复现要点 |
|
||||
| --- | --- |
|
||||
| letterbox | 等比缩放到 `imgsz`、灰边填充(ultralytics 预测默认填充值 114);左右同一套参数(形状一致时天然满足) |
|
||||
| 输出解码 | YOLO26 检测头输出布局与解码(建议导出一份 ONNX 作为参照物;本仓环境:ultralytics 8.4 / torch 2.11 / onnx 1.18) |
|
||||
| NMS | `conf` 先过滤、NMS 用配置 IoU 门限;`max_det` 默认 300 |
|
||||
| 坐标回映 | letterbox 逆变换(scale/pad)到原生分辨率;输出 `x1,y1,x2,y2` 浮点 |
|
||||
| 并发 | 双实例双线程(单实例并发调用不安全) |
|
||||
|
||||
## 配置项(全部外置,占位值)
|
||||
|
||||
| 键 | 占位值 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `model_path` | `models/yolo26n-drone.pt` | 相对路径按启动工作目录解析(demo 内按仓库根兜底) |
|
||||
| `imgsz` | 640 | 须为 32 的整数倍(YOLO 步长约束) |
|
||||
| `conf_threshold` | 0.25 | 识别端自身过滤口径(测距端不消费检测置信度,§2.4) |
|
||||
| `iou_threshold` | 0.7 | NMS IoU 门限 |
|
||||
| `class_whitelist` | `null` | 可选白名单;同一目标左右目类别必须一致(§2.2 第 5 条) |
|
||||
| `device` | `null` | null = 自动选择(`cpu` / `cuda:0` / …) |
|
||||
| `concurrency` | `parallel` | `parallel` / `sequential` |
|
||||
|
||||
## 测试与演示
|
||||
|
||||
```bash
|
||||
cd utils
|
||||
"D:/program file/conda/envs/pytorch/python.exe" -m pytest tests/stereo_yolo -q # 36 条
|
||||
python utils/demo_stereo_yolo.py # 真模型 + 占位素材
|
||||
```
|
||||
|
||||
单测全部用注入的假检测器驱动(无模型、无素材、无硬件):frame_id 左右共用、
|
||||
出口自检丢弃退化框、白名单过滤、单目失败隔离、形状不一致拒收、双人屏障
|
||||
断言真并发(串行实现会屏障超时)。
|
||||
|
||||
demo(真模型 + AI 合成素材 `utils/assets/stereo_yolo/drone_sky.png`):
|
||||
① 单图冒烟 → ② 合成双目对(同一 patch 羽化粘贴、已知视差 12 px,实测
|
||||
|ΔD|≈0.3 px、|Δy|≈0.2 px)→ 真检测框喂 `StereoRanger.update()`,记录值与
|
||||
解析值 `Z=F·B/D` 同量级 → ③ 空场景(正常空帧不告警)→ ④ 形状不一致拒收
|
||||
→ ⑤ 帧周期实测(台架开发机 ≈34 ms/帧,占位)。替换素材文件即可换真实图片。
|
||||
|
||||
## 验收对照(规格 §6)
|
||||
|
||||
| 项 | 状态 |
|
||||
| --- | --- |
|
||||
| 坐标回映误差 <0.5 px | 由库内完成,无法构件级单测;以合成对整体校验(|ΔD|≈0.3 px @1080p,含检测边缘噪声);C++ 移植后需实测 |
|
||||
| 垂直对齐 P95 ≤1 px | 合成对实测 |Δy|≈0.2 px(合成口径,非真实校正质量);待真实素材 |
|
||||
| 类别一致性 | 模型单类 `Drone`,合成对天然一致;待真实素材 |
|
||||
| 输出合法性 | ✓ 单测(非有限值/退化框构造用例) |
|
||||
| 输入纯净性 | ✓ 结构性保证(前端无跨帧状态) |
|
||||
| 下游对接 | ✓ demo 场景②;δZ ∝ Z² 趋势由测距端单测覆盖 |
|
||||
| 帧周期 | △ 台架开发机实测 ≈34 ms/帧(30 fps 预算 33.3 ms);待平台实测(P7) |
|
||||
Reference in New Issue
Block a user