# OAK 可视化器

可视化器允许您直接在网页浏览器中查看来自 OAK 设备的多个摄像头流和数据输出。它是 OpenCV 的 imshow() 函数的一个更灵活的替代方案，支持同时查看多个流以及交互式控件。目前，它在 Chrome 浏览器中得到完全支持。

请注意，可视化器与 [DepthAI API](https://docs.luxonis.com/software-v3/depthai.md) 配合使用，并与所有 OAK 设备兼容。

> 请注意，可视化器的所有功能仅在 Chrome 中有效。所有浏览器都应支持 RAW 流。编码流及其相关功能仅在 Chrome 中得到支持，因为它们需要完整的
> [WebCodecs API](https://developer.mozilla.org/en-US/docs/Web/API/VideoDecoder)
> ，而目前只有 Chrome 能够以高质量和高性能提供该 API。

## 开始使用

#### Basic Setup

要使用可视化器，您需要在 DepthAI 应用中创建一个 RemoteConnection：

```python
import depthai as dai

# 创建一个 RemoteConnection（可视化器服务器）
visualizer = dai.RemoteConnection()

# 创建流水线
with dai.Pipeline() as pipeline:
    # 创建摄像头节点
    # 不带参数构建将使用默认摄像头
    rgb_cam = pipeline.create(dai.node.Camera).build()

    # 从摄像头请求分辨率为 1280x720 的 NV12 流
    rgb_stream = rgb_cam.requestOutput(size=(1280, 720), type=dai.ImgFrame.Type.NV12)

    # 将摄像头流作为主题添加到可视化器
    visualizer.addTopic("rgb", rgb_stream)

    # 构建并启动流水线
    pipeline.start()

    # 注册流水线图，以便在可视化器中显示
    visualizer.registerPipeline(pipeline)

    # 流水线运行时执行的主循环
    while pipeline.isRunning():
        # 检查可视化器中的按键输入
        if visualizer.waitKey(1) == ord('q'):
            # 如果按下 'q' 键，停止流水线
            pipeline.stop()
```

运行此代码后，打开浏览器访问 http://localhost:8080 即可查看流。

#### Stereo Device Setup

要使用可视化器，您需要在 DepthAI 应用中创建一个 RemoteConnection：

```python
import depthai as dai

# 创建一个 RemoteConnection（可视化器服务器）
visualizer = dai.RemoteConnection()

# 创建流水线
with dai.Pipeline() as pipeline:
    # 创建摄像头节点
    rgb_cam = pipeline.create(dai.node.Camera).build(dai.CameraBoardSocket.CAM_A)
    left_cam = pipeline.create(dai.node.Camera).build(dai.CameraBoardSocket.CAM_B)
    right_cam = pipeline.create(dai.node.Camera).build(dai.CameraBoardSocket.CAM_C)

    # 从摄像头请求 NV12 流
    rgb_stream = rgb_cam.requestOutput(size=(1280, 720), type=dai.ImgFrame.Type.NV12)
    left_stream = left_cam.requestOutput(size=(800, 600), type=dai.ImgFrame.Type.NV12)
    right_stream = right_cam.requestOutput(size=(800, 600), type=dai.ImgFrame.Type.NV12)

    # 将摄像头流作为主题添加到可视化器
    visualizer.addTopic("rgb", rgb_stream)
    visualizer.addTopic("left", left_stream)
    visualizer.addTopic("right", right_stream)

    # 构建并启动流水线
    pipeline.start()

    # 注册流水线图，以便在可视化器中显示
    visualizer.registerPipeline(pipeline)

    # 流水线运行时执行的主循环
    while pipeline.isRunning():
        # 检查可视化器中的按键输入
        if visualizer.waitKey(1) == ord('q'):
            # 如果按下 'q' 键，停止流水线
            pipeline.stop()
```

运行此代码后，打开浏览器访问 http://localhost:8080 即可查看流。

#### Advanced Configuration

您可以通过额外参数自定义可视化器的行为：

```python
# 自定义 RemoteConnection 配置
remote = dai.RemoteConnection(
    address="0.0.0.0",      # 绑定到所有接口
    webSocketPort=8765,     # 自定义 WebSocket 端口
    serveFrontend=True,     # 启用 Web 用户界面
    httpPort=8080           # 自定义 HTTP 端口
)

# 添加流并使用分组进行组织
remote.addTopic("rgb", rgb_stream, group="RGB")
remote.addTopic("left", left_stream, group="Left")
remote.addTopic("right", right_stream, group="Right")

# 添加神经网络结果
# 将检测结果与 rgb 流分组，可确保检测结果不会叠加到 left/right 流上
remote.addTopic("detections", nn.out, group="RGB")
```

## 功能特性

 * 多路流同时查看 - 在浏览器中同时查看所有摄像头流
 * 自定义消息队列 - 创建自定义消息队列，将数据发送到可视化器
 * 远程查看 - 通过网络中的任何设备访问可视化器

## API 参考

### RemoteConnection 类

RemoteConnection 类是可视化器的主要接口：

```python
remote = dai.RemoteConnection(
    address="0.0.0.0",      # 绑定的IP地址
    webSocketPort=8765,     # WebSocket端口
    serveFrontend=True,     # 是否提供前端UI服务
    httpPort=8080           # Web界面的HTTP端口
)
```

### 添加主题

您可以通过两种方式向可视化器添加主题（流）。第一种方式，添加一个用于流式传输节点输出的主题：

```python
remote.addTopic(
    topicName="rgb",              # UI中显示的名称
    output=rgb_stream,            # 要流式传输的节点输出
    group="Cameras",              # 可选的分组名称
    useVisualizationIfAvailable=True  # 如果存在，将调用输出对象的getVisualizationMessage方法以获取可视化信息。
)
```

或者创建一个输出队列，其内容将被流式传输：

```python
rgb_queue = visualizer.addTopic(
    topicName="rgb",              # UI中显示的名称 
    group="Cameras",              # 可选的分组名称
    maxSize=2,                    # 创建的队列的最大大小
    blocking=False,               # 创建的队列是否为阻塞队列的指示符
    useVisualizationIfAvailable=True  # 如果存在，将调用输出对象的getVisualizationMessage方法以获取可视化信息。
)
# 向队列发送自定义数据
rgb_queue.send(my_data)
```

### 与神经网络集成

```python
# 创建神经网络节点
nn = pipeline.create(dai.node.DetectionNetwork).build(
    input=rgb_cam, # 用作神经网络输入的摄像头节点
    model="luxonis/yolov6-nano:r2-coco-512x288", # 来自Luxonis Hub的模型标识
)
nn.setConfidenceThreshold(0.5)

# 将神经网络结果添加到可视化器
remote.addTopic("detections", nn.out, group="RGB")
```

## 示例应用

### 多摄像头流式传输

```python
# 创建摄像头
rgb_cam = pipeline.create(dai.node.Camera).build(dai.CameraBoardSocket.CAM_A)
left_cam = pipeline.create(dai.node.Camera).build(dai.CameraBoardSocket.CAM_B)
right_cam = pipeline.create(dai.node.Camera).build(dai.CameraBoardSocket.CAM_C)

# 从摄像头请求NV12流
rgb_stream = rgb_cam.requestOutput(size=(1280, 720), type=dai.ImgFrame.Type.NV12)
left_stream = left_cam.requestOutput(size=(800, 600), type=dai.ImgFrame.Type.NV12)
right_stream = right_cam.requestOutput(size=(1280, 720), type=dai.ImgFrame.Type.NV12)

# ...

# 将所有摄像头添加到可视化器
remote.addTopic("rgb", rgb_stream, group="Cameras")
remote.addTopic("left", left_stream, group="Cameras")
remote.addTopic("right", right_stream, group="Cameras")
```

### 目标检测可视化

```python
# 设置检测网络
nn = pipeline.create(dai.node.DetectionNetwork).build(
    input=rgb_cam, # 用作神经网络输入的摄像头节点
    model="luxonis/yolov6-nano:r2-coco-512x288", # 来自Luxonis Hub的模型标识
)
nn.setConfidenceThreshold(0.5)

# 将RGB预览和检测结果添加到可视化器
remote.addTopic("preview", rgb_stream, group="Camera")
remote.addTopic("detections", nn.out, group="Camera")
```
