7.9 KiB
- 系统目标
检测靶纸四角的等腰直角三角形标记(每个角一个)
计算激光落点在靶面上的二维偏移(厘米)
通过PnP算法估算靶面到相机的距离(米)
- 核心算法流程 2.1 三角形检测 (detect_triangle_markers) 采用多策略级联保证鲁棒性: 图像输入 → 多阈值策略 → 候选三角形过滤 → 四点匹配 检测策略(按优先级):
1.全局Otsu二值化(最快,~10ms) 2.自适应阈值(多种block size,光照不均时) 3.ROI局部阈值(候选不足3个时,分象限独立处理) 4.Black-Hat形态学增强(仍不足时,突出暗色标记)
三角形几何验证:
必须是直角三角形(检查勾股定理,容差20%)
两直角边长度差<20%
内部像素足够暗(灰度≤130,暗像素比例≥30%)
与周围背景对比度≥15灰度级
四点匹配算法:
从候选三角形中枚举所有4点组合
计算四边形评分:(对角比-1)*3 + (水平比-1) + (垂直比-1) + (边长偏差)*2
选择评分最低的组合作为四角标记
2.2 单应性落点计算 (homography_calibration) 建立图像坐标系 → 靶面坐标系(二维平面)的透视变换
将激光点像素坐标映射到靶面坐标(厘米)
使用RANSAC提高鲁棒性(阈值1像素)
2.3 PnP距离估计 (pnp_distance_meters) 已知四个标记点的三维坐标(x,y,z,单位cm)
通过solvePnP求解相机外参(旋转+平移)
距离 = ‖平移向量‖ / 100(转换为米)
- 关键优化策略 3.1 多路径投票 同一图像区域被不同二值化方法检测到时,path_votes++
选择投票数高的候选,提高检测可信度
3.2 早退机制 候选≥3个 且 覆盖3个以上象限 → 停止更多阈值尝试
大幅降低嵌入式设备计算开销
3.3 3点补全机制 当只检测到3个角时,通过仿射变换估算第4个角位置
公式:P_missing = M_inv @ [x_target, y_target, 1]
3.4 图像缩放 默认缩放到0.5倍进行检测(由config控制)
坐标还原时乘以inv_scale,保持与标定矩阵一致
- 数据流示例 python 输入:
- img_rgb: H×W×3 图像
- laser_xy: (x_px, y_px) 激光点像素坐标
- marker_positions: {0:[0,0,0], 1:[0,30,0], 2:[30,30,0], 3:[30,0,0]} # 4角3D坐标(cm)
输出: { "ok": True, "dx_cm": 2.5, # 靶面X偏移(cm,向右为正) "dy_cm": -3.2, # 靶面Y偏移(cm,向上为正) "distance_m": 5.43, # 相机到靶面距离(米) "offset_method": "triangle_homography", "distance_method": "pnp_triangle" } 5. 鲁棒性设计 5.1 参数自适应 从config.py动态读取所有阈值(可在线调整)
三角形边长范围、灰度阈值、对比度要求等均可配置
5.2 异常处理 角点退化检测(距离<3像素判定为重复)
NaN/Inf校验(单应性矩阵、偏移量、距离)
距离合理性检查(0.3~20米)
5.3 降级策略 PnP失败 → 只输出偏移,距离置None
4角检测失败 → 尝试3角补全
快速路径失败 → CLAHE增强兜底(可选)
- 性能特点 CPU友好:默认Otsu单次处理,多数场景10-30ms完成检测
内存可控:最大候选数截断(默认10个),避免组合爆炸
嵌入式适配:支持图像缩放、早退机制降低计算量
- 局限性 依赖四个等腰直角三角形(需靶纸特殊设计)
要求三角形内部足够暗、与背景有对比度
单应性假设靶面为平面(实际靶纸可能有轻微起伏)
这套算法在射击训练系统中作为主要定位手段。
- 为了加速单应性的计算,引入了yolo模型,一共做了两个模型,一个为靶纸和黑色三角形一体的识别模型,用于做原照片上快速找到靶纸区域。另一个模型是黑色三角形的模型,用于做靶纸区域再找黑色三角形。但是经过对比发现,引入黑色三角形模型反而更慢。入下面的流程A和流程B: yolo靶纸+传统(流程B) yolo靶纸+yolo黑色三角形(流程A) 平均值 646.08 916.4457143 标准差 94.61300968 57.40401849
公共前置(两条路都一样) 是否用靶环模型裁 Stage1
TRIANGLE_YOLO_ROI_ENABLE=True 时:跑 靶环 YOLO,得到全图上的 roi_xyxy,后面的三角形都在 img_work = 全图[roi] 上做(必要时再缩成 img_det 给整图传统分支用)。 False 时:roi_xyxy=None,三角形在 整幅相机图 上当 img_work。 之后都进入 try_triangle_scoring(img_cv, …, roi_xyxy=…, black_yolo_boxes_work=…)
在里面先做灰度、v_suppress、锐化、det_scale 缩略图等 prep(与是否黑三角模型无关)。 差别从 black_yolo_boxes_work 有没有有效子框列表 开始。
流程 A:用黑色三角形模型(Stage2 黑三角 YOLO) 配置要点:TRIANGLE_BLACK_YOLO_ENABLE=True,且 TRIANGLE_BLACK_TRIANGLE_LOCATE_MODE="yolo",并且 已有 Stage1 裁切(roi_xyxy 不能为 None,否则根本不会跑黑三角 YOLO)。
步骤概要:
try_black_triangle_boxes_work
输入:全图 RGB + Stage1 的 ring_roi_xyxy。 在 Stage1 裁切图(与训练一致的 slab)上跑 黑三角 YOLO,得到若干个 子框(black_boxes_work,坐标在 裁切图/work 系)。 try_triangle_scoring 内
若 black_yolo_boxes_work 非空: 按配置在 Stage1 全分辨率灰度(或缩略灰度,视 det_scale / TRIANGLE_BLACK_YOLO_PATCH_GRAY_SOURCE)上,对每个子框裁 patch,跑 _extract_triangle_from_yolo_patch(子框内:Otsu → 失败再单次 Adaptive + 轮廓 + 形状/颜色)。 median_leg 过滤,再 四点分配 ID。 若 ≥3 个(通常 4 个)有效:认为 Stage2 成功,跳过 整幅 Stage1 上的 detect_triangle_markers。 若 不足 3 个 且未关 fallback:在 缩略后的整幅 work 灰度上再走 detect_triangle_markers(整图 Otsu + 整图 Adaptive×block_sizes + 各类 fallback),与「不用黑三角模型时的传统主路径」同类。 后续
角点从 det 坐标 ×inv_scale 回到 work,再 +roi 原点 回到全图;单应性、补第 4 点、PnP 等与另一条路相同。 耗时上多出来的部分:黑三角 YOLO 推理 + 每个子框一遍传统小流水线(成功时通常 不再付整图 detect_triangle_markers)。
流程 B:不用黑色三角形模型(纯传统定位三角) 典型配置(任一即可达到「不用黑三角模型」的效果):
TRIANGLE_BLACK_YOLO_ENABLE=False,或 TRIANGLE_BLACK_TRIANGLE_LOCATE_MODE="traditional"(即使模型开关开着也不跑黑三角 YOLO),或 没有 Stage1 ROI(roi_xyxy is None)时,当前逻辑下 也不会跑 Stage2 黑三角 YOLO。 此时 black_yolo_boxes_work=None(或不等价于「有子框」)。
步骤概要:
try_triangle_scoring 内 不跑 子框 _extract_triangle_from_yolo_patch。 直接在 img_det(缩略后的 work) 上调用 detect_triangle_markers: 全局 Otsu(若 TRIANGLE_SKIP_GLOBAL_OTSU_EXTRACT_ON_YOLO_ROI 在有 ROI 时可能 不算 Otsu 轮廓,但仍会生成 Otsu 图供后续用); 可选 象限 ROI(TRIANGLE_ROI_ENABLED); 整图 Adaptive(TRIANGLE_ADAPTIVE_BLOCK_SIZES,例如 (11,)); 不足再走 放宽 approxPolyDP、BlackHat 等。 后面同样是过滤、四点组合/象限分配、单应性、PnP 等。 特点:没有黑三角 NPU 时间,也 没有「按框重复 4 次子框传统」;但要在 一整张(缩略)ROI 图 上跑一套更重的 整图 pipeline。
对照一句话 用黑三角 YOLO(流程 A) 不用黑三角 YOLO(流程 B) Stage2 黑三角模型给子框 → 子框内 Otsu + 至多一次 Adaptive 无 Stage2 模型 三角角点从哪来 优先 子框传统;不够再 整图 detect_triangle_markers 只有 整图 detect_triangle_markers 和「全图是否只做 Adaptive」 子框 不是只做 Adaptive;整图回退时也与全图路径一致(先 Otsu 等) 整图路径 也不是只做 Adaptive 靶环 YOLO(Stage1 裁切)在 A/B 里都可以开或关,与「黑三角模型」是独立开关。