- capture_calib: capture calibration images (MindVision / USB) with a live quality gate (Laplacian sharpness, 3x3 coverage, board auto-detect) - calibrate: batch intrinsics from calib_images/, writes configs/camera.yaml - camera_calib: CameraCalib loader (intrinsics + distortion, cached undistort remap) and solvePose() via IPPE with a reprojection gate - configs/camera.yaml: MV-SUA131GC intrinsics, RMS 0.483 px over 31 images, ruler-verified distance error < 2% - xmake: three targets sharing an rm_deps rule, C++17 - gitignore: keep calibration photos/videos and generated compile_commands.json out of the repo
132 lines
4.5 KiB
Markdown
132 lines
4.5 KiB
Markdown
# 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<cv::Point2f, 4> 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% 说明标定可用。
|