0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

YOLO26 のセマンティックセグメンテーションを PyTorch と ONNX で比較する

0
Last updated at Posted at 2026-07-14

YOLO26 のセマンティックセグメンテーションを PyTorch と ONNX で比較する

こんにちは、皆さん。

画像に車が写っているかだけでなく、道路や歩道がどこからどこまで続いているかを、画素単位で知りたいことがあります。

さて、今日は YOLO26n のセマンティックセグメンテーションモデルを Apple Silicon の CPU で動かし、PyTorch と ONNX Runtime の結果と速度を比較しました。

先に結果を書くと、両方の class map は 99.3129% の画素で一致しました。ONNX Runtime の全処理時間は平均27.55 ms、PyTorch は266.00 msでした。差の多くは推論本体ではなく、後処理の違いから生じています。

今回検証する内容

セマンティックセグメンテーションは、画像の各画素をクラスへ分ける処理です。物体を四角で囲む object detection と違い、道路、空、車などの形に沿った領域を得られます。

今回は Cityscapes で学習された公式 yolo26n-sem.pt を使い、次を確認します。

  • Apple M1 Max の CPU で PyTorch 推論と ONNX export ができるか
  • 同じ入力条件で、2つの class map がどの程度一致するか
  • 前処理、推論、後処理、全処理にかかる時間
  • 都市道路の生成画像を19クラスへどのように分けるか

検証に使用した元画像です。

YOLO26セマンティックセグメンテーションの検証前の都市道路画像

対象の lab: kiarina/labs/2026/07/14/yolo26-semantic-segmentation

検証環境の再現

mise と uv、初回のモデル・共有画像取得にインターネット接続が必要です。

git clone --depth 1 --filter=blob:none --sparse \
  https://github.com/kiarina/labs.git
cd labs
git sparse-checkout set .mise/tasks 2026/07/14/yolo26-semantic-segmentation
mise trust . && mise trust 2026/07/14/yolo26-semantic-segmentation
mise -C 2026/07/14/yolo26-semantic-segmentation run

初回は checkpoint を取得して SHA-256 を検証し、ONNX opset 18 へ変換します。実行後は PyTorch 版、ONNX 版、差分、説明付き比較の4画像が生成されます。

使用したモデルとライセンス

使用した学習済みモデルは1つです。PyTorch と ONNX は別のモデルを比較しているのではなく、同じ checkpoint を2つの実行経路で動かしています。

モデル 役割 入出力
yolo26n-sem.pt 各画素を Cityscapes の19クラスへ分類する 1x3x640x640画像 → class logits
export した yolo26n-sem.onnx 同じ重みを ONNX Runtime で実行する 1x3x640x640画像 → 1x640x640 class ID

class logits は、各画素が各クラスらしい度合いを表す生の値です。class ID は、その中から選ばれたクラスの番号です。

データの流れを短く表すと次のようになります。

1774x887 JPEG
  -> 縦横比を保って640x640へ配置(letterbox)
  -> 同じcheckpointを2経路で実行
       PyTorch: class logits -> 拡大 -> class ID
       ONNX:    640x640 class ID -> 拡大
  -> 元の1774x887 class map
  -> 画素一致率、クラス別IoU、処理時間を比較

letterbox は、画像を変形せず余白を足して指定サイズへ収める方法です。IoU は2領域の重なり具合で、100%に近いほど一致しています。

  • checkpoint: Ultralytics assets v8.4.0
  • model size: 3,487,283 bytes
  • SHA-256: f3f293cca764de1f93044030d8d5612de9c5ffbf37c9c8ea1b69418b73038999
  • Ultralytics のコードと学習済みモデル: AGPL-3.0 または Ultralytics Enterprise License

Ultralytics のライセンス説明では、学習済みモデルも標準では AGPL-3.0 の対象とされています。非公開・商用製品などへ組み込む場合は Enterprise License が必要になる場合があります。利用時点の公式条件を確認してください。本 lab は checkpoint や生成した ONNX を Git 管理せず、実行時に取得・生成します。

検証方法

入力は、車道、歩道、建物、信号、車、人、自転車などが写る固定画像1枚です。

file: tests/assets/jpg/street_scene_1774x887_287kb.jpg
resolution: 1774x887
SHA-256: d5c865f452599311fbbfd0c132bb4f8b7ade4dd88f0c8ac14ce136490ea53a2e

PyTorch と ONNX の両方を imgsz=640、rect=False、CPU に固定しました。3回 warm-up した後、10回測定しています。warm-up は、初回だけ発生する準備処理の影響を減らすための事前実行です。モデル初期化、画像読み込み、画像保存は benchmark に含めません。

このモデルが出力できるのは次の19クラスです。

road, sidewalk, building, wall, fence, pole, traffic light, traffic sign,
vegetation, terrain, sky, person, rider, car, truck, bus, train,
motorcycle, bicycle

検証結果

左が元画像、右が ONNX の class map を50%で重ねた結果です。下には実際に予測されたクラスと画素割合を載せています。

