# AutoCalibration

AutoCalibration 是一个主机节点，在管线中运行自动立体校准工作流，并在运行时提供校准质量结果。

区分两个层面很重要：

 * AutoCalibration 是一个你添加到管线中的主机节点。
 * 它在内部控制和使用后台的 DynamicCalibration。
 * DEPTHAI_AUTOCALIBRATION 是自动校准的全局部署开关。

## 启用自动校准的三种方式

根据您需要的控制程度选择：

 * 全局变量（DEPTHAI_AUTOCALIBRATION） 最适合已部署的管线，当您希望在不更改代码的情况下启用自动行为时。
 * AutoCalibration 主机节点 最适合当您希望显式控制管线级别的模式、重试、验证、烧录和结果处理时。
 * 管线设置器（pipeline.setAutoCalibrationMode(...)） 最适合当您希望轻量级代码级别的控制而不添加 AutoCalibration 主机节点时。

## 通过全局变量进行自动校准

使用以下环境变量值之一：

```bash
DEPTHAI_AUTOCALIBRATION=ON_START
DEPTHAI_AUTOCALIBRATION=CONTINUOUS
DEPTHAI_AUTOCALIBRATION=OFF
```

这些值运行自动校准，而无需在应用程序中添加节点级别的 API 处理。

> 从
> `DepthAI 3.6`
> 开始，自动校准在
> `ON_START`
> 模式下默认启用。 使用
> `DEPTHAI_AUTOCALIBRATION=OFF`
> 或
> `pipeline.setAutoCalibrationMode(...OFF)`
> 禁用它。

