Markdownで表示

セマンティックセグメンテーション

セマンティックセグメンテーションは画像の各ピクセルにクラスを割り当て、同じクラスのインスタンス同士を区別しません。タスクキーはsemanticです。

定義

セマンティックセグメンテーションは物体ではなくピクセルにラベルを付けます。各ピクセルに1つのクラスIDを割り当てるため、画像内で2台の車が接していると、境界のない1つの車クラス領域になります。インスタンスを数えるのはインスタンスセグメンテーション、すべてのピクセルへラベルを付けながらインスタンスも分離するのはパノプティックセグメンテーションです。

semanticが標準タスクキーで、チェックポイントのファイル名にある-sem接尾辞が選択します。そのため、公開済みの重みを読み込むときにtask=は不要です。

predict()result.semantic_maskを設定します。.dataは元画像のキャンバス上の(H, W)整数クラスマップ、.classesは存在するIDを並べ替えたリスト、.class_mask(id)は1クラスを選択するブール値の(H, W)配列です。値255は無視ラベルです。クラスとして扱われず、損失と指標から除外され、.classesにも含まれません。

モデル

学習と推論の両方に対応するファミリーは3つです。SegFormerLingBot-VisionDINOv2です。SegFormerとLingBot-Visionは基本パッケージで実行でき、公開済みの重みがあります。DINOv2にはpip install "libreyolo[rfdetr]"が必要で、LibreYOLOがホストするチェックポイントはありません。アップストリームのバックボーンを読み込み、密なヘッドはランダム初期化から始まるため、すぐに使える推論器ではなく学習の出発点です。

さらに4つのファミリーが推論、検証、エクスポートに対応しますが、train()NotImplementedErrorを送出します。FCNDeepLabv3PIDNetEoMTです。

クラス集合はファミリーではなくチェックポイントごとに異なります。公開済みの重みは、ADE20Kの150クラスやCityscapesの19クラスなど、ほとんど共通点のないラベル空間を持つデータセットから得られています。何にラベルを付けられるかはチェックポイントのnamesで確認し、2つのチェックポイントを比較できるのは同じデータセットで学習した場合だけです。

推論

重みは初回使用時にHugging Faceからダウンロードされ、ローカルにキャッシュされます。

Python
from libreyolo import LibreYOLO, SAMPLE_IMAGE # ファイル名の-sem接尾辞がタスクを選択するためtask引数は不要model = LibreYOLO("LibreSegformerb0-sem.pt")result = model(SAMPLE_IMAGE, save=True) mask = result.semantic_maskprint(mask.data.shape)   # 元キャンバス上の(H, W)クラスIDprint(mask.classes)      # 255を除く存在クラスIDを並べ替えたもの
CLI
libreyolo predict model=LibreSegformerb0-sem.pt save=True \  source=https://raw.githubusercontent.com/LibreYOLO/libreyolo/release/libreyolo/assets/parkour.jpg
クラスごとに処理
from libreyolo import LibreYOLO, SAMPLE_IMAGE result = LibreYOLO("LibreSegformerb0-sem.pt")(SAMPLE_IMAGE)mask = result.semantic_mask for class_id in mask.classes:    pixels = mask.class_mask(class_id)   # boolean (H, W)    print(result.names[class_id], int(pixels.sum()))
別ファミリーでも同じ呼び出し
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibrePIDNets-sem.pt")result = model(SAMPLE_IMAGE) print(result.semantic_mask.data.shape)

マップはピクセルごとのargmaxなのでNMS処理がなく、iouは効果を持ちません。SegFormer、PIDNet、その他の密な予測器では、confmax_detをAPI互換性のため受け付けますが何もしません。EoMTは例外で、confがクエリ選択を絞り込みます。入力ソース、ストリーミング、結果の処理については推論を参照してください。

データセット形式

各画像は.txtラベルファイルではなく、密な単一チャンネルマスクと対応付けます。画像パス内のimagesをマスクディレクトリへ置き換えて検索します。

dataset/
  data.yaml
  images/
    train/000001.jpg
    val/000101.jpg
  masks/
    train/000001.png
    val/000101.png

