Files
Vision/scripts/calibrate/README.md
T
dev01 fd3d6b7ab5 feat: add PnP laser solving and update 0xA5 frame to 4-float protocol
- Integrate PnP rectangle pose estimation + laser world coordinate computation from scripts/calibrate/laser_pnp.py
- Publish normalized measurement (laser/RECT) and reference (rect center) via Float32MultiArray
- Update gimbal 0xA5 frame to 18-byte format: measure_x, ref_x, measure_y, ref_y
- Add camera calibration, laser line params, and RECT_L/W constants
- Add corner ordering (TL/BL/BR/TR), SOLVEPNP_IPPE, and pose/laser visualization overlay
- Remove standalone vision_example.py (superseded by ROS2 nodes)
- Add scripts/calibrate/ with calibration and PnP tools
2026-06-03 22:38:51 +08:00

110 lines
3.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 相机标定与激光点解算
## 文件说明
| 文件 | 用途 |
|------|------|
| `calibrate.py` | 相机内参标定,交互式拍照,输出 `calibration_result.json` |
| `laser_calibrate.py` | 激光器-相机联合标定,拟合相机坐标系下的激光直线,输出 `laser_result.json` |
| `pnp_solve.py` | 矩形检测 + PnP 位姿解算,实时显示相机位姿 |
| `laser_pnp.py` | 矩形检测 + PnP 位姿解算 + 激光点世界坐标计算 |
## 棋盘格规格
- 方格边长:**15 mm**
- 内角点数:**11 列 x 8 行**(12x9 个方格)
---
## 工作流程
### 第一步:相机内参标定
```bash
python calibrate.py
```
1. 输入是否为无畸变镜头(y/n),然后输入拍摄数量(建议 15~20 张)
2. 将棋盘格以不同角度/位置放在相机视野中
3. 画面显示绿色 **CHESSBOARD DETECTED** 后,输入 `y` 并回车拍照
4. 图像自动保存到 `calibration_images/` 目录
5. 拍完后自动标定,输出内参矩阵 K 和畸变系数
6. 结果保存为 `calibration_result.json`,同时终端打印完整 JSON
### 第二步(可选):激光器-相机联合标定
> 需要开启激光,激光点投射在标定板上
```bash
python laser_calibrate.py
```
1. 自动加载 `calibration_result.json`
2. 输入拍摄数量(建议 >= 10 张),标定板以不同姿态摆放
3. 画面显示绿色棋盘格角点 + 红色激光点圆圈后,输入 `y` 拍照
4. 每张图像:PnP 解算标定板位姿 -> 提取激光点像素 -> 反投影求交 -> 得到相机坐标系 3D 点
5. 图像自动保存到 `laser_calib_images/` 目录
6. 采集完成后 PCA 拟合激光直线,输出:
- `d_cam`:激光方向向量(相机坐标系)
- `O_cam`:基准起点(直线与相机 Z=0 平面的交点)
7. 结果保存为 `laser_result.json`,同时终端打印完整 JSON
### 第三步:在线运行
**仅 PnP 位姿解算:**
```bash
python pnp_solve.py
```
将 `calibrate.py` 输出的 JSON 粘贴到文件顶部的 `CALIB_JSON` 变量中,修改 `RECT_L`/`RECT_W` 为实际矩形尺寸。
**PnP 位姿 + 激光点世界坐标:**
```bash
python laser_pnp.py
```
将 `calibrate.py` 输出的 JSON 粘贴到 `CALIB_JSON`,将 `laser_calibrate.py` 输出的 JSON 粘贴到 `LASER_JSON`,修改 `RECT_L`/`RECT_W`。
画面实时显示:
- 矩形四个角点标注(TL/BL/BR/TR)
- 右手坐标系坐标轴(X 红 / Y 绿 / Z 蓝)
- 相机平移向量 T 和旋转欧拉角 R
- 激光点世界坐标 (x, y)(仅在 `laser_pnp.py` 中)
---
## 内参矩阵缩放
内参矩阵 K 的单位是像素,与图像分辨率绑定。畸变系数(`dist`)是无量纲的,不随分辨率变化。
等比例缩放因子 $s = W_{\text{new}} / W_{\text{orig}}$:
```python
K_scaled = K.copy()
K_scaled[0, 0] *= s # fx
K_scaled[1, 1] *= s # fy
K_scaled[0, 2] *= s # cx
K_scaled[1, 2] *= s # cy
```
对应的 `pnp_solve.py` 和 `laser_pnp.py` 通过 `IMAGE_SCALE` 常量自动处理缩放。
---
## 坐标系约定
**世界坐标系**(矩形平面,Z=0):
```
TL=(0,0) ──── TR=(l,0)
│ │
BL=(0,w) ──── BR=(l,w)
```
- X 轴沿矩形长边,向右
- Y 轴沿矩形宽边,向下
- Z 轴由右手定则确定:X x Y = Z,指向观察者
**相机坐标系**:OpenCV 标准右手系,X 右、Y 下、Z 前(指向场景)。