Markdownで表示

点検出

点検出はバウンディングボックスの代わりに、物体ごとに1つのx、y位置を返します。LibreYOLOではpointタスクとして提供され、推論結果は物体ごとにx、y、クラス、信頼度を1行に保持します。

定義

pointタスクは幅、高さ、マスクを持たず、1つのx、y座標とクラスで各物体の位置を特定します。推論結果は物体の平坦なリストなので、その行数が物体数になります。この性質によりカウント用のタスクとして使えます。

推論結果ではresult.pointsに値が格納されます。これは元画像のピクセル単位でx, y, class, confidenceを各行に持つ(N, 4)配列をラップしたPointsペイロードです。.xyは座標、.xynは画像サイズで割った同じ座標、.clsはクラスインデックス、.confはスコアを返し、len()は点の数を返します。result.boxesは空のままなので、ioumax_detが作用する対象はありません。

モデル

pointには3つのファミリーが対応し、相互に置き換えられるものではありません。

FOMOは固定ボキャブラリーの選択肢です。低解像度グリッドの各セルを背景または物体中心として分類するグリッド分類器です。LibreYOLOで学習できる唯一の点検出ファミリーであり、エクスポートできる唯一のファミリーでもあります。

LocateAnythingはクラスインデックスの代わりにテキストを受け取るため、ボキャブラリーは入力した任意のフレーズになります。vlm追加パッケージが必要で、LibreYOLO()ファクトリではなくLibreLocateAnythingとして構築します。重みは非商用利用に制限されています。正確な条件と、チェックポイントが組み合わせるさらに2つのライセンスはモデルページに記載されています。

SenseNova-Visionは、他の6タスクでも使う同じプロンプト生成チェックポイントを通してpointに対応し、LibreVLM("sensenova-vision", task="point")で読み込みます。sensenova追加パッケージが必要です。推論ごとに7Bモデルの生成処理を実行するため、専用検出器より画像ごとのレイテンシが明らかに長くなります。重みは非商用で、ライセンスはモデルページに記載されています。

推論

このサイトでLibreFOMOの重みだけは自動ダウンロードの例外です。LibreYOLO("LibreFOMOs-point.pt")はディスク上のファイルを探し、取得せずファイル名を示すValueErrorを送出します。先にHugging FaceのLibreYOLO組織からチェックポイントをダウンロードし、ローカルパスで読み込むか、独自に学習してください。

点を推論して数える
from libreyolo import LibreYOLO, SAMPLE_IMAGE # LibreFOMOの重みは自動ダウンロードされない# https://huggingface.co/LibreYOLOから先に取得しローカルパスで読み込むmodel = LibreYOLO("./LibreFOMOs-point.pt")result = model(SAMPLE_IMAGE, save=True) points = result.pointsprint(len(points))     # 物体数print(points.xy)       # 元画像のピクセル単位の(N, 2)中心座標print(points.cls, points.conf)
正規化座標とクラスごとの個数
from collections import Counter from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("./LibreFOMOs-point.pt")result = model(SAMPLE_IMAGE) points = result.points.numpy()print(points.xyn)                          # [0, 1]範囲の同じ中心座標print(Counter(points.cls.astype(int).tolist()))

ローダーが認識するにはファイル名に-pointタスク接尾辞が必要です。predict(..., nms_radius=1)は、FOMOの2つの検出を両方残すために必要なグリッドセル間の距離を制御します。入力ソース、ストリーミング、結果の処理については推論を参照してください。

データセット形式

pointに固有のラベル形式はありません。点検出ファミリーは標準のYOLO検出レイアウトを読み取り、各ボックス行から1つの中心を導出します。そのためcx cyが点になり、w hは行が有効かどうかの判定にだけ使われます。

dataset/
  data.yaml
  images/
    train/scene.jpg
    val/scene.jpg
  labels/
    train/scene.txt
    val/scene.txt

各ラベルファイルには物体ごとに1行の正規化座標を記述します。

<class_id> <cx> <cy> <w> <h>
yaml
path: dataset
train: images/train
val: images/val
nc: 1
names: {0: seedling}

ラベルファイルが存在しないか空の場合、その画像に物体がないことを意味します。完全な契約についてはデータセット形式を参照してください。

学習

学習実装を持つ点検出ファミリーはFOMOだけです。LocateAnythingとSenseNova-Visionのtrain()NotImplementedErrorを送出します。これらはアップストリームでファインチューニングし、その結果を読み込んでください。

