# 手动校准

### 立体相机重新校准

估计所有相机传感器的内参和外参

[立体相机重新校准](#Stereo%20camera%20recalibration)

### ToF重新校准

校准ToF外参

[ToF重新校准](#ToF%20recalibration)

> **自动校准您的相机**
> 如果您只需要校准
> **外参**
> ，可以通过使用我们的
> [动态校准节点](https://docs.luxonis.com/software-v3/depthai/depthai-components/host_nodes/dynamic_calibration.md)
> 动态完成。

## 关于相机校准

相机校准是确定相机内参、外参和畸变参数的过程。这些参数能够将3D点准确映射到2D传感器，并帮助校正镜头畸变。

### 内参参数

内参参数定义相机的内部特性：

 * 焦距 (fx, fy)： 设置视野范围。焦距越高，视野越窄；焦距越低，视野越宽。
 * 光心 (cx, cy)： 光轴与传感器相交的主点。略有偏移（约20像素）是可接受的。这是由于镜头-传感器对齐的微小变化（如小移位或倾斜）造成的。正确校准可以补偿这些偏移，使其不影响相机的精度或性能。
 * 畸变系数： 调整镜头缺陷：
   * 径向畸变 (k1, k2, k3, k4, k5, k6)： 校正桶形或枕形效应。
   * 切向畸变 (p1, p2)： 补偿镜头-传感器未对准。
   * 薄棱镜/倾斜畸变 (s1, s2, s3, s4, τx, τy)： 解决倾斜问题，尤其在广角镜头中。

### 外参参数

外参参数描述相机相对于场景或其他相机的位置和方向：

 * 旋转： 相机的方向。
 * 平移： 相机相对于参考点的位置。

这些参数对于多相机应用（如立体视觉）至关重要，因为它们允许每个相机的图像与其他相机对齐。

### 校准流程

校准是准确确定相机内参和外参的过程。稳健的校准程序通常包括：

 1. 基于标记的校准： 使用Charuco标记（棋盘和Aruco标记的组合），在不同距离和角度下放置，以获得高精度。
 2. 受控环境： 在稳定的环境中进行校准，覆盖所有相关的姿态和角度。这种方法有助于实现可重复的校准结果。
 3. 模型特定定制： 根据特定相机型号调整校准过程，以提高可靠性。

### 畸变模型

使用不同的畸变模型来校正每种镜头类型的独特畸变。这些模型基于[OpenCV的畸变模型框架](https://docs.opencv.org/4.x/d9/d0c/group__calib3d.html)，但可能针对特定相机配置进行调整。

 * 普通视场（NFOV）：
   使用标准透视模型校正径向畸变 (k1, k2, k3, …) 和切向畸变 (p1, p2)。

 * 宽视场（WFOV）：
   使用扩展透视模型，可包含多达 14个总畸变参数：
   
   1. 径向畸变： k1, k2, k3, k4, k5, k6
   2. 切向畸变： p1, p2
   3. 薄棱镜： s1, s2, s3, s4
   4. 倾斜参数： τx, τy
   
   > **注意：**
   > 在实践中，我们不会启用全部14个参数。对于广角镜头，我们启用两个额外参数（通常是τx和τy）来解决观察到的倾斜问题。这个
   > *扩展透视模型*
   > 非常适用于我们的宽视场（WFOV）镜头。

 * 鱼眼镜头：
   使用专门模型处理极端的圆形畸变。我们通常避免鱼眼校准，因为OpenCV的鱼眼支持无法满足我们的所有需求，而扩展透视模型已经能有效覆盖WFOV应用。

更多细节，请参考[OpenCV相机校准与畸变模型文档](https://docs.opencv.org/4.x/d9/d0c/group__calib3d.html)。

## 立体相机重新校准

使用[相机校准](#About%20Camera%20Calibration)部分描述的内参、外参和畸变参数，立体校准将两个相机相对于彼此对齐。根据这些参数，系统计算校正矩阵，使StereoDepth节点能够生成准确的立体视差和深度估计。

> 所有OAK相机（除
> [模组系列](https://docs.luxonis.com/hardware/platform/deploy/ffc.md)
> 外）在出厂前均已校准，因此无需重新校准。对于OAK FFC相机模组，安装相机至所需配置后需进行相机校准。

下方视频演示了校准步骤。有关校准选项的更多详情，请参阅后续章节，或运行 ./calibrate.py --help 查看所有可用校准选项。

### 前提条件

若计算机上尚无 depthai 仓库，需先克隆并安装依赖：

```bash
git clone https://github.com/luxonis/depthai.git --branch main
cd depthai
git submodule update --init --recursive
python3 install_requirements.py
```

#### 准备Charuco标定板

建议在电视或大型平板显示器上显示Charuco标定板。大屏幕效果更佳，因为图像中可见的Charuco标记更多，通常能提高校准精度。根据屏幕尺寸，我们建议全屏显示以下Charuco标定板：

 * [24英寸屏幕Charuco标定板](https://drive.google.com/file/d/1phwh_6jrwDddYP2Efb-Mw93e1H_d3j4F/view?usp=drive_link)
 * [28英寸屏幕Charuco标定板](https://drive.google.com/file/d/1FV2jNvzMkOBqdP_a8ULEGKOZxR5c-rWU/view?usp=drive_link)
 * [32英寸屏幕Charuco标定板](https://drive.google.com/file/d/1oR_WLaL2iXKXkWci68s55C38Bb74PJer/view?usp=drive_link)
 * [36英寸屏幕Charuco标定板](https://drive.google.com/file/d/1483YOjJro9FAKP0X0gweeoV1x4B5Np4b/view?usp=drive_link)
 * [42英寸屏幕Charuco标定板](https://drive.google.com/file/d/1W05dPQvk3F8YM8jpMG_GhubG46AbXtWX/view?usp=drive_link)
 * [50英寸屏幕Charuco标定板](https://drive.google.com/file/d/1qb4z0omvHa0z1G3AtqMa9gCdykPQiuKX/view?usp=drive_link)
 * [55英寸屏幕Charuco标定板](https://drive.google.com/file/d/13hSTA2NUSoKyZFqzE4NRw6csfO7fMHX7/view?usp=drive_link)
 * [65英寸屏幕Charuco标定板](https://drive.google.com/file/d/1Hc3L3w9g4otGoJvRtgJmA3-Sg1RLjVGF/view?usp=drive_link)
 * [75英寸屏幕Charuco标定板](https://drive.google.com/file/d/1pyGY5CPhn09Vdxb9wH90SoBFKzu4OYww/view?usp=drive_link)

若屏幕尺寸不同，请向下取整至最接近的尺寸。

#### 显示Charuco标定板

显示Charuco标定板时，标记和方格应清晰可见。请注意：

 * 避免屏幕过亮或过暗。
 * 避免屏幕受到强烈光线或阳光直射。
 * 全屏显示Charuco标定板。

注意显示的Charuco标定板上方格的大小。这是校准脚本的 SQUARE_SIZE_IN_CM 参数。

### 校准

请根据您的设备选择适当的校准流程：

#### Compact devices

#### 运行校准脚本

将占位参数值替换为有效条目：

```bash
python3 calibrate.py -s [SQUARE_SIZE_IN_CM] --board [BOARD] -nx [squaresX] -ny [squaresY]
```

例如，在32英寸屏幕上校准OAK-D S2：

```bash
python3 calibrate.py -s 3.76 --board OAK-D-S2 -nx 17 -ny 9
```

#### Modular devices

#### 准备板配置

模组型设备（OAK-FFC-4P、3P、6P）需要自定义板配置文件，该文件描述设备的相机配置。

请使用[此处](https://github.com/luxonis/depthai-boards/tree/main/boards)的某个 .json 板文件作为模板，创建自定义板配置。

> 最好使用与自定义板相机配置相似的模板。

在板配置中，我们定义相机、其插座及其相对于其他相机的位置。每个相机应包含以下信息：

| 特性 | 详情 |
| --- | --- |
| 相机板插座 | 定义在板PCB上（如 `CAM_A`, `CAM_B`, `CAM_C`, `CAM_D`...） |
| 相机模组HFOV | [硬件目录](https://docs.luxonis.com/hardware.md) |
| 相机类型 | 彩色/单色 |
| 相机外参 | 平移 [x, y, z] 和旋转 [r, p, y] |

例如，OAK-FFC-4P配备两个OV9282（PY003）相机，立体基线14.8cm，IMX378（PY052）位于两者之间，距右侧单目相机5cm：

```json
{
    "board_config": {
        "name": "Custom FFC",
        "revision": "R1M0E1",
        "cameras": {
            "CAM_C": {
                "name": "right",
                "hfov": 71.86,
                "type": "mono",
                "extrinsics": {
                    "to_cam": "CAM_B",
                    "specTranslation": {
                        "x": 14.8,
                        "y": 0,
                        "z": 0
                    },
                    "rotation": {
                        "r": 0,
                        "p": 0,
                        "y": 0
                    }
                }
            },
            "CAM_B": {
                "name": "left",
                "hfov": 71.86,
                "type": "mono",
                "extrinsics": {
                    "to_cam": "CAM_A",
                    "specTranslation": {
                        "x": -9.8,
                        "y": 0,
                        "z": 0
                    },
                    "rotation": {
                        "r": 0,
                        "p": 0,
                        "y": 0
                    }
                }
            },
            "CAM_A": {
                "name": "middle",
                "hfov": 69,
                "type": "color"
            }
        },
        "stereo_config": {
            "left_cam": "CAM_B",
            "right_cam": "CAM_C"
        }
    }
}
```

另一个使用OAK-FFC-4P但无彩色相机的示例：

```json
{
    "board_config": {
        "name": "Custom FFC",
        "revision": "R1M0E1",
        "cameras": {
            "CAM_C": {
                "name": "right",
                "hfov": 71.86,
                "type": "mono",
                "extrinsics": {
                    "to_cam": "CAM_B",
                    "specTranslation": {
                        "x": 14.8,
                        "y": 0,
                        "z": 0
                    },
                    "rotation": {
                        "r": 0,
                        "p": 0,
                        "y": 0
                    }
                }
            },
            "CAM_B": {
                "name": "left",
                "hfov": 71.86,
                "type": "mono"
            }
        },
        "stereo_config": {
            "left_cam": "CAM_B",
            "right_cam": "CAM_C"
        }
    }
}
```

> 请务必将自定义板配置放置在
> `depthai`
> 仓库的
> `resources/depthai_boards/boards/`
> 文件夹中。

#### 运行校准脚本

设置好板配置后，使用JSON配置的名称作为板名称运行校准：

```bash
python3 calibrate.py -s [SQUARE_SIZE_IN_CM] -brd OAK-FFC-4P.json -nx [squaresX] -ny [squaresY]
```

例如，对于上述测量的17x9 Charuco标定板：

```bash
python3 calibrate.py -s 3.76 -nx 17 -ny 9 -brd OAK-FFC-4P.json
```

| 参数 | 参数别名 | 参数描述 |
| --- | --- | --- |
| `-s` | `--squareSizeCm` | 打印的 charuco 板的正方形尺寸（厘米） |
| `-brd` | `--board` | 相机名称（来自 [depthai-boards](https://github.com/luxonis/depthai-boards/tree/main/boards)，不区分大小写），或自定义 .json
板配置文件路径 |
| `-nx` | `--squaresX` | X 方向的正方形数量。squaresX 在 [准备 Charuco 板](#Prepare%20Charuco%20Board) 中指定，取决于您的屏幕尺寸。 |
| `-ny` | `--squaresY` | Y 方向的正方形数量。squaresY 在 [准备 Charuco 板](#Prepare%20Charuco%20Board) 中指定，取决于您的屏幕尺寸。 |
| `-cm` | `--cameraMode` | 相机模式，`perspective`（默认）或 `fisheye`。 |
| `-mdmp` | `--minDetectedMarkersPercent` | 一帧中检测到的标记的最小百分比，用于将该帧视为有效。默认值为 0.5（50%）。如果您想更严格，可以增加此值，但这可能会导致获取足够有效帧的时间变长。 |
| `-ep` | `--maxEpipolarError` | 最大极线误差（像素），用于将该帧视为有效。默认值为 0.7。如果您想更严格，可以减小此值。 |

有关参数的完整列表和使用示例，请运行：

```bash
python3 calibrate.py --help
```

#### 校准过程中的相机定位

我们建议从不同的角度和距离进行校准拍摄，这将有助于校准算法找到最佳校准结果。

1. 靠近屏幕：确保校准板几乎覆盖整个视场角（FOV）。拍摄 5 张图像以覆盖相机的整个 FOV：

 * 正面视图，校准板位于 FOV 中央。
 * 不移动相机，旋转以将相机 FOV 与校准板边缘对齐。拍摄 4 张图像，分别对应屏幕的四个边缘。

2. 靠近屏幕，从侧面：拍摄 4 张或更多倾斜校准板的图像，覆盖大部分 FOV。将相机移动到屏幕的顶部、底部、左侧和右侧。可以使用不同的距离。

3. 中等距离：校准板应覆盖约 40% 的 FOV。拍摄 5 张图像以覆盖相机的整个 FOV：

 * 正面视图，校准板位于 FOV 中央。
 * 与靠近屏幕的位置类似，旋转相机以将 FOV 与校准板边缘对齐。

4. 远离屏幕：校准板仅覆盖 FOV 的一小部分。总共拍摄 9 张图像以覆盖相机的整个 FOV：

 * 正面视图，校准板位于 FOV 中央。
 * 拍摄 4 张图像，将相机 FOV 与所有四个边缘对齐，类似于靠近和中等距离的位置。
 * 另外，拍摄 4 张图像，与屏幕的四个角对齐。

#### 运行处理阶段

拍摄图像后，您可以通过按 s 键运行校准处理阶段。脚本会显示每张图像的极线，您应验证它们是否正确对齐。检查完所有图像后，校准结果（如果成功）将刷写到设备的 EEPROM 中。 每张拍摄的图像都保存在 dataset
文件夹中，因此您无需重新拍摄图像即可重新运行校准过程。

如果您想对已拍摄的图像重新运行校准过程，请使用 -m process 参数：

```bash
python3 calibrate.py -s [SQUARE_SIZE_IN_CM] --board [BOARD] -nx [squaresX] -ny [squaresY] -m process
```

校准结果存储在 resources/ 文件夹中，可在以后用于测试或调试。您也可以将此本地校准文件加载或刷写到设备。有关更多详细信息，请参阅
[校准加载示例](https://docs.luxonis.com/software/depthai/examples/calibration_load.md#calibration-load)。

### 测试深度

要测试深度质量，请使用 OAK Viewer，按照 [OAK Viewer 使用说明](https://docs.luxonis.com/software-v3/depthai/tools/oak-viewer.md) 操作。

### 故障排除

 * 如果校准失败并出现错误：High reprojection error!，通常的原因是板配置文件配置错误，通常是由于指定了错误的相机模块 HFOV。
 * 如果校准成功但深度仍然不正确，可能是您的左右相机接反了。请使用更改后的板配置文件重新尝试校准，或交换相机插入的板接口。

## ToF 重新校准

飞行时间（ToF）校准对于将 ToF 传感器与系统中的其他相机对齐至关重要。此过程侧重于获取外参，对于确保不同相机之间的协调运行至关重要。

> 请注意，此校准不会提高深度精度，因为该方面由设备的固件管理。

### 校准步骤

如果您已经安装了 DepthAI 仓库，请通过以下命令更新它以支持 TOF 校准：

```bash
git checkout new_tof_calib
git submodule update --init --recursive
```

更新电路板后，安装更新后的 DepthAI Python 库：

```bash
python3 ./install_requirements.py
```

要开始校准过程，请使用适合您的 Charuco 板的参数运行 calibrate.py。例如：

```bash
python3 calibrate.py -db -nx 12 -ny 9 -c 1 -cd 0 -s 6 -ms 4.7 -brd OAK-D-SR-POE
```

参数说明：

 * -db：表示默认板，即您正在使用 Charuco 标记。
 * -nx：x 方向上的 Charuco 标记数量。
 * -ny：y 方向上的 Charuco 标记数量。
 * -c：每次显示多边形时拍摄的图片数量（可选）。
 * -cd：拍摄图片前的倒计时时间（秒，可选）。
 * -s：Charuco 标记周围正方形的边长（厘米）。
 * -ms：标记的边长（厘米）。
 * -brd：设备的板型（此处为 OAK-D-SR-POE）。

如果遇到诸如 division by zero 或 Failed to detect markers in the image dataset/rgb/rgb_p3_10.png 的错误，请从所有相机文件夹中删除 Charuco
板检测效果不佳的图像，然后使用添加了 -m process 参数的相同命令再次运行。这样只会启动处理阶段，因此您无需重新拍摄板图像。

```bash
python3 calibrate.py -db -nx 12 -ny 9 -c 1 -cd 0 -s 6 -ms 4.7 -brd OAK-D-SR-POE -m process
```
