# 27RM RoboMaster 视觉工程(MindVision 相机 + OpenCV)。 ## 构建 ```bash xmake # 产出两个程序(见下) xmake run 27RM # 跑主程序 ``` ## 程序清单 | 程序 | 用途 | |---|---| | `27RM` | 自瞄主程序 | | `capture_calib` | **相机标定图采集工具** | | `calibrate` | **标定计算工具**(照片 → 内参/畸变 → `configs/camera.yaml`) | ## 配置 ``` configs/ └── camera.yaml # 相机内参 + 畸变 + 标定元信息(由 calibrate 生成,需入库) ``` 代码里这样用(`inc/camera_calib.hpp`): ```cpp #include "camera_calib.hpp" CameraCalib calib; if (!calib.load("configs/camera.yaml")) return -1; // 启动时加载一次 cv::Mat undist; calib.undistort(frame, undist); // 每帧去畸变 // 装甲板四角点(左下、左上、右上、右下)→ 位姿 std::array corners{lb, lt, rt, rb}; if (auto pose = calib.solvePose(corners, ArmorSize::small())) { double yaw, pitch; CameraCalib::poseToYawPitch(pose->tvec, yaw, pitch); // pose->distance_mm / pose->reproj_error_px 可用于过滤坏帧 } ``` > 程序必须在工程根目录运行(`configs/` 是相对路径),或自行传绝对路径。 ## 相机标定流程 > **本工程标定板规格**:10 × 7 内角点、**方格 20.0 mm**(卡尺实测值,不是打印标称值) > **相机**:MV-SUA131GC(1/3" CMOS,3.75μm 像元)+ MV-LD-M12-2.8MM-C 镜头,输出 1280×1024 > ⚠️ M12 镜头**调焦会改变有效焦距**,标定和使用时必须保持对焦环位置一致 ### 1. 采集标定图 ```bash # 用 MindVision 相机(机器人上那台) ./build/linux/x86_64/debug/capture_calib --square 20.0 # 或改用 USB 摄像头 ./build/linux/x86_64/debug/capture_calib --usb 0 --square 20.0 ``` 按键: | 键 | 功能 | |---|---| | 空格 | 保存当前帧(默认要求检测到棋盘格) | | `f` | 强制保存(未检测到也存) | | `d` | 删除上一张 | | `c` | 开关实时角点检测显示 | | `g` | 灰度预览(排查过曝/反光) | | `q` / ESC | 退出 | 拍摄要求: - 标定板出现在画面**中心、四角、边缘**(2.8mm 广角镜头边缘畸变最大) - 姿态多样:正对、倾斜、旋转、俯仰 - 清晰不糊、光照均匀、无反光、板子贴平硬板 - **20~30 张**,保存于 `calib_images/`(已加入 .gitignore,不会入库) ### 2. 计算内参 ```bash ./build/linux/x86_64/debug/calibrate --dir calib_images --square 20.0 # 只算顶层 ./build/linux/x86_64/debug/calibrate --dir calib_all --square 20.0 # 全部 31 张(推荐) ./build/linux/x86_64/debug/calibrate --square 20.0 --show # 逐张查看角点与重投影 ``` 工具会输出重投影误差 RMS、内参 K、畸变系数、每张图误差排行,并写入 `camera_calib.yml`。 | 重投影误差 | 评价 | |---|---| | < 0.3 px | 很好 | | 0.3 ~ 0.5 px | 可接受 | | > 0.5 px | 建议重拍 | > **当前标定结果**(`calib_all/` 31 张,20mm 方格): > fx=657.47, fy=658.25, cx=625.64, cy=509.00,RMS **0.483 px** > **距离验证**:卷尺 700mm vs 程序 687~697mm,误差 **< 2%** ✓ ### ⚠️ 标定图必须同时具备「三种多样性」 | 维度 | 作用 | 不满足的后果 | |---|---|---| | **画面位置**(九宫格覆盖) | 约束**畸变系数** | 边缘畸变解不出来,RMS 偏高 | | **倾角**(正对/上下倾/左右倾/大角度) | 约束**焦距与主点** | 参数耦合,精度下降 | | **距离**(近/中/远,板子占画面 40%/20%/8%) | 约束**尺度** ⭐ | **fx 无法确定**:所有图同距离时,"焦距×距离"可整体缩放而图像不变,优化器会落到错误值,**且 RMS 依然很低**(最阴险的坑) | > 实测教训:一套 19 张、覆盖 9/9 但**距离相近**的图,标出的 fx=883(实际 659,偏差 34%),距离误差直接 +32%; > 与旧的 12 张(距离 24~65cm)合并后 fx 回到 657,误差 <2%。**距离多样性是 fx 的锚点,不可省。** ### 3. 使用内参 ```cpp cv::Mat K, D; cv::FileStorage fs("camera_calib.yml", cv::FileStorage::READ); fs["camera_matrix"] >> K; fs["dist_coeffs"] >> D; ``` 之后用 `cv::undistort` / `cv::solvePnP` 做去畸变与位姿解算。 ### 4. 距离验证(改完参数一定要做) ```bash ~/yolo-env/bin/python ~/rm_vision/verify_distance.py 图片.jpg --square 20.0 --distance 647 ``` 用卷尺量出真实距离,与程序算出的距离对比:误差 < 2% 说明标定可用。