18
13

NVIDIA Vision Programming Interface (VPI)入門 Python API編

Last updated at Posted at 2023-05-04

VPIとは

VPI(https://docs.nvidia.com/vpi/)は、NVIDIA Vision Programming Interfaceのことで、Jetsonデバイス、NVIDIA GPU搭載のx86_64マシン向けにコンピュータビジョン、画像処理アルゴリズムの機能を提供するライブラリです。

また、各種アルゴリズムは、CPUだけでなくNVIDIA GPU、PVAなどの異なるアクセラレータ向けの実装がなされており、特定アクセラレータに処理をオフロードし、連携できるようになっています。https://docs.nvidia.com/vpi/2.2/architecture.htmlにあるVPIアーキテクチャの図を以下に引用します。

より詳細な情報を知りたい方はhttps://www.youtube.com/watch?v=gCf1wQLfYCMにあるNVIDIA Japanによる解説動画を観るとよいでしょう。

動作環境

VPIがサポートしている動作環境は以下の通りです。詳細はhttps://docs.nvidia.com/vpi/2.2/architecture.html#arch_supported_platformsを参照ください。

  • Jetson AGX Xavier、Jetson Xavier NX
  • Jetson AGX Orin、Jetson AGX Orin NX
  • NVIDIA GPU搭載(Maxwell世代以降)のLinux x86_64マシン

インストール方法はhttps://docs.nvidia.com/vpi/2.2/installation.htmlを参照ください。

バックエンド

https://docs.nvidia.com/vpi/2.2/basic_concepts.html#basic_backendにある表を以下に示します。この表にはVPIが提供するバックエンドと対応デバイス、アーキテクチャが書かれています。

Backend Device/platform
CPU x86_64アーキテクチャ/Ubuntuマシン、Jetsonデバイスで利用可能
CUDA x86_64アーキテクチャのNVIDIA GPU搭載Ubuntuマシン、Jetsonデバイスで利用可能
PVA
(Programmable Vision Accelerator)
Jetson AGX Xavier、Jetson Xavier NXシリーズ以降のデバイスのみで利用可能(NanoシリーズはPVA非搭載)
VIC
(Video Image Compositor)
Jetsonデバイスのみ利用可能
NVENC
(NVIDIA Encoder Engine)
Jetsonデバイスのみ利用可能。ただし、dense optical flowはJetson AGX Xavierシリーズ以降のJetsonデバイスのみ
OFA
(NVIDIA Optical Flow Accelerator)
Jetson AGX OrinシリーズのJetsonデバイスのみ利用可能

各バックエンドの詳細はhttps://docs.nvidia.com/vpi/2.2/architecture.html#arch_backendを参照ください。

データ構造

VPIにおけるプリミティブなデータ構造について紹介します。VPIはC API、Python APIを提供していますが、以降の説明ではPython APIを用いた例を述べます。詳細はhttps://docs.nvidia.com/vpi/2.2/basic_concepts.html#basic_buffersを参照ください。

以降、これらのプリミティブなデータ構造の使い方の例を示します。

vpi.Image

vpi.Imageの使用例は以下の通りです。ここでは8bit unsigned integer型の画素値を持つ1チャンネル画像を扱っているので画像フォーマットはvpi.Format.U8と指定しています。画像フォーマットの詳細はhttps://docs.nvidia.com/vpi/2.2/python/build/vpi.Format.htmlを参照ください。

import vpi

width = 640
height = 480
format = vpi.Format.U8

# vpi.Image
img = vpi.Image((width, height), format)

print(f"img.format = {img.format}")
print(f"img.width = {img.width}")
print(f"img.height = {img.height}")
print(f"img.size = {img.size}")

このスクリプトの実行結果は以下の通りです。

img.format = Format.U8
img.width = 640
img.height = 480
img.size = (640, 480)

vpi.Array

vpi.Arrayの使用例は以下の通りです。

import vpi

capacity = 10
format = vpi.Format.U8

# vpi.Array
arr = vpi.Array(capacity, format)

print(f"arr.capacity = {arr.capacity}")
print(f"arr.size = {arr.size}")

このスクリプトの実行結果は以下の通りです。

arr.capacity = 10
arr.size = 0

対応アルゴリズム

VPIが提供するコンピュータビジョン、画像処理アルゴリズムはhttps://docs.nvidia.com/vpi/2.2/algorithms.htmlにあります。ただし、バックエンドによってはサポートしていないアルゴリズムがあったり、利用できる画像サイズ、パラメータに制約があるためアルゴリズムのページを確認ください。

シンプルなパイプライン

https://docs.nvidia.com/vpi/2.2/architecture.html#arch_simple_pipelineにあるシンプルな画像処理パイプラインの例を用いて説明します。この例ではおおまかに以下の処理を行っています。

  1. 読み込んだ画像をndarrayに格納
  2. ndarrayをvpi.Imageに変換
  3. CUDA backendでbox filter適用
import cv2
import vpi

img_cv = cv2.imread("kodim08.png", cv2.IMREAD_GRAYSCALE)

# ndarrayをvpi.Imageに変換
img = vpi.asimage(img_cv)

# CUDA backendでbox filter適用
with vpi.Backend.CUDA:
    output = img.box_filter(ksize=7)

前述のコードで

with vpi.Backend.CUDA:
    output = img.box_filter(ksize=7)

となっている箇所は、box_filterメソッドにてバックエンドを指定するように

output = img.box_filter(ksize=7, backend=vpi.Backend.CUDA)

と書くこともできます。

データ変換

VPIには各種データ変換機能が用意されており、他のライブラリと連携ができるようになっています。
ここではPython APIでよく使うと思われる以下の変換について紹介します。

  • ndarray->vpi.Image
  • vpi.Image->ndarray
  • torch.Tensor->vpi.Image

また、Jetsonデバイスのみではありますが、EGLImage、NvBufferとの相互変換もサポートしています。詳細はhttps://docs.nvidia.com/vpi/2.2/python/interoperabilities.htmlを参照ください。

ndarray->vpi.Image

vpi.asimageでndarrayからvpi.Imageへ変換することができます。

import cv2
import vpi

img_cv = cv2.imread("kodim08.png", cv2.IMREAD_GRAYSCALE)

# ndarrayをvpi.Imageに変換
img = vpi.asimage(img_cv)

vpi.Image->ndarray

以下のメソッドでvpi.Imageからndarrayへ変換することができます。

import vpi

width = 640
height = 480
format = vpi.Format.U8
img = vpi.Image((width, height), format)

# cpuメソッド
buffer1 = input.cpu()

# toメソッド
buffer2 = input.to(vpi.MemType.CPU)

torch.Tensor->vpi.Image

vpi.asimageでtorch.Tensorからvpi.Imageへ変換することができます。

import cv2
import torch
import vpi

img_cv = cv2.imread("kodim08.png", cv2.IMREAD_GRAYSCALE)
torch_image = torch.asarray(np_image).cuda()
vpi_image = vpi.asimage(torch_image)

詳細はhttps://developer.nvidia.com/blog/improved-interoperability-between-vpi-and-pytorch/を参照ください。

VPIディレクトリ構成

https://docs.nvidia.com/vpi/2.2/installation.htmlに説明がある通り、VPIのディレクトリ構成は下表の通りです。

ファイルパス
/opt/nvidia/vpi2 VPIルートディレクトリ
/opt/nvidia/vpi2/bin デモプログラムなどの実行バイナリが格納されたディレクトリ
/opt/nvidia/vpi2/include インクルードディレクトリ
/opt/nvidia/vpi2/lib/<arch> VPIライブラリが格納されたディレクトリ
/opt/nvidia/vpi2/samples VPIサンプルプログラム(C++、Python)が格納されたディレクトリ

動作確認環境

筆者は以下の環境で動作確認を行いました。

  • reComputer J4012(Jetson Orin NX 16GB)
  • JetPack 5.1.1
  • Python 3.8.10
  • VPI 2.2.7
18
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
13