# 计算机视觉

我们的平台支持在设备上执行计算机视觉（CV）功能。虽然无法运行 [OpenCV](https://github.com/opencv/opencv)，但您可以使用其许多支持的功能。借助 DepthAI，您可以：

 * 裁剪、旋转、变形/去畸变、镜像、翻转、透视变换等，使用 [ImageManip](https://docs.luxonis.com/software-v3/depthai/depthai-components/nodes/image_manip.md)
 * 边缘检测（Sobel 滤波器），使用 [EdgeDetector](https://docs.luxonis.com/software-v3/depthai/depthai-components/nodes/edge_detector.md)
 * 特征检测与跟踪，使用 [FeatureTracker](https://docs.luxonis.com/software-v3/depthai/depthai-components/nodes/feature_tracker.md)
 * 对象跟踪（卡尔曼滤波、匈牙利算法），使用 [ObjectTracker](https://docs.luxonis.com/software-v3/depthai/depthai-components/nodes/object_tracker.md)
   开箱即用支持 Yolo 和 MobileNet 目标检测器。
 * 立体深度感知（Census 变换、代价匹配与聚合），使用
   [StereoDepth](https://docs.luxonis.com/software-v3/depthai/depthai-components/nodes/stereo_depth.md)

如果您想使用其他 CV 功能，请参阅以下指南，了解如何在设备的硬件加速模块上高效实现和运行 CV 功能。

## 在设备上运行您自己的 CV 功能

演示：

 * [帧拼接](https://github.com/luxonis/oak-examples/tree/master/gen2-custom-models/generate_model#concatenate-frames) - 使用
   [PyTorch](https://pytorch.org/)
 * [拉普拉斯边缘检测](https://github.com/luxonis/oak-examples/tree/master/gen2-custom-models/generate_model#blur-frames) - 使用 Kornia
 * [帧模糊](https://github.com/luxonis/oak-examples/tree/master/gen2-custom-models/generate_model#corner-detection) - 使用 Kornia
 * [Rahul Ravikumar 的教程：在 OAK 上运行自定义模型](https://rahulrav.com/blog/depthai_camera.html)
 * [Kunal Tyagi 的 PyTorch Harris 角点检测](https://github.com/kunaltyagi/pytorch_harris/)

## 使用 PyTorch 创建自定义模型

为了本指南的说明，我们将创建一个简单的模型，将三帧拼接为一帧。这是一个简单的例子，但您可以使用相同的过程创建更复杂的模型。

### TL;DR

如果您只对实现感兴趣

[TL;DR](https://github.com/luxonis/oak-examples/blob/master/gen2-custom-models/generate_model/pytorch_concat.py)

### 创建 PyTorch NN 模块

我们首先需要创建一个继承 PyTorch 的 [nn.Module](https://pytorch.org/docs/stable/generated/torch.nn.Module.html) 的 Python 类。然后，我们可以将 NN
逻辑放在所创建类的 forward 函数中。在帧拼接的例子中，我们可以使用 [torch.cat](https://pytorch.org/docs/master/generated/torch.cat.html#torch-cat) 函数将多帧拼接起来：

```python
class CatImgs(nn.Module):
    def forward(self, img1, img2, img3):
        return torch.cat((img1, img2, img3), 3)
```

对于更复杂的模块，请参考 Kunal Tyagi 的 [PyTorch Harris 角点检测](https://github.com/kunaltyagi/pytorch_harris/) 演示。

请记住，VPU 仅支持 [FP16](https://en.wikipedia.org/wiki/Half-precision_floating-point_format#Half_precision_examples)，这意味着最大值为
65504。当相乘多个值时，如果不正确归一化/除值，可能会很快溢出。

### 将 NN 模块导出为 onnx

由于 PyTorch 不被 OpenVINO 直接支持，我们首先需要将模型导出为 [onnx 格式](https://onnx.ai/)，然后再转换为 OpenVINO 格式。PyTorch 具有 [对 onnx
的内置支持](https://pytorch.org/docs/stable/onnx.html)，因此导出为 onnx 非常简单：

```python
# 对于 300x300 的帧
X = torch.ones((1, 3, 300, 300), dtype=torch.float32)
torch.onnx.export(
    CatImgs(),
    (X, X, X), # 用于形状的虚拟输入
    "path/to/model.onnx",
    opset_version=12,
    do_constant_folding=True,
)
```

这将把拼接模型导出为 onnx 格式。我们可以使用 [Netron 应用](https://netron.app/) 可视化创建的模型：

### 简化 onnx 模型

当将模型导出为 onnx 时，PyTorch 的效率并不高。它会创建大量不必要的操作/层，从而增加网络的尺寸（可能导致较低的 FPS）。因此，我们建议使用
[onnx-simplifier](https://github.com/daquexian/onnx-simplifier)，这是一个简单的 Python 包，可以移除不必要的操作/层。

```python
import onnx
from onnxsim import simplify

onnx_model = onnx.load("path/to/model.onnx")
model_simplified, check = simplify(onnx_model)
onnx.save(model_simplified, "path/to/simplified/model.onnx")
```

以下是一个示例，展示了使用 onnx-simplifier 进行简化的显著效果。左侧是直接从 PyTorch 导出的模糊模型（来自 Kornia），右侧是相同功能的简化网络：

### 转换为 OpenVINO/blob

现在我们有了一个（简化后的）onnx 模型，可以将其转换为 OpenVINO 格式，然后转换为 .blob 格式。有关转换模型的更多信息，请参见
[转换指南](https://docs.luxonis.com/software-v3/ai-inference/conversion.md)。

通常，首先使用 [OpenVINO 的模型优化器](https://docs.openvinotoolkit.org/latest/openvino_docs_MO_DG_Deep_Learning_Model_Optimizer_DevGuide.html)
将 onnx 转换为 IR 格式（.bin/.xml），然后使用 [Compile
工具](https://docs.openvinotoolkit.org/latest/openvino_inference_engine_tools_compile_tool_README.html) 编译为 .blob。但我们也可以使用
blobconverter 将 onnx 直接转换为 .blob。

Blobconverter 可以一步完成这两个步骤——无需安装 OpenVINO。您可以像这样编译您的 onnx 模型：

```python
import blobconverter

blobconverter.from_onnx(
    model="/path/to/model.onnx",
    output_dir="/path/to/output/model.blob",
    data_type="FP16",
    shaves=6,
    use_cache=False,
    optimizer_params=[]
)
```

> **在线 blobconverter**
> 您也可以使用
> [在线 blobconverter](https://blobconverter.luxonis.com/)
> 来转换您的模型。

### 在管道中使用 .blob

现在，您可以使用 [NeuralNetwork](https://docs.luxonis.com/software-v3/depthai/depthai-components/nodes/neural_network.md) 节点来加载您的 .blob
模型。请查看 [oak-examples/custom-models](https://github.com/luxonis/oak-examples/tree/master/gen2-custom-models) 以运行使用这些自定义模型的演示应用程序。

## Kornia

[Kornia](https://kornia.readthedocs.io/en/latest/)，“最先进且经过精心挑选的AI计算机视觉算法”，拥有一套在PyTorch中实现的常见计算机视觉算法。这使得用户能够执行类似以下操作：

```python
import kornia

class Model(nn.Module):
    def forward(self, image):
        return kornia.filters.gaussian_blur2d(image, (9, 9), (2.5, 2.5))
```

并使用与 [使用PyTorch创建自定义模型](#Create%20a%20custom%20model%20with%20PyTorch)
完全相同的流程来实现[帧模糊](https://github.com/luxonis/oak-examples/blob/master/gen2-custom-models/generate_model/kornia_blur.py)效果，如下图所示：

> **算法支持**
> 在我们的测试中，我们发现
> **有几种算法**
> 不受OpenVINO框架或VPU支持。我们已为
> [Sobel滤波器](https://kornia.readthedocs.io/en/latest/filters.html?highlight=sobel#kornia.filters.Sobel)
> 提交了一个
> [问题](https://github.com/openvinotoolkit/openvino/issues/7557)
> 。