YOLO26で都市道路画像を画素単位に色分けした結果

Apple M1 Max の CPU で、PyTorch と ONNX Runtime の両方を実行できました。

backend / stage mean min max std dev
PyTorch preprocessing 0.93 ms 0.89 ms 1.04 ms 0.04 ms
PyTorch inference 28.83 ms 26.39 ms 30.31 ms 1.02 ms
PyTorch postprocessing 236.07 ms 233.19 ms 239.70 ms 1.67 ms
PyTorch wall time 266.00 ms 264.44 ms 270.02 ms 1.69 ms
ONNX preprocessing 1.01 ms 0.91 ms 1.24 ms 0.10 ms
ONNX inference 25.67 ms 24.32 ms 26.91 ms 0.88 ms
ONNX postprocessing 0.72 ms 0.60 ms 1.11 ms 0.15 ms
ONNX wall time 27.55 ms 26.06 ms 28.82 ms 0.95 ms

ONNX の推論本体は PyTorch の約0.89倍、全処理時間は約0.10倍でした。速度差の中心は後処理です。PyTorch は logits を元画像サイズへ拡大してから class ID を選びます。今回 export した ONNX は class ID を直接出力するため、後処理が短くなりました。

記事作成時に再実行すると、PyTorch の全処理は平均290.79 ms、ONNX は29.76 msでした。速度は実行ごとに変動しますが、約10倍の差と画素一致率99.3129%は再現しました。

画素とクラス別の一致

全画素の 99.3129% が同じ class ID、0.6871% が異なる class ID でした。予測された16クラスのデータは次のとおりです。

class PyTorch area ONNX area IoU
road 21.27% 21.22% 99.52%
sidewalk 10.38% 10.39% 98.48%
building 16.28% 16.30% 98.99%
wall 3.05% 3.05% 97.16%
fence 4.18% 4.17% 98.32%
pole 1.62% 1.61% 88.15%
traffic light 0.03% 0.04% 88.03%
traffic sign 0.29% 0.29% 93.30%
vegetation 26.52% 26.54% 98.85%
terrain 0.02% 0.02% 82.92%
sky 8.94% 8.97% 99.15%
person 0.90% 0.90% 96.20%
rider 0.21% 0.21% 94.61%
car 5.11% 5.12% 98.67%
motorcycle 0.74% 0.74% 95.68%
bicycle 0.44% 0.44% 94.24%

赤い部分が2経路で異なった画素です。大きな領域の内部より、物体の境界に集中しています。

PyTorchとONNXのclass IDが異なった画素を赤く示した画像

最初に失敗した比較

最初は rect を固定せず、画素一致率が98.9648%でした。PyTorch は最小限の padding、固定 shape の ONNX は640x640の paddingを使い、同じ imgsz=640 でも入力条件が揃っていませんでした。

両方を rect=False にすると99.3129%へ改善しました。backend を比べるときは、モデルだけでなく前処理も揃える必要があります。

検証環境は次のとおりです。

machine: MacBook Pro (Apple M1 Max, arm64)
OS: macOS 26.5.2
Python: 3.12.10
Ultralytics: 8.4.95
PyTorch: 2.13.0
ONNX: 1.22.0
ONNX Runtime: 1.27.0
OpenCV: 5.0.0
NumPy: 2.5.1
provider: CPUExecutionProvider

結果の考察

専門的な数値は上に載せたとおりですが、簡単に読むと次の3点です。

  1. 大きな領域はよく一致した

道路、建物、植生、空は IoU 98%以上でした。全体の見た目もほぼ同じです。差は細い pole、traffic light、terrain や、各領域の境界で相対的に大きくなりました。

  1. ONNX が速い主因は出力形式だった

推論本体の差は約3 msですが、後処理は約235 ms違いました。今回は ONNX が class ID map を直接返すためです。「ONNX なら常に10倍速い」という結果ではなく、この export と後処理を含む条件での結果です。

  1. 都市道路は分けられたが、遠いバスは取れなかった

道路、歩道、建物、空、人、車、自転車などは妥当な位置へ割り当てられました。一方、画像奥の小さなバスは bus になりませんでした。遠くて小さい物体には限界があります。

今回の入力は正解 mask のない生成画像1枚です。そのため、99.3129%は PyTorch と ONNX の一致率であり、予測の正解率ではありません。Cityscapes validation、実写、別画像、異なる解像度、MPS、CoreML、量子化、メモリ使用量は未検証です。

検証後の感想

ONNX へ変換しても見た目をほぼ保ちつつ、CPU で1枚約30 msまで短くなったのは良い結果でした。道路や歩道の領域をローカルで連続処理する用途には使いやすそうです。

一方で、速さの大部分が後処理の違いから来ている点は重要でした。backend の名前だけで性能を判断せず、前処理と出力形式まで確認する必要があります。次は実写の道路動画で、フレーム間の安定性と CoreML の速度も比べてみたいです。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?