Ultralytics-中文文档-十三-

Ultralytics 中文文档(十三)

使用 DeepStream SDK 和 TensorRT 在 NVIDIA Jetson 上的 Ultralytics YOLOv8

原文:docs.ultralytics.com/guides/deepstream-nvidia-jetson/

这份详尽的指南提供了在NVIDIA Jetson设备上使用 DeepStream SDK 和 TensorRT 部署 Ultralytics YOLOv8 的详细步骤。在这里,我们使用 TensorRT 来最大化 Jetson 平台上的推理性能。

NVIDIA Jetson 上的 DeepStream

注意

本指南已在基于 NVIDIA Jetson Orin NX 16GB 运行 JetPack 版本JP5.1.3Seeed Studio reComputer J4012和基于 NVIDIA Jetson Nano 4GB 运行 JetPack 版本JP4.6.4Seeed Studio reComputer J1020 v2上进行了测试。它预计可以在包括最新和传统的所有 NVIDIA Jetson 硬件中使用。

什么是 NVIDIA DeepStream?

NVIDIA 的 DeepStream SDK是基于 GStreamer 的完整流分析工具包,用于基于 AI 的多传感器处理、视频、音频和图像理解。它非常适合视觉 AI 开发人员、软件合作伙伴、初创公司和 OEM 构建 IVA(智能视频分析)应用和服务。您现在可以创建包含神经网络和其他复杂处理任务(如跟踪、视频编码/解码和视频渲染)的流处理管道。这些管道实现了对视频、图像和传感器数据的实时分析。DeepStream 的多平台支持为您在本地、边缘和云端开发视觉 AI 应用和服务提供了更快、更简单的方法。

先决条件

在开始遵循本指南之前:

  • 访问我们的文档,快速入门指南:NVIDIA Jetson 与 Ultralytics YOLOv8,为您的 NVIDIA Jetson 设备设置 Ultralytics YOLOv8

  • 根据 JetPack 版本安装DeepStream SDK

提示

在本指南中,我们使用了将 DeepStream SDK 安装到 Jetson 设备的 Debian 软件包方法。您也可以访问Jetson 上的 DeepStream SDK(存档)来获取 DeepStream 的旧版本。

YOLOv8 在 DeepStream 上的配置

我们使用的是marcoslucianops/DeepStream-Yolo GitHub 存储库,该存储库包含 NVIDIA DeepStream SDK 对 YOLO 模型的支持。我们感谢 marcoslucianops 为其贡献所做的努力!

  1. 安装依赖项

    pip  install  cmake
    pip  install  onnxsim 
    
  2. 克隆以下存储库

    git  clone  https://github.com/marcoslucianops/DeepStream-Yolo
    cd  DeepStream-Yolo 
    
  3. YOLOv8 releases下载您选择的 Ultralytics YOLOv8 检测模型(.pt)。这里我们使用yolov8s.pt

    wget  https://github.com/ultralytics/assets/releases/download/v8.2.0/yolov8s.pt 
    

    注意

    您还可以使用自定义训练的 YOLOv8 模型

  4. 将模型转换为 ONNX

    python3  utils/export_yoloV8.py  -w  yolov8s.pt 
    

    将以下参数传递给上述命令

    对于 DeepStream 6.0.1,请使用 opset 12 或更低版本。默认 opset 为 16。

    --opset  12 
    

    更改推理尺寸(默认值:640)

    -s  SIZE
    --size  SIZE
    -s  HEIGHT  WIDTH
    --size  HEIGHT  WIDTH 
    

    例如 1280 的示例:

    -s  1280
    or
    -s  1280  1280 
    

    要简化 ONNX 模型(DeepStream >= 6.0)

    --simplify 
    

    要使用动态批量大小(DeepStream >= 6.1)

    --dynamic 
    

    若要使用静态批量大小(例如批量大小为 4)

    --batch  4 
    
  5. 根据安装的 JetPack 版本设置 CUDA 版本

    对于 JetPack 4.6.4:

    export  CUDA_VER=10.2 
    

    对于 JetPack 5.1.3:

    export  CUDA_VER=11.4 
    
  6. 编译库

    make  -C  nvdsinfer_custom_impl_Yolo  clean  &&  make  -C  nvdsinfer_custom_impl_Yolo 
    
  7. 根据您的模型编辑config_infer_primary_yoloV8.txt文件(适用于具有 80 个类别的 YOLOv8s)

    [property]
    ...
    onnx-file=yolov8s.onnx
    ...
    num-detected-classes=80
    ... 
    
  8. 编辑deepstream_app_config文件

    ...
    [primary-gie]
    ...
    config-file=config_infer_primary_yoloV8.txt 
    
  9. 您还可以在deepstream_app_config文件中更改视频源。这里加载了一个默认视频文件

    ...
    [source0]
    ...
    uri=file:///opt/nvidia/deepstream/deepstream/samples/streams/sample_1080p_h264.mp4 
    

运行推理

deepstream-app  -c  deepstream_app_config.txt 

注意

在开始推理之前生成 TensorRT 引擎文件可能需要很长时间,请耐心等待。

YOLOv8 with deepstream

提示

如果要将模型转换为 FP16 精度,只需在config_infer_primary_yoloV8.txt内设置model-engine-file=model_b1_gpu0_fp16.enginenetwork-mode=2

INT8 校准