マスクは通常PNGの可逆圧縮単一チャンネル画像です。パレットモードのPNGはパレットインデックスとして読み込まれます。各ピクセル値は0..nc-1範囲のクラスID、値255は無視を意味します。マスク解像度は対応する画像と一致する必要があります。

YAMLでは共通契約に加えて2つのキーを使用します。

yaml
path: dataset
train: images/train
val: images/val
masks_dir: masks
nc: 19
names:
  0: road
  1: sidewalk

masks_dirimagesの代わりに使うディレクトリ名で、デフォルトはmasksです。label_mappingは任意の{source_id: train_id}マッピングで、読み込み時にマスクのピクセル値へ適用されます。1から150の番号を使うデータセットを0から149へ変換する場合などに使用します。マッピングされていないソース値はすべて無視になり、各学習IDは0..nc-1範囲でなければなりません。

masks_dirを省略すると、ローダーはフォールバックへ切り替わります。通常のimagesからlabelsへの規約で解決したポリゴンラベルを読み込み時にラスタライズし、物体クラスの後にbackgroundクラスを追加するため、ncが1増えます。

標準ローダーはlibreyolo.data.SemanticDatasetです。

学習

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreSegformerb0-sem.pt")model.train(data="my-dataset.yaml", epochs=160, imgsz=512, batch=8)
CLI
libreyolo train model=LibreSegformerb0-sem.pt data=my-dataset.yaml \  epochs=160 imgsz=512 batch=8
ADE20Kで学習
# ade20k.yamlには約1 GBのアーカイブ用ダウンロードスクリプトが# 埋め込まれているためデータがローカルになければ明示的な許可が必要libreyolo train model=LibreSegformerb0-sem.pt data=ade20k.yaml \  epochs=160 imgsz=512 batch=8 allow_download_scripts=True

ここでのimgszには検出器にはない制約があります。各ファミリーはパッチグリッドまたは出力ストライドに基づく除数を宣言し、imgszが割り切れない場合は、学習と検証の両方で実行前にValueErrorを送出します。除数はSegFormerで32、LingBot-VisionとEoMTで16、DINOv2で14、FCNとPIDNetで8です。データセット、データ拡張、マルチGPU、ロガーについては学習を参照してください。

検証

val()は、データセットYAMLのvalで指定した分割に対して計算したmetrics/キーを持つ通常の辞書を返します。

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreSegformerb0-sem.pt") # val()はオブジェクトではなく通常のdictを返すmetrics = model.val(data="my-dataset.yaml") print(metrics["metrics/mIoU"])print(metrics["metrics/pixel_accuracy"])
CLI
libreyolo val model=LibreSegformerb0-sem.pt data=my-dataset.yaml

metrics/mIoUは平均Intersection over Unionです。各クラスについて予測ピクセルと正解ピクセルの共通部分を和集合で割り、クラス間で平均します。主要な数値であり、学習中の最良エポック選択にも使用されます。metrics/pixel_accuracyは正しいクラスを割り当てたピクセルの割合ですが、大きな背景クラスによって高く見える場合があるため、比較にはmIoUを使用してください。255と記されたピクセルはどちらの指標にも含まれません。辞書にはmIoU値のコピーであるfitnessも含まれます。

エクスポート

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreSegformerb0-sem.pt")model.export(format="onnx", imgsz=512)
CLI
libreyolo export model=LibreSegformerb0-sem.pt format=onnx imgsz=512
エクスポートしたファイルを使用
from libreyolo import LibreYOLO, SAMPLE_IMAGE # ファクトリはファイルの拡張子に応じて振り分けるためエクスポートした# アーティファクトもチェックポイントと同様に読み込まれ同じResultsオブジェクトを返すmodel = LibreYOLO("LibreSegformerb0-sem.onnx")result = model(SAMPLE_IMAGE) print(result.semantic_mask.data.shape)

エクスポートしたアーティファクトはファイルの拡張子に基づいてLibreYOLO()で再読み込みできるため、.onnx.engineファイルもチェックポイントと同様に動作し、同じResultsを返します。対応形式はファミリーごとに異なり、各モデルページのマトリックスは手入力ではなく検証済みの集合から生成されます。形式、追加パッケージ、制約についてはエクスポートとデプロイを参照してください。

LibreYOLO v1.5.0で検証済みです。