### 行为说明

 * 适用于立体 1280x800 管线。
 * 将校准烧录为用户校准。
 * 出厂校准保持不变。
 * 如果您的管线已经包含一个
   [DynamicCalibration](https://docs.luxonis.com/software-v3/depthai/depthai-components/host_nodes/dynamic_calibration.md) 节点或一个
   AutoCalibration 节点，则基于 AutoCalibrationMode 的自动程序不会初始化。

> 在
> `ON_START`
> 和
> `CONTINUOUS`
> 过程中，新的校准被烧录为
> **用户校准**
> 。这会覆盖当前存储在设备上的现有用户校准。

### ON_START 过程

在启动期间运行自动校准，然后继续正常管线执行。

#### 示例

```bash
DEPTHAI_AUTOCALIBRATION=ON_START python3 examples/Stereo/stereo.py
```

可选的详细日志：

```bash
DEPTHAI_LEVEL=info DEPTHAI_AUTOCALIBRATION=ON_START python3 examples/Stereo/stereo.py
```

如果启动校准验证失败，则不烧录新校准。

典型的启动时间取决于场景覆盖和重试次数：

 * 快速路径：约 2.5s。
 * 通常重试路径：约 6s。
 * 最坏情况重试（maxIterations = 10）：最多约 25s。

### CONTINUOUS 过程

在运行时连续运行校准，适应变化的热/机械条件。

#### 示例

```bash
DEPTHAI_AUTOCALIBRATION=CONTINUOUS python3 examples/Stereo/stereo.py
```

可选的详细日志：

```bash
DEPTHAI_LEVEL=info DEPTHAI_AUTOCALIBRATION=CONTINUOUS python3 examples/Stereo/stereo.py
```

此模式增加了持续的处理开销，与 ON_START 不同。

## 通过管线设置器进行自动校准

当您希望在代码中显式控制模式而不添加 AutoCalibration 主机节点时，使用 pipeline.setAutoCalibrationMode(...)。

#### Python

```python
pipeline = dai.Pipeline()
pipeline.setAutoCalibrationMode(dai.Pipeline.AutoCalibrationMode.ON_START)
# 或者连续运行：
# pipeline.setAutoCalibrationMode(dai.Pipeline.AutoCalibrationMode.CONTINUOUS)

# 禁用自动校准
pipeline.setAutoCalibrationMode(dai.Pipeline.AutoCalibrationMode.OFF)
```

#### C++

```cpp
dai::Pipeline pipeline;
pipeline.setAutoCalibrationMode(dai::Pipeline::AutoCalibrationMode::ON_START);
// 或者连续运行：
// pipeline.setAutoCalibrationMode(dai::Pipeline::AutoCalibrationMode::CONTINUOUS);

// 禁用自动校准
pipeline.setAutoCalibrationMode(dai::Pipeline::AutoCalibrationMode::OFF);
```

> 如果同时设置了
> `DEPTHAI_AUTOCALIBRATION`
> 和
> `pipeline.setAutoCalibrationMode(...)`
> ，则在代码中设置的管线本地模式会覆盖环境变量。

## 管线中的 AutoCalibration 主机节点

当您希望显式控制并直接访问运行时输出时，使用此方法。

### 示例

#### Python

```python
import cv2 as cv
import numpy as np
import depthai as dai

# 创建管道
with dai.Pipeline() as pipeline:
    device = pipeline.getDefaultDevice()
    botchCalibration(device)

    camLeft = pipeline.create(dai.node.Camera).build(dai.CameraBoardSocket.CAM_B)
    camRight = pipeline.create(dai.node.Camera).build(dai.CameraBoardSocket.CAM_C)
    stereo = pipeline.create(dai.node.StereoDepth)

    dcWorker = pipeline.create(dai.node.AutoCalibration).build(camLeft, camRight)
    dcWorker.initialConfig.maxIterations = 2
    dcWorker.initialConfig.sleepingTime = 10
    dcWorker.initialConfig.flashCalibration = False 
    dcWorker.initialConfig.mode = dai.AutoCalibrationConfig.CONTINUOUS  # 连续模式（可选：ON_START）
    dcWorker.initialConfig.validationSetSize = 5 
    dcWorker.initialConfig.dataConfidenceThreshold = 0.7
    workerOutputQueue = dcWorker.output.createOutputQueue()

    videoQueueLeft = camLeft.requestOutput((1280, 800), fps=30)
    videoQueueRight = camRight.requestOutput((1280, 800), fps=30)

    videoQueueLeft.link(stereo.left)
    videoQueueRight.link(stereo.right)

    stereoOut = stereo.depth.createOutputQueue()
    pipeline.start()

    while pipeline.isRunning():
        workerOutput = workerOutputQueue.tryGet()
        if workerOutput is not None:
            if workerOutput.passed:
                print("Passed")
                print(f"dataConfidence = {workerOutput.dataConfidence}")
                print(f"calibrationConfidence = {workerOutput.calibrationConfidence}")
            else:
                print("Did not pass")

        depth = stereoOut.get()
        cv.imshow("Depth", depth)

        if cv.waitKey(1) == ord("q"):
            break
        
    pipeline.stop()
```

#### C++

```cpp
#include <iostream>
#include <memory>
#include <opencv2/opencv.hpp>
#include <vector>

#include "depthai/depthai.hpp"
int main() {
    dai::Pipeline pipeline;

    // 创建设备
    auto device = pipeline.getDefaultDevice();

    // 节点
    auto camLeft = pipeline.create<dai::node::Camera>()->build(dai::CameraBoardSocket::CAM_B);
    auto camRight = pipeline.create<dai::node::Camera>()->build(dai::CameraBoardSocket::CAM_C);
    auto stereo = pipeline.create<dai::node::StereoDepth>();

    // AutoCalibration 节点
    auto dcWorker = pipeline.create<dai::node::AutoCalibration>();
    dcWorker->build(camLeft, camRight);

    auto config = dcWorker->initialConfig;
    config->maxIterations = 2;
    config->sleepingTime = 10;
    config->flashCalibration = false;
    config->mode = dai::AutoCalibrationConfig::CONTINUOUS;
    config->validationSetSize = 5;
    config->dataConfidenceThreshold = 0.7;

    // 连接
    camLeft->requestOutput({1280, 800})->link(stereo->left);
    camRight->requestOutput({1280, 800})->link(stereo->right);

    // 队列
    auto workerOutputQueue = dcWorker->output.createOutputQueue();
    auto stereoOut = stereo->depth.createOutputQueue();

    pipeline.start();

    while(pipeline.isRunning()) {
        auto workerOutput = workerOutputQueue->tryGet<dai::AutoCalibrationResult>();
        if(workerOutput != nullptr) {
            if(workerOutput->passed) {
                std::cout << "Passed. Confidence: " << workerOutput->dataConfidence << std::endl;
            } else {
                std::cout << "Did not pass." << std::endl;
            }
        }

        auto depth = stereoOut->get<dai::ImgFrame>();
        cv::imshow("Depth", depth);

        if(cv::waitKey(1) == 'q') break;
    }

    return 0;
}
```

### 配置参数

通过 auto_calib.initialConfig 配置行为：

 * mode 选择自动校准过程（ON_START 或 CONTINUOUS）。
 * flashCalibration 如果为 true，校准通过验证后作为用户校准写入闪存。
 * maxIterations 最大校准尝试次数。
 * sleepingTime 校准尝试/迭代之间的延迟时间。
 * validationSetSize 在接受校准前使用的验证样本数量。

### 节点输出（结果）

该节点提供 AutoCalibrationResult 消息。常见字段如下：

 * passed 校准/验证是否成功。
 * dataQuality 所收集校准数据的质量指标。
 * calibrationConfidence 最终校准的置信度分数。

## 可用性与发布状态

 * DepthAI 3.5.0 通过 DEPTHAI_AUTOCALIBRATION 提供可选的启动自动校准（Beta 版）。
 * 从 DepthAI 3.6 开始，自动校准在 ON_START 模式下默认启用。
 * 使用 DEPTHAI_AUTOCALIBRATION=OFF 或 pipeline.setAutoCalibrationMode(...OFF) 可禁用它。

Install example:

```bash
python3 -m pip install depthai==3.5.0
```

## 反馈

> `AutoCalibration`
> 是一个正在积极发展的功能。如果您想帮助塑造它，在实际部署中使用该节点，并与我们在 GitHub 上分享反馈：哪些运行良好，哪些失败了，以及您希望看到哪些参数或输出得到改进。我们会根据用户反馈优先进行 API 改进。

如果遇到问题或希望改进 API，请通过以下途径报告：

 * 论坛：[discuss.luxonis.com](https://discuss.luxonis.com/)
 * GitHub：[luxonis/depthai-core](https://github.com/luxonis/depthai-core)
 * 在调试过程中收集标定数据时，请使用 [立体视觉调校辅助](https://www.luxonis.com/stereo-tuning-assistance) 并附上捕获的 zip 文件夹。

## 参考

### dai::node::AutoCalibration

Kind: class

#### dai::DynamicCalibrationControl DCC

Kind: enum

#### std::shared_ptr< AutoCalibrationConfig > initialConfig

Kind: variable

#### Output output

Kind: variable

#### std::shared_ptr< AutoCalibration > build(const std::shared_ptr< Camera > & cameraLeft, const std::shared_ptr< Camera > &
cameraRight)

Kind: function

#### ~AutoCalibration()

Kind: function

#### void run()

Kind: function

#### void setRunOnHost(bool runOnHost)

Kind: function

#### bool runOnHost()

Kind: function

Returns true or false whether the node should be run on host or not.

#### void buildInternal()

Kind: function

Function called from within the

#### DeviceNodeCRTP()

Kind: function

#### DeviceNodeCRTP(const std::shared_ptr< Device > & device)

Kind: function

#### DeviceNodeCRTP(std::unique_ptr< Properties > props)

Kind: function

#### DeviceNodeCRTP(std::unique_ptr< Properties > props, bool confMode)

Kind: function

#### DeviceNodeCRTP(const std::shared_ptr< Device > & device, std::unique_ptr< Properties > props, bool confMode)

Kind: function

### 需要帮助？

请前往 [OAKChina 官网](https://www.oakchina.cn/) 获取技术支持或解答您的任何疑问。
