# ============================================================ # 双目相机螺栓测量系统配置文件 (C++ port) # # 这是 Python 项目 e:/02_Modules/StereoVisionBoltMeasurement/config.yaml # 的镜像。两者必须保持参数一致——任何一边改值,另一边同步。 # 数据路径用 Python 项目的绝对路径(见 paths 段末尾)。 # ============================================================ # ---------- 工作距离 ---------- # 从标定推导视差范围,替代 SGBM 固定 [288,1024]。 # z_min=1200 → disp_max≈1089,覆盖近处螺杆(disp~1060)。 working_distance: z_min_mm: 900 z_max_mm: 4000 # ---------- 图像基本参数 ---------- image: width: 4096 height: 3000 channels: 1 expected_dtype: "uint8" allowed_extensions: [".tiff", ".tif", ".bmp", ".png"] # ---------- 图像输入自检 ---------- image_validation: min_max_value: 10 max_saturation_ratio: 0.20 # ---------- ChArUco 标定板参数 ---------- charuco: rows: 9 cols: 9 square_length_mm: 50.0 marker_length_mm: 37.0 dict_id: 11 # DICT_6X6_1000 min_corners_per_image: 30 # ---------- 标定模块参数 ---------- calibration: source: "xml" xml_path: "calib/stereo_calib.xml" min_image_pairs: 15 max_skip_ratio: 0.30 max_single_rms: 0.40 max_stereo_rms: 0.80 expected_baseline_range: [80, 600] use_fix_intrinsic: true # ---------- 校正模块参数 ---------- # alpha=1.0 是硬约束,详见 CLAUDE.md 隐式决策 #1。 rectification: alpha: 1.0 interpolation: "cubic" validation_feature_count: 500 validation_match_count: 10 epipolar_inlier_threshold_pixel: 5.0 min_epipolar_inlier_count: 3 max_epipolar_error_pixel: 5.0 min_valid_roi_ratio: 0.25 # ---------- SGBM 立体匹配参数 ---------- # min_disparity / num_disparities 依赖 f_rect·B;如标定改了必须重算。 # 当前值假设 f_rect≈3190, B≈235mm(alpha=1.0 下)。 sgbm: min_disparity: 288 num_disparities: 736 block_size: 5 P1: 600 P2: 2400 disp12_max_diff: 1 uniqueness_ratio: 10 speckle_window_size: 100 speckle_range: 2 pre_filter_cap: 63 mode: "SGBM_3WAY" # ---------- WLS 滤波 ---------- wls: lambda_value: 8000.0 sigma_color: 1.5 # ---------- 视差自检 ---------- disparity_validation: min_valid_pixel_ratio: 0.10 min_disparity_range: 50 max_nan_ratio: 0.90 # ---------- 点云参数 ---------- # z_min_mm / z_max_mm / expected_wd_range are FALLBACK only — when run_pipeline / # c_api are wired (the standard path) SceneRuntime derives the real reachable # Z range from (f_rect, baseline, sgbm.min_disparity, sgbm.num_disparities) and # overrides these values per frame. See docs/L_100_SCENE_HANDOFF.md §6.2 and # include/stereo_bolt/scene_runtime.hpp. Keep the fallback values conservative # enough to cover every supported workpiece distance. pointcloud: z_min_mm: 600 z_max_mm: 3000 expected_wd_range: [600, 3000] min_num_points: 50000 max_z_std_mm: 800 min_bbox_extent_x_mm: 200 min_bbox_extent_y_mm: 100 sor_nb_neighbors: 30 sor_std_ratio: 2.0 voxel_downsample_min_points: 500000 voxel_size_mm: 0.5 roi_mask: enabled: false method: "hsv_threshold" hsv_lower: [0, 0, 210] hsv_upper: [180, 50, 255] morph_close_kernel: 15 dilate_px: 100 min_area_ratio: 0.02 # ---------- 2D 检测(左图分割) ---------- # mask_method: 决定 foam_mask(支撑面像素 mask) 怎么算 # "brightness" — 亮度阈值 + 最大连通域(只对原始低曝光泡沫板场景有效; # rectify ROI 外恒为 0,所以 mask 会等于 ROI 矩形) # "ransac" — 在 dense xyz_map 上 RANSAC 找主导平面, # 把"到平面 < ransac.distance_thresh_mm"的像素当 mask # 默认 "brightness" 保 parity_tests 不变,新工业数据用 "ransac" bolt_detect_2d: mask_method: "ransac" foam_brightness_threshold: 70 foam_morph_open_kernel: 21 foam_dilate_px: 0 bbox_margin_px: 60 bolt_morph_close_kernel: 15 bolt_min_area_px: 800 min_bolts: 1 max_bolts: 0 bolt_exclude_dilate_px: 0 # 硬约束:默认 0,详见 CLAUDE.md 隐式决策 #5 ransac: distance_thresh_mm: 8.0 # 点到平面距离 < 此值即视为 inlier(3σ 容忍下, # frame 100 residual_std≈2.6 mm) max_iterations: 200 min_inlier_ratio: 0.15 # 兜底:inlier 占比过低视作失败,自动回退 sample_stride: 4 # xyz_map 下采样步长(每 4×4 像素取 1 个 RANSAC 候选) morph_close_kernel_px: 9 # mask 后处理:闭运算填洞 + 最大连通域 # ---------- 参考平面 (SVD on foam mask) ---------- plane: max_residual_std_mm: 15.0 max_normal_to_axis_deg: 60 outlier_rejection_iterations: 5 outlier_mad_k: 2.5 # ---------- 支撑面几何门 ---------- # plane fit 后、bolt extract 前执行。把 bolt 的 3D 中心投影到主支撑面 # inlier OBB, 超出 OBB 超过 margin_mm 的检测会被剔除并打印 WARN。 # margin_mm 独立于 bolt.expected_diameter_mm, 避免混杂不同尺寸螺杆时 # 几何门随螺杆规格隐式变宽/变窄。 support_gate: enabled: true margin_mm: 10.0 # ---------- 螺栓几何先验 ---------- # 主路径(run_pipeline / c_api)对每颗 bolt 先跑 bbox_projection 得 h_est, # 然后 extract 内的 height 过滤改用 max(h_est × 1.3, h_est + 20 mm), # validate_measurements 改用 |measured - h_est| < bolt.height_tolerance_mm。 # 下面的 max_height_mm / extract_height_filter_mm 只剩 fallback 作用 —— 当 # bbox_projection 失败、h_est 不可得时才走全局上限。 # 工件外形规格(expected_diameter_mm)仍是真正的先验,保留。 bolt: min_height_mm: 5.0 max_height_mm: 250.0 # fallback ceiling (used only when h_est is unavailable) extract_height_filter_mm: 200.0 # fallback filter (same condition) height_tolerance_mm: 60.0 # |measured - h_est| 允许差;触发 validate_measurements 失败 expected_diameter_mm: 16.0 min_points_per_bolt: 50 max_axis_plane_angle_deg: 30 extract_fallback: "bbox_projection" # 'none' | 'bbox_projection'; 后者用 YOLO bbox + 平面法向反解高度,处理 SGBM 在窄/反光螺杆上失败的情况 # ---------- 几何测量 ---------- measurement: top_extraction_method: "percentile_on_axis" top_percentile: 0.99 plane_use_sgbm: true # 主线定义:螺杆顶点沿拟合轴线到支撑平面的交点距离。 height_from_plane: true plane_height_along_axis: true plane_anchor_max_foot_gap_std_mm: 20.0 plane_sgbm_scale: 0.25 plane_max_samples: 40000 # ---------- Diagnostics ---------- diagnostics: enabled: true blind_strip_warn_ratio: 0.25 min_roi_pointcloud_coverage_ratio: 0.001 # ---------- YOLO 螺栓检测 ---------- # 注意 C++ 端走 ONNX:先在 Python 把 best_v4_finetune.pt 导出 .onnx。 # dilate 量原本写成像素(50/30),跟距离和分辨率耦合。改成毫米后由 # scene_runtime.cpp 在运行时用 pixels_per_mm(= f / Z_repr)换算成像素, # 不同工作距离 / 不同镜头不再需要手调。 yolo: enabled: true model_path: "weights/obb.rknn" backend: "rknn" task: "obb" imgsz: 1024 conf: 0.50 dead_zone_min_valid_pts: 50 dead_zone_bbox_dilate_mm: 24.0 # = expected_diameter_mm × 1.5; 算 valid_xyz 前把 bbox 膨胀,救窄/反光螺杆 foam_bbox_dilate_mm: 16.0 # = expected_diameter_mm × 1.0; foam_mask 从 YOLO bbox 减去前用的膨胀量 # Experimental: keep sparse-global YOLO bolts only when right YOLO + local LR check pass. local_stereo_fallback: enabled: true min_valid_points: 50 # ---------- 评估通过判据 ---------- evaluation: height_max_mm: 2.0 height_p95_mm: 1.5 pair_max_mm: 2.0 pair_p95_mm: 1.5 repeatability_std_max_mm: 1.0 matching_max_distance_mm: 50.0 # ---------- 流水线行为 ---------- pipeline: fail_fast: true resume_from_checkpoint: true parallel_frames: false save_intermediate: false # ---------- 日志 ---------- logging: level: "INFO" log_to_file: true log_file: "outputs/logs/pipeline.log" # ---------- 路径 ---------- # 项目自带数据集在 data/ 下,跟 Python 工程完全脱钩。 paths: calibration_dir: "data/calib" test_dir: "E:/01_Projects/01_InProgress/hongchuang_bolt_detect_2026/image/0627-bolt-12mp" groundtruth_csv: "data/groundtruth.csv" output_dir: "outputs/macro257" stereo_params_yaml: "outputs/macro257/stereo_params.yaml"