# ToF

ToF节点将原始飞行时间传感器数据转换为深度图，并输出原始结果及滤波后的结果。该节点适用于集成ToF传感器的设备，例如：

 * [OAK-D ToF](https://shop71313603.taobao.com/?spm=pc_detail.30350276.shop_block.dshopinfo.27a17dd635FNDA)
 * [OAK-FFC ToF 33D](https://shop71313603.taobao.com/?spm=pc_detail.30350276.shop_block.dshopinfo.27a17dd635FNDA)

ToF深度可直接用于空间节点，例如[SpatialDetectionNetwork](https://docs.luxonis.com/software-v3/depthai/depthai-components/nodes/spatial_detection_network.md)和[SpatialLocationCalculator](https://docs.luxonis.com/software-v3/depthai/depthai-components/nodes/spatial_location_calculator.md)。

关于与立体视觉的深度质量对比，请参阅[ToF深度精度](https://docs.luxonis.com/hardware/platform/depth/depth-accuracy.md)。

## 如何放置

#### Python

```python
pipeline = dai.Pipeline()
tof = pipeline.create(dai.node.ToF)
```

#### C++

```cpp
dai::Pipeline pipeline;
auto tof = pipeline.create<dai::node::ToF>();
```

## 输入与输出

## DepthAI v3 ToF 架构

DepthAI v3 ToF 流水线可理解为两层：

 1. ToF 基础解码 将传感器测量值转换为基础信号（rawDepth、amplitude、intensity、phase），并处理ToF特定的解码设置，如相位解缠。
 2. 滤波阶段 通过ToF定向滤波预设和运行时滤波器配置，生成滤波后的深度输出（depth）。

在 RVC2 上，滤波阶段由主机运行。

## ToF 相机的设置差异

许多 OAK 深度示例假设经典立体布局（一个彩色摄像头 + 位于 CAM_* 插槽的立体对）。 ToF 相机通常配置为 ToF + 彩色摄像头（两个功能摄像头源），深度来自 dai.node.ToF，而非 StereoDepth。

通用应用中的常见集成陷阱：

 * 不要将ToF传感器当作普通的彩色预览源。
 * 不要在仅ToF设备上自动创建默认的立体对流。
 * 通过 ToF 构建深度，仅在需要时添加彩色流（例如对齐/叠加）。

## ToF 设置

常见基础解码设置（来自 [ToFConfig](https://docs.luxonis.com/software-v3/depthai/depthai-components/messages/tof_config.md)）：

 * 光学校正：将径向距离转换为深度（Z-map），使其行为与立体深度一致。
 * 去畸变：默认对 depth 和 amplitude 进行去畸变。
 * 相位解缠：通过增加噪声代价扩展量程。
 * 相位混洗时域滤波：通过合并混洗/非混洗捕获来降低噪声。
 * 突发模式：避免帧复用解码，以牺牲输出帧率为代价减少运动伪影。

不同解缠级别对应的近似量程：

 * 0（禁用）：最远约1.87米（80 MHz）
 * 1：最远约3.0米
 * 2：最远约4.5米
 * 3：最远约6.0米
 * 4：最远约7.5米

后处理通过 [ImageFilters](https://docs.luxonis.com/software-v3/depthai/depthai-components/nodes/image_filters.md) 和
[ImageFiltersConfig](https://docs.luxonis.com/software-v3/depthai/depthai-components/messages/image_filters_config.md)
配置。对于基于置信度的清理，请参阅
[ToFDepthConfidenceFilterConfig](https://docs.luxonis.com/software-v3/depthai/depthai-components/messages/tof_depth_confidence_filter_config.md)。

## 快速调优指南：深度图像滤波器

调优目标是平衡深度图的干净无噪与运动物体的快速准确更新。 对于ToF深度输出，delta 通常以深度单位（通常为毫米）表示，而 alpha 是 [0.0, 1.0] 范围内的混合因子。 将所有以下数值视为起点，并根据实际场景进行调优。

### 步骤 1：空白状态

开始调优前，先禁用所有滤波器。 这有助于您测量基准噪声、验证传感器放置/照明条件，并避免用软件滤波掩盖设置问题。

### 步骤 2：时间滤波器（从此开始）

首先调整 TemporalFilterParams，因为它控制随时间变化的动态平滑。

 * delta：判断深度变化是显著变化还是噪声的阈值。
   * 初始值设为 delta = 15。
   * 对于较大物体（例如 ~50 mm 物体高度），使用 delta = 25 以使运动更新更快。
   * 对于小物体，收紧至 delta = 10。
 * alpha：当前帧与历史数据的混合权重。
   * 较低的 alpha（例如 0.1）输出更平滑，但可能带来延迟/拖影。
   * 较高的 alpha（例如 0.4）更新更快，但平滑效果减弱。
 * 重要提示：delta = 0 会使几乎所有变化都变得显著，并基本绕过时间混合。

### 步骤 3：散斑滤波器

使用 SpeckleFilterParams 去除单帧中的孤立斑点和椒盐噪声。

 * differenceThreshold（别名：max_diff）：判断相邻像素是否属于同一区域的阈值。
 * speckleRange（别名：max_speckle_size）：要移除的最大区域大小。
 * 调优策略：逐渐增加 speckleRange 以去除更大的浮动斑点，但避免设值过大导致删除真实小物体。

### 步骤 4：空间滤波器

使用 SpatialFilterParams 在保留边缘的同时平滑物体表面。

 * alpha：平滑强度（通常较低的值平滑效果更强）。
 * delta：边缘保留阈值；较大的深度跳变被视为边缘，不进行混合。
 * holeFillingRadius：用周围有效数据填充无效（0）像素的半径。
 * numIterations：多次迭代可在轻微处理代价下优化输出。

### 步骤 5：中值滤波器

当仍有残留椒盐噪声时，使用 MedianFilterParams 进行最终强力清理。

 * 此节点支持的模式：MEDIAN_OFF、KERNEL_3x3、KERNEL_5x5。
 * 选择能解决噪声的最小内核，以尽量减少边缘/细节损失。

### 调优快速参考

| 滤波器 | 关键参数 | 主要用途 | 权衡 |
| --- | --- | --- | --- |
| 时间 | `delta`, `alpha` | 平滑随时间变化的动态噪声 | 平滑度 vs 运动延迟 |
| 散斑 | `speckleRange`, `differenceThreshold` | 去除孤立斑点/噪声 | 清洁度 vs 删除小物体 |
| 空间 | `delta`, `alpha`, `holeFillingRadius`, `numIterations` | 保留边缘的表面平滑 | 平滑度 vs 处理代价 |
| 中值 | `KERNEL_3x3`, `KERNEL_5x5` | 强力椒盐噪声清理 | 噪声去除 vs 边缘/细节模糊 |

有关完整参数定义和运行时配置流程，请参阅
[ImageFilters](https://docs.luxonis.com/software-v3/depthai/depthai-components/nodes/image_filters.md)、[ImageFiltersConfig](https://docs.luxonis.com/software-v3/depthai/depthai-components/messages/image_filters_config.md)
和
[ToFDepthConfidenceFilterConfig](https://docs.luxonis.com/software-v3/depthai/depthai-components/messages/tof_depth_confidence_filter_config.md)。

## ToF 运动模糊

为减少运动模糊：

 * 提高传感器帧率（最高 160 FPS），但需考虑更高系统负载和更短曝光时间。
 * 禁用相位切换时间滤波器（噪声更高）。
 * 禁用相位解包裹（降低最大测程）。
 * 在适用时启用突发模式。

## 最大距离

最大距离取决于调制频率和相位解包裹设置。

```math
c = 299792458.0 # 光速，单位 m/s

MAX_80MHZ_M = c / (80000000 * 2) = 1.873 m
MAX_100MHZ_M = c / (100000000 * 2) = 1.498 m

MAX_DIST_80MHZ_M = (phaseUnwrappingLevel + 1) * 1.873 + (phaseUnwrapErrorThreshold / 2)
MAX_DIST_100MHZ_M = (phaseUnwrappingLevel + 1) * 1.498 + (phaseUnwrapErrorThreshold / 2)
```

## ToF 帧率

传感器/发射器可运行高达 160 FPS。有效深度输出取决于解码/滤波设置（例如突发模式和相位处理）。

## 使用示例

#### Python

```python
pipeline = dai.Pipeline()

socket = dai.CameraBoardSocket.AUTO
preset = dai.ImageFiltersPresetMode.TOF_MID_RANGE
tof = pipeline.create(dai.node.ToF).build(socket, preset)

# 基础输出和滤波输出
raw_depth_q = tof.rawDepth.createOutputQueue()
depth_q = tof.depth.createOutputQueue()

# 运行时配置队列（如果所选 API 绑定支持）
base_cfg_q = tof.tofBaseInputConfig.createInputQueue()
filters_cfg_q = tof.imageFiltersInputConfig.createInputQueue()
```

#### C++

```cpp
dai::Pipeline pipeline;

auto tof = pipeline.create<dai::node::ToF>()->build(
    dai::CameraBoardSocket::AUTO,
    dai::ImageFiltersPresetMode::TOF_MID_RANGE
);

auto rawDepthQ = tof->rawDepth.createOutputQueue();
auto depthQ = tof->depth.createOutputQueue();
```

## 示例

 * [RVC2 ToF 示例](https://docs.luxonis.com/software-v3/depthai/examples/rvc2/tof/tof.md)
 * [ToF 点云 + 运行时调优
   (oak-examples)](https://github.com/luxonis/oak-examples/tree/bbc446232ad9378e03e9cb89b04dbb9f99f2448f/depth-measurement/3d-measurement/tof-pointcloud)

## 参考

### dai::node::ToF

Kind: class

#### Subnode < ToFBase > tofBase

Kind: variable

#### Output & rawDepth

Kind: variable

Raw depth output from ToF sensor. On RVC2 this is connected to the unfiltered base depth output. On RVC4 this is an unconnected
placeholder output.

#### Output & depth

Kind: variable

Filtered depth output

#### Output & amplitude

Kind: variable

Amplitude output

#### Output & intensity

Kind: variable

Intensity output

#### Output & confidence

Kind: variable

Confidence output

#### Output & phase

Kind: variable

Phase output

#### Output & raw

Kind: variable

Raw data coming from the sensor

#### Input & inputConfig

Kind: variable

Runtime ToFConfig input for the ToF base node (decoder on RVC2, IPP on RVC4). RVC4: directly reconfigures the IPP that produces
ImageFilters . The host-filter stage that actually produces ImageFiltersConfig to

#### Input & tofBaseInputConfig

Kind: variable

Input config for ToF base node

#### Input * imageFiltersInputConfig

Kind: variable

Input config for image filters

#### ToFBase & tofBaseNode

Kind: variable

ToF base node

#### ImageFilters * imageFiltersNode

Kind: variable

Image filters node

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

Kind: function

#### ~ToF()

Kind: function

#### void buildInternal()

Kind: function

Function called from within the

#### std::shared_ptr< ToF > build(dai::CameraBoardSocket boardSocket, dai::ImageFiltersPresetMode presetMode, std::optional< float
> fps)

Kind: function

Build the ToF node with a specific board socket, legacy preset mode, and optional FPS. parameters: boardSocket: Board socket to
use, or AUTO to select an available ToF socket automatically; presetMode: Legacy ToF image filter preset mode; fps: Requested ToF
camera FPS

#### std::shared_ptr< ToF > build(dai::CameraBoardSocket boardSocket, dai::ToFConfig::Profile presetMode, std::optional< float >
fps)

Kind: function

Build the ToF node with a specific board socket, profile, and optional FPS. parameters: boardSocket: Board socket to use, or AUTO
to select an available ToF socket automatically; presetMode: ToF processing profile to apply; fps: Requested ToF camera FPS

#### void postBuildStage()

Kind: function

### 需要帮助？

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