# 计算机视觉

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

 * 裁剪、旋转、畸变/去畸变、镜像、翻转、透视变换等，使用[ImageManip](https://docs.luxonis.com/software/depthai-components/nodes/image_manip.md)
 * 检测边缘（Sobel滤波器）使用[EdgeDetector](https://docs.luxonis.com/software/depthai-components/nodes/edge_detector.md)
 * 检测和跟踪特征使用[FeatureTracker](https://docs.luxonis.com/software/depthai-components/nodes/feature_tracker.md)
 * 跟踪物体（卡尔曼滤波器、匈牙利算法）使用[ObjectTracker](https://docs.luxonis.com/software/depthai-components/nodes/object_tracker.md)
   开箱即用支持Yolo和MobileNet目标检测器。
 * 感知立体深度（Census变换、代价匹配与聚合）使用[StereoDepth](https://docs.luxonis.com/software/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
 * [在OAK上运行自定义模型的教程](https://rahulrav.com/blog/depthai_camera.html) - Rahul Ravikumar
 * [PyTorch中的Harris角点检测](https://github.com/kunaltyagi/pytorch_harris/) - Kunal Tyagi

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

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

### TL;DR

如果您只对实现感兴趣

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

### 创建PyTorch神经网络模块

我们首先需要创建一个继承PyTorch的[nn.Module](https://pytorch.org/docs/stable/generated/torch.nn.Module.html)的Python类。然后我们可以将神经网络逻辑放入所创建类的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开发的[Harris角点检测PyTorch](https://github.com/kunaltyagi/pytorch_harris/)演示。

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

### 将神经网络模块导出为onnx

由于PyTorch不被OpenVINO直接支持，我们首先需要将模型导出为[onnx格式](https://onnx.ai/)，然后再转换为OpenVINO。PyTorch内置了对onnx的支持，因此导出到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/ai-inference/conversion.md)。

通常的做法是首先使用[OpenVINO的模型优化器](https://docs.openvinotoolkit.org/latest/openvino_docs_MO_DG_Deep_Learning_Model_Optimizer_DevGuide.html)将onnx转换为IR格式（.bin/.xml），然后使用[编译工具](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

您现在可以将您的.blob模型与[NeuralNetwork](https://docs.luxonis.com/software/depthai-components/nodes/neural_network.md)节点一起使用。查看[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)
> 提交了一个
> [Issue](https://github.com/openvinotoolkit/openvino/issues/7557)
> 。