如果要进行推理的 INT8 精度,您需要按照以下步骤操作

  1. 设置OPENCV环境变量

    export  OPENCV=1 
    
  2. 编译库

    make  -C  nvdsinfer_custom_impl_Yolo  clean  &&  make  -C  nvdsinfer_custom_impl_Yolo 
    
  3. 对于 COCO 数据集,请下载val2017,解压并移动到DeepStream-Yolo文件夹

  4. 创建一个用于校准图像的新目录

    mkdir  calibration 
    
  5. 运行以下命令从 COCO 数据集中选择 1000 张随机图像以进行校准

    for  jpg  in  $(ls  -1  val2017/*.jpg  |  sort  -R  |  head  -1000);  do  \
      cp  ${jpg}  calibration/;  \
    done 
    

    注意

    NVIDIA 建议至少使用 500 张图像以获得良好的准确性。在此示例中,选择 1000 张图像以获得更高的准确性(更多图像=更高的准确性)。您可以设置为head -1000。例如,对于 2000 张图像,设置为head -2000。此过程可能需要很长时间。

  6. 创建包含所有选定图像的calibration.txt文件

    realpath  calibration/*jpg  >  calibration.txt 
    
  7. 设置环境变量

    export  INT8_CALIB_IMG_PATH=calibration.txt
    export  INT8_CALIB_BATCH_SIZE=1 
    

    注意

    较高的 INT8_CALIB_BATCH_SIZE 值将导致更高的准确性和更快的校准速度。根据您的 GPU 内存设置它。

  8. 更新config_infer_primary_yoloV8.txt文件

    来自

    ...
    model-engine-file=model_b1_gpu0_fp32.engine
    #int8-calib-file=calib.table
    ...
    network-mode=0
    ... 
    

    为了

    ...
    model-engine-file=model_b1_gpu0_int8.engine
    int8-calib-file=calib.table
    ...
    network-mode=1
    ... 
    

运行推理

deepstream-app  -c  deepstream_app_config.txt 

多流设置

要在单个 DeepStream 应用程序下设置多个流,您可以对deepstream_app_config.txt文件进行以下更改

  1. 根据所需的流数量更改行和列以构建网格显示。例如,对于 4 个流,我们可以添加 2 行和 2 列。

    [tiled-display]
    rows=2
    columns=2 
    
  2. 设置 num-sources=4 并添加所有 4 个流的 uri

    [source0]
    enable=1
    type=3
    uri=<path_to_video>
    uri=<path_to_video>
    uri=<path_to_video>
    uri=<path_to_video>
    num-sources=4 
    

运行推理

deepstream-app  -c  deepstream_app_config.txt 

多流设置

基准结果

以下表格总结了在 NVIDIA Jetson Orin NX 16GB 上,YOLOv8s 模型在不同 TensorRT 精度级别(输入尺寸为 640x640)下的性能表现。

模型名称 精度 推理时间 (ms/im) FPS
YOLOv8s FP32 15.63 64
FP16 7.94 126
INT8 5.53 181

致谢

此指南最初由我们的朋友 Seeed Studio 的 Lakshantha 和 Elaine 创建。

常见问题解答

如何在 NVIDIA Jetson 设备上设置 Ultralytics YOLOv8?

要在 NVIDIA Jetson 设备上设置 Ultralytics YOLOv8,首先需要安装与你的 JetPack 版本兼容的 DeepStream SDK。按照我们的快速入门指南逐步配置你的 NVIDIA Jetson,以便部署 YOLOv8。

在 NVIDIA Jetson 上使用 TensorRT 与 YOLOv8 的好处是什么?

使用 TensorRT 优化 YOLOv8 模型,显著降低 NVIDIA Jetson 设备上的延迟,并提高吞吐量。TensorRT 通过层融合、精度校准和内核自动调整提供高性能、低延迟的深度学习推理。这导致更快更高效的执行,特别适用于视频分析和自动化机器等实时应用。

能否在不同的 NVIDIA Jetson 硬件上运行 Ultralytics YOLOv8 与 DeepStream SDK?

是的,部署 Ultralytics YOLOv8 与 DeepStream SDK 和 TensorRT 的指南适用于整个 NVIDIA Jetson 系列。这包括 Jetson Orin NX 16GB(使用 JetPack 5.1.3)和 Jetson Nano 4GB(使用 JetPack 4.6.4)。详细步骤请参阅 YOLOv8 的 DeepStream 配置部分。

如何将 YOLOv8 模型转换为 DeepStream 的 ONNX 格式?

要将 YOLOv8 模型转换为 ONNX 格式以在 DeepStream 中部署,请使用来自 DeepStream-Yolo 仓库的 utils/export_yoloV8.py 脚本。

这是一个示例命令:

python3  utils/export_yoloV8.py  -w  yolov8s.pt  --opset  12  --simplify 

要了解更多有关模型转换的详细信息,请查看我们的模型导出部分。

NVIDIA Jetson Orin NX 上 YOLOv8 的性能基准是多少?

NVIDIA Jetson Orin NX 16GB 上 YOLOv8 模型的性能因 TensorRT 精度级别而异。例如,YOLOv8s 模型达到:

  • FP32 精度: 15.63 ms/im, 64 FPS

  • FP16 精度: 7.94 ms/im, 126 FPS

  • INT8 精度: 5.53 ms/im, 181 FPS

这些基准测试突显了在 NVIDIA Jetson 硬件上使用 TensorRT 优化的 YOLOv8 模型的效率和能力。详细信息请参见我们的基准测试结果部分。

Triton 推理服务器与 Ultralytics YOLOv8。

原文:docs.ultralytics.com/guides/triton-inference-server/

Triton 推理服务器(以前称为 TensorRT 推理服务器)是 NVIDIA 开发的开源软件解决方案。它提供了一个针对 NVIDIA GPU 优化的云推理解决方案。Triton 简化了生产环境中大规模部署 AI 模型的过程。将 Ultralytics YOLOv8 与 Triton 推理服务器集成,可以部署可扩展、高性能的深度学习推理工作负载。本指南提供了设置和测试集成的步骤。

www.youtube.com/embed/NQDtfSi5QF4

观看:开始使用 NVIDIA Triton 推理服务器。

什么是 Triton 推理服务器?

Triton 推理服务器旨在生产部署各种 AI 模型,支持 TensorFlow、PyTorch、ONNX Runtime 等广泛的深度学习和机器学习框架。其主要用例包括:

  • 从单个服务器实例中服务多个模型。

  • 动态模型加载和卸载,无需服务器重启。

  • 集成推理,允许多个模型一起使用以实现结果。

  • 为 A/B 测试和滚动更新进行模型版本控制。

先决条件

在继续之前,请确保具备以下先决条件:

  • 您的机器上安装了 Docker。

  • 安装tritonclient

    pip  install  tritonclient[all] 
    

将 YOLOv8 导出为 ONNX 格式

在将模型部署到 Triton 之前,必须将其导出为 ONNX 格式。ONNX(开放神经网络交换)是一种允许在不同深度学习框架之间转移模型的格式。使用YOLO类的export功能:

from ultralytics import YOLO

# Load a model
model = YOLO("yolov8n.pt")  # load an official model

# Export the model
onnx_file = model.export(format="onnx", dynamic=True) 

设置 Triton 模型仓库

Triton 模型仓库是 Triton 可以访问和加载模型的存储位置。

  1. 创建必要的目录结构:

    from pathlib import Path
    
    # Define paths
    model_name = "yolo"
    triton_repo_path = Path("tmp") / "triton_repo"
    triton_model_path = triton_repo_path / model_name
    
    # Create directories
    (triton_model_path / "1").mkdir(parents=True, exist_ok=True) 
    
  2. 将导出的 ONNX 模型移至 Triton 仓库:

    from pathlib import Path
    
    # Move ONNX model to Triton Model path
    Path(onnx_file).rename(triton_model_path / "1" / "model.onnx")
    
    # Create config file
    (triton_model_path / "config.pbtxt").touch() 
    

运行 Triton 推理服务器

使用 Docker 运行 Triton 推理服务器:

import contextlib
import subprocess
import time

from tritonclient.http import InferenceServerClient

# Define image https://catalog.ngc.nvidia.com/orgs/nvidia/containers/tritonserver
tag = "nvcr.io/nvidia/tritonserver:23.09-py3"  # 6.4 GB

# Pull the image
subprocess.call(f"docker pull {tag}", shell=True)

# Run the Triton server and capture the container ID
container_id = (
    subprocess.check_output(
        f"docker run -d --rm -v {triton_repo_path}:/models -p 8000:8000 {tag} tritonserver --model-repository=/models",
        shell=True,
    )
    .decode("utf-8")
    .strip()
)

# Wait for the Triton server to start
triton_client = InferenceServerClient(url="localhost:8000", verbose=False, ssl=False)

# Wait until model is ready
for _ in range(10):
    with contextlib.suppress(Exception):
        assert triton_client.is_model_ready(model_name)
        break
    time.sleep(1) 

然后使用 Triton 服务器模型进行推理:

from ultralytics import YOLO

# Load the Triton Server model
model = YOLO("http://localhost:8000/yolo", task="detect")

# Run inference on the server
results = model("path/to/image.jpg") 

清理容器:

# Kill and remove the container at the end of the test
subprocess.call(f"docker kill {container_id}", shell=True) 

遵循以上步骤,您可以在 Triton 推理服务器上高效部署和运行 Ultralytics YOLOv8 模型,为深度学习推理任务提供可扩展和高性能的解决方案。如果遇到任何问题或有进一步的疑问,请参阅官方 Triton 文档或联系 Ultralytics 社区获取支持。

常见问题

如何设置 Ultralytics YOLOv8 与 NVIDIA Triton 推理服务器?

使用NVIDIA Triton 推理服务器设置Ultralytics YOLOv8涉及几个关键步骤:

  1. 将 YOLOv8 导出为 ONNX 格式

    from ultralytics import YOLO
    
    # Load a model
    model = YOLO("yolov8n.pt")  # load an official model
    
    # Export the model to ONNX format
    onnx_file = model.export(format="onnx", dynamic=True) 
    
  2. 设置 Triton 模型仓库

    from pathlib import Path
    
    # Define paths
    model_name = "yolo"
    triton_repo_path = Path("tmp") / "triton_repo"
    triton_model_path = triton_repo_path / model_name
    
    # Create directories
    (triton_model_path / "1").mkdir(parents=True, exist_ok=True)
    Path(onnx_file).rename(triton_model_path / "1" / "model.onnx")
    (triton_model_path / "config.pbtxt").touch() 
    
  3. 运行 Triton 服务器

    import contextlib
    import subprocess
    import time
    
    from tritonclient.http import InferenceServerClient
    
    # Define image https://catalog.ngc.nvidia.com/orgs/nvidia/containers/tritonserver
    tag = "nvcr.io/nvidia/tritonserver:23.09-py3"
    
    subprocess.call(f"docker pull {tag}", shell=True)
    
    container_id = (
        subprocess.check_output(
            f"docker run -d --rm -v {triton_repo_path}/models -p 8000:8000 {tag} tritonserver --model-repository=/models",
            shell=True,
        )
        .decode("utf-8")
        .strip()
    )
    
    triton_client = InferenceServerClient(url="localhost:8000", verbose=False, ssl=False)
    
    for _ in range(10):
        with contextlib.suppress(Exception):
            assert triton_client.is_model_ready(model_name)
            break
        time.sleep(1) 
    

此设置可帮助您高效地在 Triton 推断服务器上部署 YOLOv8 模型,用于高性能 AI 模型推断。

使用 Ultralytics YOLOv8 与 NVIDIA Triton 推断服务器有什么好处?

Ultralytics YOLOv8NVIDIA Triton Inference Server集成,具有多个优势:

  • 可扩展的 AI 推断:Triton 允许从单个服务器实例中服务多个模型,支持动态模型的加载和卸载,因此对各种 AI 工作负载具有高度可扩展性。

  • 高性能:针对 NVIDIA GPU 进行优化,Triton 推断服务器确保高速推断操作,非常适合实时目标检测等实时应用。

  • 集成和模型版本控制:Triton 的集成模式允许组合多个模型以提高结果,其模型版本控制支持 A/B 测试和滚动更新。

有关设置和运行 YOLOv8 与 Triton 的详细说明,请参考设置指南。

为什么在使用 Triton 推断服务器之前需要将 YOLOv8 模型导出为 ONNX 格式?

在部署在NVIDIA Triton Inference Server上之前,为您的 Ultralytics YOLOv8 模型使用 ONNX(开放神经网络交换格式)提供了几个关键的好处:

  • 互操作性:ONNX 格式支持不同深度学习框架(如 PyTorch、TensorFlow)之间的转换,确保更广泛的兼容性。

  • 优化:包括 Triton 在内的许多部署环境都为 ONNX 进行了优化,实现更快的推断和更好的性能。

  • 部署简便性:ONNX 在各种操作系统和硬件配置中广泛支持,简化了部署过程。

要导出您的模型,请使用:

from ultralytics import YOLO

model = YOLO("yolov8n.pt")
onnx_file = model.export(format="onnx", dynamic=True) 

您可以按照导出指南中的步骤完成该过程。

我可以在 Triton 推断服务器上使用 Ultralytics YOLOv8 模型进行推断吗?

是的,您可以在NVIDIA Triton Inference Server上运行 Ultralytics YOLOv8 模型进行推断。一旦您的模型设置在 Triton 模型存储库中并且服务器正在运行,您可以加载并运行推断模型如下:

from ultralytics import YOLO

# Load the Triton Server model
model = YOLO("http://localhost:8000/yolo", task="detect")

# Run inference on the server
results = model("path/to/image.jpg") 

有关设置和运行 Triton 服务器与 YOLOv8 的深入指南,请参考运行 Triton 推断服务器部分。

Ultralytics YOLOv8 在部署时与 TensorFlow 和 PyTorch 模型有何区别?

Ultralytics YOLOv8相比于 TensorFlow 和 PyTorch 模型,在部署时提供了几个独特的优势:

  • 实时性能:优化用于实时目标检测任务,YOLOv8 提供了最先进的精度和速度,非常适合需要实时视频分析的应用。

  • 易用性:YOLOv8 与 Triton 推理服务器无缝集成,并支持多种导出格式(ONNX、TensorRT、CoreML),使其在各种部署场景下具备灵活性。

  • 高级功能:YOLOv8 包括动态模型加载、模型版本管理和集成推理等功能,对于可扩展和可靠的 AI 部署至关重要。

有关更多详细信息,请比较模型部署指南中的部署选项。

隔离分割对象

原文:docs.ultralytics.com/guides/isolating-segmentation-objects/

执行分割任务后,有时希望从推断结果中提取出隔离的对象。本指南提供了使用 Ultralytics 预测模式完成此操作的通用方法。

示例独立对象分割

步骤详解

  1. 请查看 Ultralytics 快速入门安装部分,了解所需库的快速设置步骤。


  2. 加载模型并在源上运行 predict() 方法。

    from ultralytics import YOLO
    
    # Load a model
    model = YOLO("yolov8n-seg.pt")
    
    # Run inference
    results = model.predict() 
    

    没有预测参数?

    如果没有指定来源,将使用库中的示例图像:

    'ultralytics/assets/bus.jpg'
    'ultralytics/assets/zidane.jpg' 
    

    这对于使用 predict() 方法进行快速测试非常有帮助。

    如需了解有关分割模型的更多信息,请访问分割任务页面。要了解更多关于 predict() 方法的信息,请参阅文档中的预测模式部分。


  3. 现在迭代结果和轮廓。对于希望将图像保存到文件的工作流程,会提取源图像 base-name 和检测到的 class-label 以供后续使用(可选)。

    from pathlib import Path
    
    import numpy as np
    
    # (2) Iterate detection results (helpful for multiple images)
    for r in res:
        img = np.copy(r.orig_img)
        img_name = Path(r.path).stem  # source image base-name
    
        # Iterate each object contour (multiple detections)
        for ci, c in enumerate(r):
            # (1) Get detection class name
            label = c.names[c.boxes.cls.tolist().pop()] 
    
    1. 要了解更多关于处理检测结果的信息,请参阅预测模式中的框部分。

    2. 要了解更多关于 predict() 结果的信息,请参阅预测模式下的结果处理部分

      For-Loop

    单个图像只会在第一个循环中迭代一次。仅包含单个检测的单个图像将在每个循环中仅迭代一次。


  4. 首先从源图像生成二进制掩码,然后在掩码上绘制填充轮廓。这将使对象从图像的其他部分中被隔离出来。右侧显示了一个来自 bus.jpg 的示例,用于一个检测到的 person 类对象。

    二进制掩码图像

    import cv2
    
    # Create binary mask
    b_mask = np.zeros(img.shape[:2], np.uint8)
    
    # (1) Extract contour result
    contour = c.masks.xy.pop()
    # (2) Changing the type
    contour = contour.astype(np.int32)
    # (3) Reshaping
    contour = contour.reshape(-1, 1, 2)
    
    # Draw contour onto mask
    _ = cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED) 
    
    1. 要了解有关 c.masks.xy 的更多信息,请参阅预测模式中的掩码部分。

    2. 这里将值转换为 np.int32,以便与 OpenCV 的 drawContours() 函数兼容。

    3. OpenCV 的 drawContours() 函数期望轮廓具有 [N, 1, 2] 的形状,请展开下面的部分以了解更多细节。

      展开以了解定义 `contour` 变量时发生的情况。
    • c.masks.xy :: 提供掩码轮廓点的坐标,格式为 (x, y)。更多细节,请参阅预测模式中的掩码部分。

    • .pop() :: 由于 masks.xy 是一个包含单个元素的列表,因此使用 pop() 方法提取此元素。

    • .astype(np.int32) :: 使用 masks.xy 将返回 float32 数据类型,但这与 OpenCV 的 drawContours() 函数不兼容,因此这将数据类型更改为 int32 以确保兼容性。

    • .reshape(-1, 1, 2) :: 将数据重新格式化为所需的 [N, 1, 2] 形状,其中 N 是轮廓点的数量,每个点由单个条目 1 表示,该条目由 2 个值组成。-1 表示此维度上的值数量是灵活的。

      展开以查看 drawContours() 配置的解释。

    • contour 变量封装在方括号 [contour] 内,在测试中有效生成所需的轮廓掩模。

    • 对于 drawContours() 参数,指定的值 -1 指示函数绘制图像中存在的所有轮廓。

    • tuple (255, 255, 255) 表示颜色白色,这是在此二进制掩模中绘制轮廓所需的颜色。

    • 添加 cv2.FILLED 将使得所有由轮廓边界包围的像素颜色相同,本例中,所有被包围的像素将会是白色。

    • 有关更多信息,请参阅 OpenCV drawContours() 文档


  5. 接下来有两种选项可以继续处理此图像,每种选项后面都有一个后续选项。

    对象隔离选项

    # Create 3-channel mask
    mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
    
    # Isolate object with binary mask
    isolated = cv2.bitwise_and(mask3ch, img) 
    
    这是如何工作的?
    • 首先,将二进制掩模从单通道图像转换为三通道图像。这种转换对后续步骤至关重要,其中掩模和原始图像结合。两幅图像必须具有相同的通道数,以兼容混合操作。

    • 使用 OpenCV 函数 bitwise_and() 合并原始图像和三通道二进制掩模。此操作仅保留两幅图像中大于零的像素值。由于掩模像素仅在轮廓区域内大于零,因此从原始图像中保留的像素是与轮廓重叠的像素。

  6. 使用黑色像素进行隔离:子选项

    全尺寸图像

    如果保留全尺寸图像,则无需任何额外步骤。

    示例全尺寸隔离对象图像黑色背景

    示例全尺寸输出

    裁剪的对象图像

    需要进一步裁剪图像以仅包括对象区域。

    示例裁剪隔离对象图像黑色背景

    # (1) Bounding box coordinates
    x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
    # Crop image to object region
    iso_crop = isolated[y1:y2, x1:x2] 
    
    1. 有关边界框结果的更多信息,请参见预测模式中的框部分。
    此代码的作用是什么?
    • c.boxes.xyxy.cpu().numpy() 调用以 xyxy 格式作为 NumPy 数组检索边界框,其中 xminyminxmaxymax 表示边界框矩形的坐标。有关更多详细信息,请参见预测模式中的框部分。

    • squeeze()操作从 NumPy 数组中移除任何不必要的维度,确保其具有预期的形状。

    • 使用.astype(np.int32)转换坐标值会将框坐标数据类型从float32更改为int32,使其适用于使用索引切片进行图像裁剪。

    • 最后,使用索引切片从图像中裁剪边界框区域。边界由检测边界框的[ymin:ymax, xmin:xmax]坐标定义。

    # Isolate object with transparent background (when saved as PNG)
    isolated = np.dstack([img, b_mask]) 
    
    这是如何工作的?
    • 使用 NumPy dstack()函数(沿深度轴堆叠数组)与生成的二进制掩码一起,将创建一个具有四个通道的图像。在保存为PNG文件时,这允许对象轮廓外的所有像素都是透明的。

    使用透明像素隔离:子选项

    全尺寸图像

    如果保留完整大小的图像,则不需要任何额外步骤。

    示例全尺寸孤立对象图像无背景

    示例全尺寸输出 + 透明背景

    裁剪对象图像

    需要额外步骤来裁剪图像,仅包括对象区域。

    示例裁剪孤立对象图像无背景

    # (1) Bounding box coordinates
    x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
    # Crop image to object region
    iso_crop = isolated[y1:y2, x1:x2] 
    
    1. 若要了解边界框结果的更多信息,请参见预测模式下的框部分
    这段代码做什么?
    • 当使用c.boxes.xyxy.cpu().numpy()时,边界框将作为 NumPy 数组返回,使用xyxy框坐标格式,这对应于边界框(矩形)的xmin, ymin, xmax, ymax点,请参见预测模式的框部分获取更多信息。

    • 添加squeeze()确保从 NumPy 数组中移除任何多余的维度。

    • 使用.astype(np.int32)转换坐标值会将框坐标数据类型从float32更改为int32,在使用索引切片裁剪图像时会兼容。

    • 最后,使用索引切片裁剪边界框的图像区域,其中边界由检测边界框的[ymin:ymax, xmin:xmax]坐标设置。

    如果我想要包括背景在内的裁剪对象,该怎么办?

    这是 Ultralytics 库的内置功能。有关详细信息,请参阅预测模式推理参数中的save_crop参数。


  7. 接下来的操作完全取决于您作为开发人员的选择。一个可能的下一步基本示例(将图像保存为文件以备将来使用)已显示。

    • 注意: 如果对您的具体用例不需要,则可以选择跳过此步骤。
      最终示例步骤
    # Save isolated object to file
    _ = cv2.imwrite(f"{img_name}_{label}-{ci}.png", iso_crop) 
    
    • 在这个示例中,img_name 是源图像文件的基本名称,label 是检测到的类名,ci 是对象检测的索引(如果有多个具有相同类名的实例)。

完整示例代码

在这里,将前一节的所有步骤合并为一个代码块。对于重复使用,最好定义一个函数来执行for循环中的某些或所有命令,但这是留给读者的练习。

from pathlib import Path

import cv2
import numpy as np

from ultralytics import YOLO

m = YOLO("yolov8n-seg.pt")  # (4)!
res = m.predict()  # (3)!

# Iterate detection results (5)
for r in res:
    img = np.copy(r.orig_img)
    img_name = Path(r.path).stem

    # Iterate each object contour (6)
    for ci, c in enumerate(r):
        label = c.names[c.boxes.cls.tolist().pop()]

        b_mask = np.zeros(img.shape[:2], np.uint8)

        # Create contour mask (1)
        contour = c.masks.xy.pop().astype(np.int32).reshape(-1, 1, 2)
        _ = cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)

        # Choose one:

        # OPTION-1: Isolate object with black background
        mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
        isolated = cv2.bitwise_and(mask3ch, img)

        # OPTION-2: Isolate object with transparent background (when saved as PNG)
        isolated = np.dstack([img, b_mask])

        # OPTIONAL: detection crop (from either OPT1 or OPT2)
        x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
        iso_crop = isolated[y1:y2, x1:x2]

        # TODO your actions go here (2) 
  1. 在此处将填充 contour 的行合并为单行,而不是像上面那样拆分为多行。

  2. 这里的内容由您决定!

  3. 有关附加信息,请参阅 Predict Mode。

  4. 参见 Segment Task 获取更多信息。

  5. 详细了解与结果一起工作

  6. 详细了解分割掩模结果

常见问题解答

如何使用 Ultralytics YOLOv8 对象分割任务中孤立对象?

要使用 Ultralytics YOLOv8 对象分割任务中的孤立对象,请按照以下步骤进行:

  1. 加载模型并运行推理:

    from ultralytics import YOLO
    
    model = YOLO("yolov8n-seg.pt")
    results = model.predict(source="path/to/your/image.jpg") 
    
  2. 生成二进制掩模并绘制轮廓:

    import cv2
    import numpy as np
    
    img = np.copy(results[0].orig_img)
    b_mask = np.zeros(img.shape[:2], np.uint8)
    contour = results[0].masks.xy[0].astype(np.int32).reshape(-1, 1, 2)
    cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED) 
    
  3. 使用二进制掩模孤立对象:

    mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
    isolated = cv2.bitwise_and(mask3ch, img) 
    

参考 Predict Mode 和 Segment Task 的指南获取更多信息。

分割任务中提供的保存孤立对象的选项有哪些?

Ultralytics YOLOv8 提供了两个主要选项来保存孤立对象:

  1. 具有黑色背景:

    mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
    isolated = cv2.bitwise_and(mask3ch, img) 
    
  2. 具有透明背景:

    isolated = np.dstack([img, b_mask]) 
    

欲了解详细信息,请访问 Predict Mode 部分。

如何使用 Ultralytics YOLOv8 对象分割任务中的边界框裁剪孤立对象?

要裁剪孤立对象至其边界框:

  1. 检索边界框坐标:

    x1, y1, x2, y2 = results[0].boxes.xyxy[0].cpu().numpy().astype(np.int32) 
    
  2. 裁剪孤立图像:

    iso_crop = isolated[y1:y2, x1:x2] 
    

详细了解 Predict Mode 文档中的边界框结果。

为什么应该在对象分割任务中使用 Ultralytics YOLOv8 进行对象孤立?

Ultralytics YOLOv8 提供:

  • 高速 实时对象检测和分割。

  • 准确的边界框和掩模生成,用于精确的对象孤立。

  • 全面的文档 和易于使用的 API,用于高效开发。

探索在 Segment Task 文档中使用 YOLO 的好处。

我可以使用 Ultralytics YOLOv8 保存包括背景在内的孤立对象吗?

是的,这是 Ultralytics YOLOv8 中的内置功能。在 predict() 方法中使用 save_crop 参数。例如:

results = model.predict(source="path/to/your/image.jpg", save_crop=True) 

阅读 Predict Mode 推理参数部分中关于 save_crop 参数的更多信息。

Coral Edge TPU 在树莓派上与 Ultralytics YOLOv8 🚀

原文:docs.ultralytics.com/guides/coral-edge-tpu-on-raspberry-pi/

带有 USB Edge TPU 加速器的树莓派单板计算机

什么是 Coral Edge TPU?

Coral Edge TPU 是一款紧凑的设备,为系统添加了 Edge TPU 协处理器。它使得 TensorFlow Lite 模型能够进行低功耗、高性能的 ML 推断。更多信息请查看Coral Edge TPU 主页

使用 Coral Edge TPU 提升树莓派模型性能

许多人希望在嵌入式设备或像树莓派这样的移动设备上运行他们的模型,因为它们非常节能且可以应用于许多不同的场景。然而,即使使用像 ONNX 或 OpenVINO 这样的格式,这些设备上的推断性能通常也很差。Coral Edge TPU 是解决这个问题的一个很好的方案,因为它可以与树莓派一起使用,并显著加速推断性能。

使用 TensorFlow Lite 在树莓派上安装 Edge TPU(新)⭐

Coral 关于如何在树莓派上使用 Edge TPU 的现有指南已经过时,当前的 Coral Edge TPU 运行时版本与当前 TensorFlow Lite 运行时版本不再兼容。此外,谷歌似乎已完全放弃了 Coral 项目,在 2021 年至 2024 年期间没有任何更新。本指南将向您展示如何在树莓派单板计算机(SBC)上使用最新版本的 TensorFlow Lite 运行时和更新的 Coral Edge TPU 运行时让 Edge TPU 正常工作。

先决条件

安装步骤

本指南假设您已经安装了工作正常的树莓派操作系统,并且已经安装了ultralytics和所有依赖项。要安装ultralytics,请访问快速入门指南进行设置。

安装 Edge TPU 运行时

首先,我们需要安装 Edge TPU 运行时。有许多不同的版本可用,因此您需要为您的操作系统选择正确的版本。

Raspberry Pi OS 高频模式 下载版本
Bullseye 32bit libedgetpu1-std_ ... .bullseye_armhf.deb
Bullseye 64bit libedgetpu1-std_ ... .bullseye_arm64.deb
Bullseye 32bit libedgetpu1-max_ ... .bullseye_armhf.deb
Bullseye 64bit libedgetpu1-max_ ... .bullseye_arm64.deb
Bookworm 32 位 libedgetpu1-std_ ... .bookworm_armhf.deb
Bookworm 64 位 libedgetpu1-std_ ... .bookworm_arm64.deb
Bookworm 32 位 libedgetpu1-max_ ... .bookworm_armhf.deb
Bookworm 64 位 libedgetpu1-max_ ... .bookworm_arm64.deb

从这里下载最新版本

下载文件后,您可以使用以下命令进行安装:

sudo  dpkg  -i  path/to/package.deb 

安装完运行时后,您需要将 Coral Edge TPU 插入到树莓派的 USB 3.0 端口中。这是因为根据官方指南,安装后需要让新的udev规则生效。

重要提示

如果您已经安装了 Coral Edge TPU 运行时,请使用以下命令卸载它。

# If you installed the standard version
sudo  apt  remove  libedgetpu1-std

# If you installed the high frequency version
sudo  apt  remove  libedgetpu1-max 
```</details>

## 将您的模型导出为 Edge TPU 兼容模型

要使用 Edge TPU,您需要将模型转换为兼容格式。建议您在 Google Colab、x86_64 Linux 机器上运行导出操作,使用官方 Ultralytics Docker 容器或者使用 Ultralytics HUB,因为 Edge TPU 编译器在 ARM 上不可用。查看导出模式以获取可用参数。

导出

```py
from ultralytics import YOLO

# Load a model
model = YOLO("path/to/model.pt")  # Load an official model or custom model

# Export the model
model.export(format="edgetpu") 
yolo  export  model=path/to/model.pt  format=edgetpu  # Export an official model or custom model 

导出的模型将保存在<model_name>_saved_model/文件夹中,命名为<model_name>_full_integer_quant_edgetpu.tflite

运行模型

导出模型后,您可以使用以下代码进行推理:

运行中

from ultralytics import YOLO

# Load a model
model = YOLO("path/to/edgetpu_model.tflite")  # Load an official model or custom model

# Run Prediction
model.predict("path/to/source.png") 
yolo  predict  model=path/to/edgetpu_model.tflite  source=path/to/source.png  # Load an official model or custom model 

在预测页面上查找关于完整预测模式详细信息的综合信息。

重要提示

您应该使用tflite-runtime而不是tensorflow来运行模型。如果安装了tensorflow,请使用以下命令卸载 tensorflow:

pip  uninstall  tensorflow  tensorflow-aarch64 

然后安装/更新tflite-runtime

pip install -U tflite-runtime 

如果您需要tensorflow 2.15.0 的tflite-runtime wheel,请从这里下载,并使用pip或您选择的软件包管理器进行安装。

FAQ

Coral Edge TPU 是什么,如何通过 Ultralytics YOLOv8 提升树莓派的性能?

Coral Edge TPU 是一个紧凑设备,旨在为您的系统添加 Edge TPU 协处理器。该协处理器能够进行低功耗、高性能的机器学习推断,特别优化了 TensorFlow Lite 模型。在使用树莓派时,Edge TPU 可以加速 ML 模型推断,显著提升性能,特别是对于 Ultralytics YOLOv8 模型。您可以在他们的主页上详细了解 Coral Edge TPU。

如何在树莓派上安装 Coral Edge TPU 运行时?

要在您的树莓派上安装 Coral Edge TPU 运行时,请从此链接下载适合您的树莓派 OS 版本的.deb包。下载后,请使用以下命令进行安装:

sudo  dpkg  -i  path/to/package.deb 

确保按照安装步骤中概述的步骤卸载任何先前的 Coral Edge TPU 运行时版本。

我可以将我的 Ultralytics YOLOv8 模型导出为与 Coral Edge TPU 兼容的格式吗?

是的,您可以将您的 Ultralytics YOLOv8 模型导出为与 Coral Edge TPU 兼容的格式。建议在 Google Colab、x86_64 Linux 机器上或使用 Ultralytics Docker 容器进行导出。您还可以使用 Ultralytics HUB 进行导出。以下是如何使用 Python 和 CLI 导出模型的方法:

导出中

from ultralytics import YOLO

# Load a model
model = YOLO("path/to/model.pt")  # Load an official model or custom model

# Export the model
model.export(format="edgetpu") 
yolo  export  model=path/to/model.pt  format=edgetpu  # Export an official model or custom model 

关于导出模式的详细信息,请参阅导出模式文档。

如果 TensorFlow 已经安装在我的树莓派上,但我想使用 tflite-runtime,我该怎么办?

如果您的树莓派上安装了 TensorFlow,并且需要切换到tflite-runtime,您首先需要卸载 TensorFlow,命令如下:

pip  uninstall  tensorflow  tensorflow-aarch64 

然后,使用以下命令安装或更新tflite-runtime

pip  install  -U  tflite-runtime 

对于特定的 wheel,例如 TensorFlow 2.15.0 tflite-runtime,您可以从此链接下载并使用pip安装。详细的操作指南可以在运行模型的部分找到。

如何在树莓派上使用 Coral Edge TPU 运行推断已导出的 YOLOv8 模型?

将您的 YOLOv8 模型导出到 Edge TPU 兼容格式后,您可以使用以下代码片段进行推断:

运行中

from ultralytics import YOLO

# Load a model
model = YOLO("path/to/edgetpu_model.tflite")  # Load an official model or custom model

# Run Prediction
model.predict("path/to/source.png") 
yolo  predict  model=path/to/edgetpu_model.tflite  source=path/to/source.png  # Load an official model or custom model 

关于完整预测模式功能的详细信息可在预测页面上找到。

在终端查看推断结果

原文:docs.ultralytics.com/guides/view-results-in-terminal/

终端中图像的 Sixel 示例

图像来自libsixel网站。

动机

当连接到远程计算机时,通常不可能或需要将数据移动到带有 GUI 的本地设备才能可视化图像结果。VSCode 集成终端允许直接渲染图像。这是如何与ultralytics结合使用预测结果的简短演示。

警告

仅兼容 Linux 和 MacOS。请查看VSCode 存储库,检查问题状态,或查看文档以获取有关在终端中使用sixel查看图像的 Windows 支持更新。

使用集成终端查看图像的 VSCode 兼容协议是sixeliTerm。本指南将演示如何使用sixel协议。

过程

  1. 首先,您必须在 VSCode 中启用设置terminal.integrated.enableImagesterminal.integrated.gpuAcceleration

    "terminal.integrated.gpuAcceleration":  "auto"  # "auto" is default, can also use "on"
    "terminal.integrated.enableImages":  false 
    

    VSCode 启用终端图像设置

  2. 在您的虚拟环境中安装python-sixel库。这是已不再维护的PySixel库的分支

    pip  install  sixel 
    
  3. 加载模型并执行推断,然后绘制结果并存储在变量中。有关推断参数和处理结果的更多信息,请参阅预测模式页面。

    from ultralytics import YOLO
    
    # Load a model
    model = YOLO("yolov8n.pt")
    
    # Run inference on an image
    results = model.predict(source="ultralytics/assets/bus.jpg")
    
    # Plot inference results
    plot = results[0].plot()  # (1)! 
    
    1. 查看绘图方法参数以了解可能的参数用法。
  4. 现在,使用 OpenCV 将numpy.ndarray转换为bytes数据。然后使用io.BytesIO创建“类文件”对象。

    import io
    
    import cv2
    
    # Results image as bytes
    im_bytes = cv2.imencode(
        ".png",  # (1)!
        plot,
    )[1].tobytes()  # (2)!
    
    # Image bytes as a file-like object
    mem_file = io.BytesIO(im_bytes) 
    
    1. 也可以使用其他图像扩展名。

    2. 仅需要返回的索引1处的对象。

  5. 创建一个SixelWriter实例,然后使用.draw()方法在终端中绘制图像。

    from sixel import SixelWriter
    
    # Create sixel writer object
    w = SixelWriter()
    
    # Draw the sixel image in the terminal
    w.draw(mem_file) 
    

示例推断结果

在终端中查看图像

危险

尚未测试此示例是否适用于视频或动画 GIF 帧。请自行决定风险。

完整代码示例

import io

import cv2
from sixel import SixelWriter

from ultralytics import YOLO

# Load a model
model = YOLO("yolov8n.pt")

# Run inference on an image
results = model.predict(source="ultralytics/assets/bus.jpg")

# Plot inference results
plot = results[0].plot()  # (3)!

# Results image as bytes
im_bytes = cv2.imencode(
    ".png",  # (1)!
    plot,
)[1].tobytes()  # (2)!

mem_file = io.BytesIO(im_bytes)
w = SixelWriter()
w.draw(mem_file) 
  1. 也可以使用其他图像扩展名。

  2. 仅需要返回的索引1处的对象。

  3. 查看绘图方法参数以了解可能的参数用法。


小贴士

您可能需要使用clear命令来“清除”终端中的图像视图。

常见问题解答

如何在 macOS 或 Linux 的 VSCode 终端上查看 YOLO 推断结果?

若要在 macOS 或 Linux 的 VSCode 终端上查看 YOLO 推断结果,请按以下步骤操作:

  1. 启用必要的 VSCode 设置:

    "terminal.integrated.enableImages":  true
    "terminal.integrated.gpuAcceleration":  "auto" 
    
  2. 安装 sixel 库:

    pip  install  sixel 
    
  3. 加载您的 YOLO 模型并运行推断:

    from ultralytics import YOLO
    
    model = YOLO("yolov8n.pt")
    results = model.predict(source="path_to_image")
    plot = results[0].plot() 
    
  4. 将推理结果图像转换为字节并在终端中显示:

    import io
    
    import cv2
    from sixel import SixelWriter
    
    im_bytes = cv2.imencode(".png", plot)[1].tobytes()
    mem_file = io.BytesIO(im_bytes)
    SixelWriter().draw(mem_file) 
    

获取更多细节,请访问预测模式页面。

为什么 sixel 协议只在 Linux 和 macOS 上有效?

目前,sixel 协议仅在 Linux 和 macOS 平台上受支持,因为这些平台具有与 sixel 图形兼容的本地终端功能。Windows 上使用 sixel 进行终端图形的支持仍在开发中。有关 Windows 兼容性的更新,请查看 VSCode 问题状态文档

如果在 VSCode 终端中显示图像遇到问题怎么办?

如果在 VSCode 终端中使用 sixel 显示图像遇到问题:

  1. 确保在 VSCode 中启用必要的设置:

    "terminal.integrated.enableImages":  true
    "terminal.integrated.gpuAcceleration":  "auto" 
    
  2. 验证 sixel 库的安装:

    pip  install  sixel 
    
  3. 检查你的图像数据转换和绘图代码是否存在错误。例如:

    import io
    
    import cv2
    from sixel import SixelWriter
    
    im_bytes = cv2.imencode(".png", plot)[1].tobytes()
    mem_file = io.BytesIO(im_bytes)
    SixelWriter().draw(mem_file) 
    

如果问题持续存在,请参考 VSCode 仓库,并访问绘图方法参数部分以获取额外的指导。

YOLO 能否使用 sixel 在终端中显示视频推理结果?

目前,尚未测试在终端中使用 sixel 显示视频推理结果或动画 GIF 帧,可能不受支持。建议从静态图像开始验证兼容性,并自行承担尝试视频结果的风险,同时注意性能限制。有关绘制推理结果的更多信息,请访问预测模式页面。

如何解决 python-sixel 库的问题?

要解决 python-sixel 库的问题:

  1. 确保库在你的虚拟环境中正确安装:

    pip  install  sixel 
    
  2. 验证你是否拥有必要的 Python 和系统依赖项。

  3. 参考 python-sixel GitHub 仓库 获取额外的文档和社区支持。

  4. 双重检查代码是否存在潜在错误,特别是 SixelWriter 的使用和图像数据转换步骤。

关于 YOLO 模型和 sixel 集成的进一步帮助,请参阅导出和预测模式文档页面。

优化 Ultralytics YOLO 模型的 OpenVINO 推理:全面指南

原文:docs.ultralytics.com/guides/optimizing-openvino-latency-vs-throughput-modes/

OpenVINO 生态系统

介绍

在部署深度学习模型时,特别是那些用于目标检测的模型(例如 Ultralytics YOLO 模型),实现最佳性能至关重要。本指南深入探讨了如何利用英特尔的 OpenVINO 工具包优化推理过程,专注于延迟和吞吐量。无论您是在消费级应用还是大规模部署中工作,了解并应用这些优化策略将确保您的模型在各种设备上高效运行。

优化延迟

对于需要从单个输入获得单个模型立即响应的应用程序,如消费者场景中典型的情况,延迟优化至关重要。目标是尽量减少输入和推理结果之间的延迟。然而,要实现低延迟需要仔细考虑,特别是在同时运行推理或管理多个模型时。

降低延迟优化关键策略:

  • 单设备单推理: 实现低延迟的最简单方法是限制每次设备仅进行一个推理。增加并发通常会导致延迟增加。

  • 利用子设备: 类似多套接 CPU 或多片 GPU 的设备可以利用其内部子设备,在增加最小延迟的情况下执行多个请求。

  • OpenVINO 性能提示: 在模型编译过程中,使用 OpenVINO 的 ov::hint::PerformanceMode::LATENCY 设置 ov::hint::performance_mode 属性可以简化性能调优,提供一种设备无关且未来可靠的方法。

管理首次推理延迟:

  • 模型缓存: 为了减少影响延迟的模型加载和编译时间,尽可能使用模型缓存。对于无法使用缓存的情况,CPU 通常提供最快的模型加载时间。

  • 模型映射 vs. 读取: 为了减少加载时间,OpenVINO 使用模型映射替换了模型读取。然而,如果模型位于可移动或网络驱动器上,考虑使用 ov::enable_mmap(false) 切换回读取模式。

  • AUTO 设备选择: 此模式在 CPU 上开始推理,在加速器准备就绪后自动切换,无缝地降低首次推理延迟。

优化吞吐量

在同时处理大量推理请求的场景中,优化吞吐量至关重要,旨在最大化资源利用率,同时不显著牺牲单个请求的性能。

吞吐量优化方法:

  1. OpenVINO 性能提示: 使用性能提示可以跨设备高效提升吞吐量的高级、未来可靠的方法。

    import openvino.properties.hint as hints
    
    config = {hints.performance_mode: hints.PerformanceMode.THROUGHPUT}
    compiled_model = core.compile_model(model, "GPU", config) 
    
  2. 显式批处理和流: 更精细的方法包括显式批处理和使用流进行高级性能调优。

设计面向吞吐量的应用程序:

为了最大化吞吐量,应用程序应该:

  • 并行处理输入,充分利用设备的能力。

  • 将数据流分解为并发推理请求,安排并行执行。

  • 利用异步 API 和回调来保持效率并避免设备饥饿。

多设备执行:

OpenVINO 的多设备模式通过自动平衡设备之间的推理请求而无需应用程序级别的设备管理,从而简化了吞吐量的扩展。

结论

使用 OpenVINO 优化 Ultralytics YOLO 模型以提高延迟和吞吐量可以显著增强应用程序的性能。通过仔细应用本指南中提出的策略,开发人员可以确保其模型高效运行,满足各种部署场景的需求。请记住,优化延迟或吞吐量的选择取决于您的具体应用需求和部署环境的特性。

欲获取更详细的技术信息和最新更新,请参阅OpenVINO 文档Ultralytics YOLO 存储库。这些资源提供深入的指南、教程和社区支持,帮助您充分利用您的深度学习模型。


确保您的模型实现最佳性能不仅仅是调整配置,还需要理解应用程序的需求并做出明智的决策。无论您是为实时响应进行优化还是为大规模处理最大化吞吐量,Ultralytics YOLO 模型与 OpenVINO 的结合为开发人员提供了强大的工具包,用于部署高性能人工智能解决方案。

常见问题

如何使用 OpenVINO 优化 Ultralytics YOLO 模型以实现低延迟?

使用 OpenVINO 优化 Ultralytics YOLO 模型以实现低延迟涉及几个关键策略:

  1. 单设备单推理: 限制每次设备推理一个以减少延迟。

  2. 利用子设备: 利用像多插槽 CPU 或多片 GPU 这样的设备,可以处理多个请求而增加的延迟最小。

  3. OpenVINO 性能提示: 在模型编译期间使用 OpenVINO 的ov::hint::PerformanceMode::LATENCY来简化设备无关的调优。

欲了解更多有关优化延迟的实用技巧,请查看我们指南中的延迟优化部分。

为何应使用 OpenVINO 优化 Ultralytics YOLO 吞吐量?

OpenVINO 通过最大化设备资源利用而不损失性能来增强 Ultralytics YOLO 模型的吞吐量。其主要优势包括:

  • 性能提示: 简单高效的跨设备性能调优。

  • 显式批处理和流处理: 为高级性能进行微调。

  • 多设备执行: 自动推理负载平衡,简化应用级管理。

示例配置:

import openvino.properties.hint as hints

config = {hints.performance_mode: hints.PerformanceMode.THROUGHPUT}
compiled_model = core.compile_model(model, "GPU", config) 

在我们详细指南的吞吐量优化部分了解更多。

在 OpenVINO 中减少首次推断延迟的最佳实践是什么?

要减少首次推断延迟,考虑以下实践:

  1. 模型缓存: 使用模型缓存来减少加载和编译时间。

  2. 模型映射 vs. 读取: 默认使用映射(ov::enable_mmap(true)),但如果模型位于可移动或网络驱动器上,则切换到读取(ov::enable_mmap(false))。

  3. AUTO 设备选择: 使用 AUTO 模式从 CPU 推断开始,并无缝转换到加速器。

关于管理首次推断延迟的详细策略,请参考管理首次推断延迟部分。

如何在 Ultralytics YOLO 和 OpenVINO 之间平衡优化延迟和吞吐量?

平衡延迟和吞吐量优化需要理解您的应用程序需求:

  • 延迟优化: 适用于需要即时响应的实时应用程序(例如消费级应用程序)。

  • 吞吐量优化: 适用于有许多并发推断的场景,最大化资源使用(例如大规模部署)。

使用 OpenVINO 的高级性能提示和多设备模式可以帮助找到适当的平衡。根据您的具体需求选择适当的OpenVINO 性能提示

我可以将 Ultralytics YOLO 模型与除 OpenVINO 外的其他 AI 框架一起使用吗?

是的,Ultralytics YOLO 模型非常灵活,可以与多种 AI 框架集成。选项包括:

Ultralytics 集成页面上探索更多集成。

ROS(机器人操作系统)快速入门指南

原文:docs.ultralytics.com/guides/ros-quickstart/

player.vimeo.com/video/639236696?h=740f412ce5

ROS 简介(字幕) 来自 Open RoboticsVimeo 上。

什么是 ROS?

机器人操作系统(ROS)是一个广泛用于机器人研究和工业的开源框架。ROS 提供了一系列库和工具,帮助开发者创建机器人应用程序。ROS 设计用于与各种机器人平台兼容,使其成为机器人学家的一种灵活而强大的工具。

ROS 的关键特性

  1. 模块化架构:ROS 采用模块化架构,允许开发者通过组合称为节点的较小、可重复使用的组件构建复杂系统。每个节点通常执行特定的功能,并且节点之间通过主题服务上的消息进行通信。

  2. 通信中间件:ROS 提供了强大的通信基础设施,支持进程间通信和分布式计算。通过数据流(主题)的发布-订阅模型和服务调用的请求-响应模型实现。

  3. 硬件抽象:ROS 在硬件上提供了一层抽象,使开发者能够编写与设备无关的代码。这使得相同的代码可以在不同的硬件设置上使用,从而更容易进行集成和实验。

  4. 工具和实用程序:ROS 自带丰富的可视化、调试和仿真工具集。例如,RViz 用于可视化传感器数据和机器人状态信息,而 Gazebo 则提供了一个强大的仿真环境,用于测试算法和机器人设计。

  5. 广泛的生态系统:ROS 生态系统庞大且不断增长,为不同的机器人应用提供了大量的包,包括导航、操作、感知等。社区积极参与这些包的开发和维护。

ROS 版本的演变

自 2007 年开发以来,ROS 已经通过多个版本进行了演进,每个版本都引入了新功能和改进,以满足机器人社区不断增长的需求。ROS 的开发可以分为两个主要系列:ROS 1 和 ROS 2。本指南侧重于 ROS 1 的长期支持(LTS)版本,称为 ROS Noetic Ninjemys,该代码也应该适用于早期版本。

ROS 1 与 ROS 2

虽然 ROS 1 为机器人开发提供了坚实的基础,但 ROS 2 通过提供以下功能解决了其缺点:

  • 实时性能:改进了对实时系统和确定性行为的支持。

  • 安全性:增强的安全功能,确保在各种环境下的安全可靠运行。

  • 可扩展性:更好地支持多机器人系统和大规模部署。

  • 跨平台支持:扩展了对 Linux 以外的各种操作系统的兼容性,包括 Windows 和 macOS。

  • 灵活通信:使用 DDS 实现更灵活和高效的进程间通信。

ROS 消息和话题

在 ROS 中,节点之间的通信通过消息话题来进行。消息是定义节点之间交换信息的数据结构,而话题是命名通道,用于发送和接收消息。节点可以向话题发布消息或者从话题订阅消息,从而使它们能够相互通信。这种发布-订阅模型支持异步通信,并解耦了节点之间的关系。在机器人系统中,每个传感器或执行器通常会向话题发布数据,然后其他节点可以消费这些数据进行处理或控制。在本指南中,我们将重点关注图像(Image)、深度(Depth)和点云(PointCloud)消息以及摄像头话题。

使用 Ultralytics YOLO 配置 ROS

本指南已在 此 ROS 环境 中进行了测试,该环境是 ROSbot ROS 仓库 的分支。该环境包括 Ultralytics YOLO 包、用于简便设置的 Docker 容器、全面的 ROS 包以及用于快速测试的 Gazebo 世界。它专为与 Husarion ROSbot 2 PRO 兼容设计。提供的代码示例将在任何 ROS Noetic/Melodic 环境中运行,包括仿真和真实世界中。

Husarion ROSbot 2 PRO

依赖安装

除了 ROS 环境外,您还需要安装以下依赖项:

  • ROS Numpy 包:用于快速转换 ROS Image 消息和 numpy 数组。

    pip  install  ros_numpy 
    
  • Ultralytics 包

    pip  install  ultralytics 
    

使用 Ultralytics 与 ROS sensor_msgs/Image

sensor_msgs/Image 消息类型 在 ROS 中常用于表示图像数据。它包含编码、高度、宽度和像素数据字段,适合用于传输摄像机或其他传感器捕获的图像。图像消息在机器人应用中广泛用于视觉感知、物体检测和导航等任务。

ROS Gazebo 中的检测与分割

图像逐步使用

以下代码片段演示了如何在 ROS 中使用 Ultralytics YOLO 包。在此示例中,我们订阅一个相机主题,使用 YOLO 处理传入的图像,并将检测到的对象发布到新的检测和分割主题。

首先,导入必要的库并实例化两个模型:一个用于分割,一个用于检测。初始化一个 ROS 节点(名称为ultralytics),以便与 ROS 主节点进行通信。为确保稳定连接,在此我们包含一个简短的暂停,以确保节点有足够的时间建立连接后再继续。

import time

import rospy

from ultralytics import YOLO

detection_model = YOLO("yolov8m.pt")
segmentation_model = YOLO("yolov8m-seg.pt")
rospy.init_node("ultralytics")
time.sleep(1) 

初始化两个 ROS 主题:一个用于检测,一个用于分割。这些主题将用于发布带注释的图像,使它们可以进一步处理。节点之间的通信使用sensor_msgs/Image消息进行。

from sensor_msgs.msg import Image

det_image_pub = rospy.Publisher("/ultralytics/detection/image", Image, queue_size=5)
seg_image_pub = rospy.Publisher("/ultralytics/segmentation/image", Image, queue_size=5) 

最后,创建一个订阅器,监听/camera/color/image_raw主题上的消息,并为每个新消息调用回调函数。此回调函数接收类型为sensor_msgs/Image的消息,使用ros_numpy将其转换为 numpy 数组,使用之前实例化的 YOLO 模型处理图像,标注图像,然后将其分别发布回/ultralytics/detection/image(用于检测)和/ultralytics/segmentation/image(用于分割)的主题。

import ros_numpy

def callback(data):
  """Callback function to process image and publish annotated images."""
    array = ros_numpy.numpify(data)
    if det_image_pub.get_num_connections():
        det_result = detection_model(array)
        det_annotated = det_result[0].plot(show=False)
        det_image_pub.publish(ros_numpy.msgify(Image, det_annotated, encoding="rgb8"))

    if seg_image_pub.get_num_connections():
        seg_result = segmentation_model(array)
        seg_annotated = seg_result[0].plot(show=False)
        seg_image_pub.publish(ros_numpy.msgify(Image, seg_annotated, encoding="rgb8"))

rospy.Subscriber("/camera/color/image_raw", Image, callback)

while True:
    rospy.spin() 
完整代码
import time

import ros_numpy
import rospy
from sensor_msgs.msg import Image

from ultralytics import YOLO

detection_model = YOLO("yolov8m.pt")
segmentation_model = YOLO("yolov8m-seg.pt")
rospy.init_node("ultralytics")
time.sleep(1)

det_image_pub = rospy.Publisher("/ultralytics/detection/image", Image, queue_size=5)
seg_image_pub = rospy.Publisher("/ultralytics/segmentation/image", Image, queue_size=5)

def callback(data):
  """Callback function to process image and publish annotated images."""
    array = ros_numpy.numpify(data)
    if det_image_pub.get_num_connections():
        det_result = detection_model(array)
        det_annotated = det_result[0].plot(show=False)
        det_image_pub.publish(ros_numpy.msgify(Image, det_annotated, encoding="rgb8"))

    if seg_image_pub.get_num_connections():
        seg_result = segmentation_model(array)
        seg_annotated = seg_result[0].plot(show=False)
        seg_image_pub.publish(ros_numpy.msgify(Image, seg_annotated, encoding="rgb8"))

rospy.Subscriber("/camera/color/image_raw", Image, callback)

while True:
    rospy.spin() 
```</details> <details class="tip" open="open"><summary>调试</summary>

ROS(机器人操作系统)的调试由于系统的分布性质可能具有挑战性。有几个工具可以协助此过程:

1.  `rostopic echo <TOPIC-NAME>`:此命令允许您查看发布在特定主题上的消息,帮助您检查数据流动态。

1.  `rostopic list`:使用此命令列出 ROS 系统中所有可用的主题,为您提供活动数据流的概述。

1.  `rqt_graph`:这个可视化工具显示节点之间的通信图,提供节点如何互连及相互作用的洞察。

1.  对于更复杂的可视化,如三维表示,可以使用[RViz](https://wiki.ros.org/rviz)。RViz(ROS 可视化)是一个强大的 ROS 三维可视化工具,允许您实时查看机器人及其环境的状态。通过 RViz,您可以查看传感器数据(例如`sensors_msgs/Image`),机器人模型状态以及各种其他类型的信息,这有助于调试和理解您的机器人系统行为。</details>

### 用`std_msgs/String`发布检测到的类别

标准的 ROS 消息也包括 `std_msgs/String` 消息。在许多应用中,不必重新发布整个带有注释的图像;相反,只需要机器人视野中存在的类。以下示例演示了如何使用 `std_msgs/String` [消息](https://docs.ros.org/en/noetic/api/std_msgs/html/msg/String.html) 将检测到的类别重新发布到 `/ultralytics/detection/classes` 话题。这些消息更轻量级且提供了关键信息,对各种应用非常有价值。

#### 示例用例

考虑一个配备有相机和物体检测模型的仓库机器人。机器人可以通过发布 `std_msgs/String` 消息列表而不是通过网络发送大型带有注释的图像。例如,当机器人检测到像 "box"、"pallet" 和 "forklift" 这样的对象时,它将这些类别发布到 `/ultralytics/detection/classes` 话题。然后,中央监控系统可以使用这些信息实时跟踪库存,优化机器人的路径规划以避开障碍物,或触发特定动作,如拾取检测到的箱子。这种方法减少了通信所需的带宽,并侧重于传输关键数据。

### 逐步使用字符串

本示例演示了如何在 ROS 中使用 Ultralytics YOLO 软件包。在这个例子中,我们订阅相机话题,使用 YOLO 处理传入的图像,并通过 `std_msgs/String` 消息将检测到的对象发布到新的话题 `/ultralytics/detection/classes`。使用 `ros_numpy` 软件包将 ROS Image 消息转换为 numpy 数组,以便与 YOLO 进行处理。

```py
import time

import ros_numpy
import rospy
from sensor_msgs.msg import Image
from std_msgs.msg import String

from ultralytics import YOLO

detection_model = YOLO("yolov8m.pt")
rospy.init_node("ultralytics")
time.sleep(1)
classes_pub = rospy.Publisher("/ultralytics/detection/classes", String, queue_size=5)

def callback(data):
  """Callback function to process image and publish detected classes."""
    array = ros_numpy.numpify(data)
    if classes_pub.get_num_connections():
        det_result = detection_model(array)
        classes = det_result[0].boxes.cls.cpu().numpy().astype(int)
        names = [det_result[0].names[i] for i in classes]
        classes_pub.publish(String(data=str(names)))

rospy.Subscriber("/camera/color/image_raw", Image, callback)
while True:
    rospy.spin() 

使用 Ultralytics 和 ROS 深度图像

除了 RGB 图像外,ROS 还支持 深度图像,这些图像提供了有关物体与相机之间距离的信息。深度图像对于机器人应用(如避障、3D 映射和定位)至关重要。

深度图像是一种图像,其中每个像素表示从相机到对象的距离。与捕捉颜色的 RGB 图像不同,深度图像捕捉空间信息,使机器人能够感知其环境的三维结构。

获取深度图像

可以使用各种传感器获取深度图像:

  1. 立体相机:使用两个相机根据图像视差计算深度。

  2. 飞行时间(ToF)相机:测量光返回对象所需的时间。

  3. 结构光传感器:投射模式并测量其在表面上的变形。

使用深度图像的 YOLO

在 ROS 中,深度图像由sensor_msgs/Image消息类型表示,其中包括编码、高度、宽度和像素数据字段。深度图像的编码字段通常使用像"16UC1"这样的格式,表示每个像素的 16 位无符号整数,其中每个值表示到物体的距离。深度图像通常与 RGB 图像一起使用,以提供环境的更全面视图。

使用 YOLO 可以从 RGB 和深度图像中提取并结合信息。例如,YOLO 可以检测 RGB 图像中的对象,这一检测可以用于在深度图像中确定相应的区域。这样可以提取检测到对象的精确深度信息,增强机器人在三维环境中理解其环境的能力。

RGB-D 相机

在处理深度图像时,确保 RGB 和深度图像正确对齐非常重要。RGB-D 相机(如Intel RealSense系列)提供了同步的 RGB 和深度图像,使得从两个来源结合信息更加容易。如果使用单独的 RGB 和深度相机,重要的是对它们进行校准,以确保准确的对齐。

深度逐步使用

在本例中,我们使用 YOLO 对图像进行分割,并将提取的掩码应用于深度图像中的对象分割。这样可以确定感兴趣对象的每个像素距离相机的焦点中心的距离。通过获取这些距离信息,我们可以计算场景中相机与特定对象之间的距离。首先导入必要的库,创建一个 ROS 节点,并实例化分割模型和 ROS 主题。

import time

import rospy
from std_msgs.msg import String

from ultralytics import YOLO

rospy.init_node("ultralytics")
time.sleep(1)

segmentation_model = YOLO("yolov8m-seg.pt")

classes_pub = rospy.Publisher("/ultralytics/detection/distance", String, queue_size=5) 

接下来,定义一个回调函数来处理传入的深度图像消息。该函数等待深度图像和 RGB 图像消息,将它们转换为 numpy 数组,并将分割模型应用于 RGB 图像。然后提取每个检测到对象的分割掩码,并使用深度图像计算对象距相机的平均距离。大多数传感器具有最大距离,称为剪裁距离,超出此距离的值被表示为 inf(np.inf)。在处理之前,过滤这些空值并将它们赋值为0是非常重要的。最后,将检测到的对象及其平均距离发布到/ultralytics/detection/distance主题上。

import numpy as np
import ros_numpy
from sensor_msgs.msg import Image

def callback(data):
  """Callback function to process depth image and RGB image."""
    image = rospy.wait_for_message("/camera/color/image_raw", Image)
    image = ros_numpy.numpify(image)
    depth = ros_numpy.numpify(data)
    result = segmentation_model(image)

    for index, cls in enumerate(result[0].boxes.cls):
        class_index = int(cls.cpu().numpy())
        name = result[0].names[class_index]
        mask = result[0].masks.data.cpu().numpy()[index, :, :].astype(int)
        obj = depth[mask == 1]
        obj = obj[~np.isnan(obj)]
        avg_distance = np.mean(obj) if len(obj) else np.inf

    classes_pub.publish(String(data=str(all_objects)))

rospy.Subscriber("/camera/depth/image_raw", Image, callback)

while True:
    rospy.spin() 
完整代码
import time

import numpy as np
import ros_numpy
import rospy
from sensor_msgs.msg import Image
from std_msgs.msg import String

from ultralytics import YOLO

rospy.init_node("ultralytics")
time.sleep(1)

segmentation_model = YOLO("yolov8m-seg.pt")

classes_pub = rospy.Publisher("/ultralytics/detection/distance", String, queue_size=5)

def callback(data):
  """Callback function to process depth image and RGB image."""
    image = rospy.wait_for_message("/camera/color/image_raw", Image)
    image = ros_numpy.numpify(image)
    depth = ros_numpy.numpify(data)
    result = segmentation_model(image)

    for index, cls in enumerate(result[0].boxes.cls):
        class_index = int(cls.cpu().numpy())
        name = result[0].names[class_index]
        mask = result[0].masks.data.cpu().numpy()[index, :, :].astype(int)
        obj = depth[mask == 1]
        obj = obj[~np.isnan(obj)]
        avg_distance = np.mean(obj) if len(obj) else np.inf

    classes_pub.publish(String(data=str(all_objects)))

rospy.Subscriber("/camera/depth/image_raw", Image, callback)

while True:
    rospy.spin() 
```</details>

## 使用 ROS 的 Ultralytics `sensor_msgs/PointCloud2`

![ROS Gazebo 中的检测和分割](https://gitee.com/OpenDocCN/dsai-docs-zh/raw/master/docs/ultra/img/034919731770fe377697d6eddc2c6aa4.png)

`sensor_msgs/PointCloud2` [消息类型](https://docs.ros.org/en/api/sensor_msgs/html/msg/PointCloud2.html) 是 ROS 中用于表示 3D 点云数据的数据结构。该消息类型对机器人应用至关重要,可以执行 3D 映射、对象识别和定位等任务。

点云是在三维坐标系内定义的数据点集合。这些数据点代表通过 3D 扫描技术捕获的对象或场景的外部表面。云中的每个点都有`X`、`Y`和`Z`坐标,对应其空间位置,可能还包括颜色和强度等附加信息。

参考框架

在处理`sensor_msgs/PointCloud2`时,必须考虑从中获取点云数据的传感器参考框架。点云最初是在传感器的参考框架中捕获的。您可以通过监听`/tf_static`话题来确定这个参考框架。然而,根据您的具体应用需求,您可能需要将点云转换为另一个参考框架。这可以通过使用`tf2_ros`包来实现,该包提供了管理坐标框架和在它们之间转换数据的工具。

获取点云

可以使用各种传感器获取点云:

1.  **激光雷达(Light Detection and Ranging,LIDAR)**:使用激光脉冲测量物体的距离并创建高精度的 3D 地图。

1.  **深度摄像头**:捕获每个像素的深度信息,允许对场景进行 3D 重建。

1.  **立体相机**:利用两个或更多摄像头通过三角测量获取深度信息。

1.  **结构光扫描仪**:在表面投射已知模式,并测量变形以计算深度。

### 使用 YOLO 处理点云

要将 YOLO 与`sensor_msgs/PointCloud2`类型的消息集成,可以采用类似于深度图的方法。通过利用点云中嵌入的颜色信息,我们可以提取一个 2D 图像,使用 YOLO 对该图像进行分割,然后将结果掩码应用于三维点,以隔离感兴趣的 3D 对象。

处理点云推荐使用 Open3D(`pip install open3d`),这是一个用户友好的 Python 库。Open3D 提供了强大的工具来管理点云数据结构、可视化它们,并无缝执行复杂操作。这个库可以显著简化处理过程,增强我们在与基于 YOLO 的分割结合时操作和分析点云的能力。

#### 点云逐步使用

导入必要的库并实例化 YOLO 模型用于分割。

```py
import time

import rospy

from ultralytics import YOLO

rospy.init_node("ultralytics")
time.sleep(1)
segmentation_model = YOLO("yolov8m-seg.pt") 

创建一个名为pointcloud2_to_array的函数,将sensor_msgs/PointCloud2消息转换为两个 numpy 数组。sensor_msgs/PointCloud2消息基于获取图像的widthheight包含n个点。例如,一个480 x 640的图像将有307,200个点。每个点包括三个空间坐标(xyz)和对应的RGB格式颜色。这些可以被视为两个独立的信息通道。

函数以原始相机分辨率(width x height)返回xyz坐标和RGB值。大多数传感器具有最大距离,称为剪裁距离,超出该距离的值表示为 inf(np.inf)。在处理之前,过滤这些空值并将它们分配一个0值是很重要的。

import numpy as np
import ros_numpy

def pointcloud2_to_array(pointcloud2: PointCloud2) -> tuple:
  """
 Convert a ROS PointCloud2 message to a numpy array.

 Args:
 pointcloud2 (PointCloud2): the PointCloud2 message

 Returns:
 (tuple): tuple containing (xyz, rgb)
 """
    pc_array = ros_numpy.point_cloud2.pointcloud2_to_array(pointcloud2)
    split = ros_numpy.point_cloud2.split_rgb_field(pc_array)
    rgb = np.stack([split["b"], split["g"], split["r"]], axis=2)
    xyz = ros_numpy.point_cloud2.get_xyz_points(pc_array, remove_nans=False)
    xyz = np.array(xyz).reshape((pointcloud2.height, pointcloud2.width, 3))
    nan_rows = np.isnan(xyz).all(axis=2)
    xyz[nan_rows] = [0, 0, 0]
    rgb[nan_rows] = [0, 0, 0]
    return xyz, rgb 

接下来,订阅/camera/depth/points话题以接收点云消息,并使用pointcloud2_to_array函数将sensor_msgs/PointCloud2消息转换为包含 XYZ 坐标和 RGB 值的 numpy 数组。使用 YOLO 模型处理 RGB 图像以提取分割的物体。对于每个检测到的物体,提取分割掩码并将其应用于 RGB 图像和 XYZ 坐标,以在 3D 空间中隔离物体。

处理掩码很简单,因为它由二进制值组成,其中1表示物体的存在,0表示物体的不存在。要应用掩码,只需将原始通道乘以掩码。这个操作有效地将兴趣对象从图像中隔离出来。最后,创建一个 Open3D 点云对象,并使用相关颜色在 3D 空间中可视化分割的对象。

import sys

import open3d as o3d

ros_cloud = rospy.wait_for_message("/camera/depth/points", PointCloud2)
xyz, rgb = pointcloud2_to_array(ros_cloud)
result = segmentation_model(rgb)

if not len(result[0].boxes.cls):
    print("No objects detected")
    sys.exit()

classes = result[0].boxes.cls.cpu().numpy().astype(int)
for index, class_id in enumerate(classes):
    mask = result[0].masks.data.cpu().numpy()[index, :, :].astype(int)
    mask_expanded = np.stack([mask, mask, mask], axis=2)

    obj_rgb = rgb * mask_expanded
    obj_xyz = xyz * mask_expanded

    pcd = o3d.geometry.PointCloud()
    pcd.points = o3d.utility.Vector3dVector(obj_xyz.reshape((ros_cloud.height * ros_cloud.width, 3)))
    pcd.colors = o3d.utility.Vector3dVector(obj_rgb.reshape((ros_cloud.height * ros_cloud.width, 3)) / 255)
    o3d.visualization.draw_geometries([pcd]) 
完整代码
import sys
import time

import numpy as np
import open3d as o3d
import ros_numpy
import rospy

from ultralytics import YOLO

rospy.init_node("ultralytics")
time.sleep(1)
segmentation_model = YOLO("yolov8m-seg.pt")

def pointcloud2_to_array(pointcloud2: PointCloud2) -> tuple:
  """
 Convert a ROS PointCloud2 message to a numpy array.

 Args:
 pointcloud2 (PointCloud2): the PointCloud2 message

 Returns:
 (tuple): tuple containing (xyz, rgb)
 """
    pc_array = ros_numpy.point_cloud2.pointcloud2_to_array(pointcloud2)
    split = ros_numpy.point_cloud2.split_rgb_field(pc_array)
    rgb = np.stack([split["b"], split["g"], split["r"]], axis=2)
    xyz = ros_numpy.point_cloud2.get_xyz_points(pc_array, remove_nans=False)
    xyz = np.array(xyz).reshape((pointcloud2.height, pointcloud2.width, 3))
    nan_rows = np.isnan(xyz).all(axis=2)
    xyz[nan_rows] = [0, 0, 0]
    rgb[nan_rows] = [0, 0, 0]
    return xyz, rgb

ros_cloud = rospy.wait_for_message("/camera/depth/points", PointCloud2)
xyz, rgb = pointcloud2_to_array(ros_cloud)
result = segmentation_model(rgb)

if not len(result[0].boxes.cls):
    print("No objects detected")
    sys.exit()

classes = result[0].boxes.cls.cpu().numpy().astype(int)
for index, class_id in enumerate(classes):
    mask = result[0].masks.data.cpu().numpy()[index, :, :].astype(int)
    mask_expanded = np.stack([mask, mask, mask], axis=2)

    obj_rgb = rgb * mask_expanded
    obj_xyz = xyz * mask_expanded

    pcd = o3d.geometry.PointCloud()
    pcd.points = o3d.utility.Vector3dVector(obj_xyz.reshape((ros_cloud.height * ros_cloud.width, 3)))
    pcd.colors = o3d.utility.Vector3dVector(obj_rgb.reshape((ros_cloud.height * ros_cloud.width, 3)) / 255)
    o3d.visualization.draw_geometries([pcd]) 
```</details>

![使用 Ultralytics 进行点云分割](https://gitee.com/OpenDocCN/dsai-docs-zh/raw/master/docs/ultra/img/53ab87c81395c1cae864d340d0d0fd07.png)

## 常见问题解答(FAQ)

### 什么是机器人操作系统(ROS)?

[机器人操作系统(ROS)](https://www.ros.org/)是一个开源框架,广泛用于机器人领域,帮助开发者创建健壮的机器人应用程序。它提供了一系列[库和工具](https://www.ros.org/blog/ecosystem/)用于构建和与机器人系统交互,使复杂应用程序的开发更加轻松。ROS 支持节点间通过[话题](https://wiki.ros.org/ROS/Tutorials/UnderstandingTopics)或[服务](https://wiki.ros.org/ROS/Tutorials/UnderstandingServicesParams)传递消息进行通信。

### 如何将 Ultralytics YOLO 与 ROS 集成以进行实时目标检测?

将 Ultralytics YOLO 与 ROS 集成涉及设置 ROS 环境并使用 YOLO 处理传感器数据。首先安装必要的依赖项,如`ros_numpy`和 Ultralytics YOLO:

```py
pip  install  ros_numpy  ultralytics 

接下来,创建一个 ROS 节点并订阅图像话题以处理传入数据。以下是一个简单的示例:

import ros_numpy
import rospy
from sensor_msgs.msg import Image

from ultralytics import YOLO

detection_model = YOLO("yolov8m.pt")
rospy.init_node("ultralytics")
det_image_pub = rospy.Publisher("/ultralytics/detection/image", Image, queue_size=5)

def callback(data):
    array = ros_numpy.numpify(data)
    det_result = detection_model(array)
    det_annotated = det_result[0].plot(show=False)
    det_image_pub.publish(ros_numpy.msgify(Image, det_annotated, encoding="rgb8"))

rospy.Subscriber("/camera/color/image_raw", Image, callback)
rospy.spin() 

ROS 话题是什么以及它们在 Ultralytics YOLO 中如何使用?

ROS 主题通过发布-订阅模型在 ROS 网络中的节点之间进行通信。主题是节点用来异步发送和接收消息的命名通道。在 Ultralytics YOLO 的背景下,您可以使一个节点订阅图像主题,使用 YOLO 处理图像进行检测或分割等任务,并将结果发布到新的主题上。

例如,订阅相机主题并处理传入图像进行检测:

rospy.Subscriber("/camera/color/image_raw", Image, callback) 

在 ROS 中为什么要使用 Ultralytics YOLO 的深度图像?

ROS 中的深度图像,由sensor_msgs/Image表示,提供了物体距相机的距离,对于障碍物避免、3D 地图和定位等任务至关重要。通过使用深度信息和 RGB 图像,机器人可以更好地理解其 3D 环境。

使用 YOLO,可以从 RGB 图像中提取分割掩模,并将这些掩模应用到深度图像上,以获取精确的 3D 物体信息,从而提升机器人在环境中导航和交互的能力。

如何使用 YOLO 在 ROS 中可视化 3D 点云?

使用 YOLO 在 ROS 中可视化 3D 点云:

  1. sensor_msgs/PointCloud2消息转换为 numpy 数组。

  2. 使用 YOLO 来分割 RGB 图像。

  3. 将分割掩模应用于点云。

这里有一个使用 Open3D 进行可视化的例子:

import sys

import open3d as o3d
import ros_numpy
import rospy
from sensor_msgs.msg import PointCloud2

from ultralytics import YOLO

rospy.init_node("ultralytics")
segmentation_model = YOLO("yolov8m-seg.pt")

def pointcloud2_to_array(pointcloud2):
    pc_array = ros_numpy.point_cloud2.pointcloud2_to_array(pointcloud2)
    split = ros_numpy.point_cloud2.split_rgb_field(pc_array)
    rgb = np.stack([split["b"], split["g"], split["r"]], axis=2)
    xyz = ros_numpy.point_cloud2.get_xyz_points(pc_array, remove_nans=False)
    xyz = np.array(xyz).reshape((pointcloud2.height, pointcloud2.width, 3))
    return xyz, rgb

ros_cloud = rospy.wait_for_message("/camera/depth/points", PointCloud2)
xyz, rgb = pointcloud2_to_array(ros_cloud)
result = segmentation_model(rgb)

if not len(result[0].boxes.cls):
    print("No objects detected")
    sys.exit()

classes = result[0].boxes.cls.cpu().numpy().astype(int)
for index, class_id in enumerate(classes):
    mask = result[0].masks.data.cpu().numpy()[index, :, :].astype(int)
    mask_expanded = np.stack([mask, mask, mask], axis=2)

    obj_rgb = rgb * mask_expanded
    obj_xyz = xyz * mask_expanded

    pcd = o3d.geometry.PointCloud()
    pcd.points = o3d.utility.Vector3dVector(obj_xyz.reshape((-1, 3)))
    pcd.colors = o3d.utility.Vector3dVector(obj_rgb.reshape((-1, 3)) / 255)
    o3d.visualization.draw_geometries([pcd]) 

这种方法提供了分割对象的 3D 可视化,对于导航和操作等任务非常有用。

posted @ 2024-08-08 13:58  绝不原创的飞龙  阅读(19)  评论(0编辑  收藏  举报