YOLOデータセットでFOMOを学習
from libreyolo import LibreYOLO model = LibreYOLO("./LibreFOMOs-point.pt")model.train(data="my-dataset.yaml", epochs=40, batch=32, lr0=3e-4)
学習済みチェックポイントで推論
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("./LibreFOMOs-point.pt")results = model.train(data="my-dataset.yaml", epochs=40) # train()は同じオブジェクトへ最良チェックポイントを再読み込みするため# 呼び出しが戻った時点で学習済みの重みを使って推論するprint(results["best_checkpoint"])print(model(SAMPLE_IMAGE).points.xy)

FOMOのimgszは自由に選べません。デフォルトは読み込んだチェックポイントのネイティブ解像度で、別の値を渡すと期待されるサイズを示すValueErrorを送出します。データセット、ロガー、マルチGPUについては学習、このファミリーのデフォルト値についてはFOMOページを参照してください。

検証

val()は距離しきい値を変えて、予測点と正解点をハンガリアン法で1対1に対応付けます。しきい値は正規化画像座標におけるユークリッド距離で、デフォルトの探索範囲は0.01から0.10までの10個の値です。

検証して指標キーを確認
from libreyolo import LibreYOLO model = LibreYOLO("./LibreFOMOs-point.pt")metrics = model.val(data="my-dataset.yaml") print(metrics["metrics/precision"], metrics["metrics/recall"])print(metrics["metrics/f1"])print(metrics["metrics/mAP@[0.01:0.10]"])   # fitnessprint(metrics["metrics/MLE"])               # 平均位置誤差print(metrics["metrics/MAE"], metrics["metrics/RMSE"])   # 個数の誤差
距離しきい値を変更
from libreyolo import LibreYOLO model = LibreYOLO("./LibreFOMOs-point.pt") # 探索範囲の境界がキー文字列の一部なので# カスタム探索では生成するmAPキーの名前も変わるmetrics = model.val(data="my-dataset.yaml", dist_thresholds=[0.02, 0.05]) print(metrics["metrics/mAP@0.02"])print(metrics["metrics/mAP@[0.02:0.05]"])

metrics/precisionmetrics/recallmetrics/f1は、探索範囲で最も厳しいしきい値(デフォルトは0.01)においてクラス間でマクロ平均した値です。metrics/mAP@0.01は同じしきい値での平均適合率、metrics/mAP@[0.01:0.10]は探索範囲全体の平均です。この探索範囲の値は、最良チェックポイントの選択で使うfitnessにもなります。どちらのmAPキーも使用するしきい値から構築されるため、dist_thresholds=を渡すと名前が変わります。

metrics/MLEは最も厳しいしきい値で対応したペア間の平均距離で、同じ正規化単位を使います。metrics/MAEmetrics/RMSEは位置ではなく個数の指標で、画像ごとの予測点数と正解点数の差を測定します。

FOMOはこれらに加えてグリッド単位の第2の指標群を追加します。信頼度とnms_radiusを変えて探索し、F1が最良となる組み合わせをmetrics/grid_F1metrics/grid_precisionmetrics/grid_recallmetrics/grid_mean_distancemetrics/grid_TPmetrics/grid_FPmetrics/grid_FNとして公開します。そのときの設定はdecode/thresholddecode/nms_radiusに記録されます。

エクスポート

FOMOは共通のエクスポート経路を使用します。エクスポートしたアーティファクトはファイルの拡張子に基づいてLibreYOLO()で再読み込みできるため、.onnx.engineファイルもチェックポイントと同様に動作し、同じResultsを返します。

エクスポート
from libreyolo import LibreYOLO model = LibreYOLO("./LibreFOMOs-point.pt")model.export(format="onnx")
エクスポートしたファイルを実行
from libreyolo import LibreYOLO, SAMPLE_IMAGE # ファクトリはファイルの拡張子に応じて振り分けるためエクスポートした# アーティファクトもチェックポイントと同様に読み込まれ同じResultsオブジェクトを返すmodel = LibreYOLO("./LibreFOMOs-point.onnx")result = model(SAMPLE_IMAGE) print(result.points.xy)

形式ごとの対応範囲はFOMOページ完全なエクスポートマトリックスに記載されています。LocateAnythingとSenseNova-Visionはエクスポートできません。生成モデルにはトレース可能な検出グラフがないため、どちらもexport()が例外を送出します。

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