機械学習
記事内に商品プロモーションを含む場合があります

物体検出のアノテーションで楽する方法(YOLOv8+labelImg)

tadanori

物体検出のアノテーションって面倒です。これを少しだけ楽にする方法をここでは紹介したいと思います。なお、新規に枠をつけるより、修正の方が楽という前提での手順になります。

※この記事のやり方は、YOLOv8以外にも応用することができます。

記事の概要

具体的には、以下の手順でアノテーションを行うことで作業量を減らします。

  1. 少ない枚数のアノテーションを行う
  2. アノテーションしたデータで学習して、アノテーションしていないデータを推論する
  3. 推論結果を修正して学習データに追加
YOLOv8用のアノテーションデータを作成したい場合はこちら

アノテーションは面倒

物体検出のアノテーション作業ってかなり面倒です。自分はlabelImgというツールを使ってアノテーションしていますが、画像を見ながら枠をつけていく作業、枚数が増えるとかなり大変です。

もっと楽なツールがないかと他のツールも使ってみましたが、どれも似たり寄ったりです(結局、labelImgが軽くて使いやすいのでこれを使っています)。

動画の場合は、似通った画像が続くので、前フレームの結果を参照してアノテーションすることで作業が楽になります。実際、この機能を持ったツールもあります。ただ、動画の連続した画像=似た画像→学習データとしてどうなの?ということで動画から学習させる場合は、間引いてデータにするのでこの機能結局使えません。

とにかく、枠をつける作業は大変です。

「なるべく楽をしたい」ということで考えた方法が今回の記事の内容になります。

アノテーションを楽にする方法

ざっくりとした流れです。

  1. 少ない数のデータ(学習データの一部)にアノテーションを実施(labelImgを想定)
  2. アノテーションしたデータを使って学習(YOLOv8)
  3. アノテーションしていない画像に対して推論(YOLOv8)
  4. 出力された結果をアノテーションツール(labelImg)で補正
全体の流れ

まず、データを学習用とそれ以外に分割します。学習用はまずは少ない枚数です。ここで少ない枚数に対してアノテーション(labelImg)を行ってYOLOv8で学習します。次に学習したモデルで学習に使わなかった画像の物体検出を行い、枠情報を生成します。この予測結果をアノテーションツールで修正することで学習データを新たに作成する、これが手順になります。

数が多い場合は、データを変えて②③④を繰り返すと、精度が上がっていって修正が少なくなっていくので手間を減らすには良いかもしれません。ただ、学習のたびに時間がかかります。

この方法だと、ちゃんと推論できている画像についてはアノテーションツールでの確認だけで済むし、少しずれた枠の修正は新しく枠を追加するより楽なので、作業量が一気に減ります。

だいぶ楽なのでぜひ試してみてください。

YOLOv8を利用していますが、アノテーションのサポートとして利用しているだけなので、他の検出モデル用のアノテーションにもここで書いたテクニックを使うことは可能です。

その場合は、アノテーション結果をYOLOフォーマットからターゲットのモデルの入力フォーマットに変換する必要があります。

YOLOをコマンドラインで使う方法(物体検出)

以下、アノテーションデータの作成をYOLOv8と、labelImgを使って行う場合のそれぞれのツールの使い方について説明します。

yolov8のインストール

python環境が入っていれば以下のコマンドを実行するだけでインストールされます。yoloコマンドが入っていればインストール完了です。

pip install ultralytics

インストールされていれば、yoloコマンドを実行すると以下のように出力されます。

> yolo

Arguments received: ['yolo']. Ultralytics 'yolo' commands use the following syntax:

    yolo TASK MODE ARGS

    Where   TASK (optional) is one of ('detect', 'segment', 'classify', 'pose')
            MODE (required) is one of ('train', 'val', 'predict', 'export', 'track', 'benchmark')
            ARGS (optional) are any number of custom 'arg=value' pairs like 'imgsz=320' that override defaults.
                See all ARGS at https://docs.ultralytics.com/usage/cfg or with 'yolo cfg'

1. Train a detection model for 10 epochs with an initial learning_rate of 0.01
    yolo train data=coco128.yaml model=yolov8n.pt epochs=10 lr0=0.01

2. Predict a YouTube video using a pretrained segmentation model at image size 320:
    yolo predict model=yolov8n-seg.pt source='https://youtu.be/Zgi9g1ksQHc' imgsz=320

3. Val a pretrained detection model at batch-size 1 and image size 640:
    yolo val model=yolov8n.pt data=coco128.yaml batch=1 imgsz=640

4. Export a YOLOv8n classification model to ONNX format at image size 224 by 128 (no TASK required)
    yolo export model=yolov8n-cls.pt format=onnx imgsz=224,128

5. Run special commands:
    yolo help
    yolo checks
    yolo version
    yolo settings
    yolo copy-cfg
    yolo cfg

Docs: https://docs.ultralytics.com
Community: https://community.ultralytics.com
GitHub: https://github.com/ultralytics/ultralytics

使い方の詳細は以下のリンクを参照してください

ドキュメント: https://docs.ultralytics.com/

CLIの使い方https://docs.ultralytics.com/usage/cli/

オプションの説明https://docs.ultralytics.com/usage/cfg/

yolov8で学習

学習済みモデルをyolo8n.pt、データセットの定義をdataset.yamlとして準備している場合、以下のコマンドで学習できます。なお、epochsimgszは適当に変更してください。とりあえず、ここでは公式のページと同じ値で設定しました。

初期の学習モデルは、YOLOv8の公式ページにありますので、そちらをダウンロードしてください。

yolo detect train data=dataset.yaml model=yolov8n.pt epochs=100 imgsz=640

GPUで実行されない場合は、device=0などのオプションをつけてください。ちなみに、m1 Macの場合は、device="mps"とするとGPU処理になります。

dataset.yamlは例えば、以下のようになります。パスは、相対パスの場合、datasets以下のフォルダになるようです。パス(path)設定がうまくできない場合は、絶対パスで指定してみてください

# Path
path: ./cats
train: images/train
val: images/valid

# Classes
nc: 1
names: ['cat']

trainはトレーニング画像、valは検証用の画像です。./catsフォルダの構成は以下のようになります。コマンドでは指定していませんが、学習にはlabelsフォルダ画像に対応したアノテーションデータが必要となります(画像データがtest.jpgだとすると、labelsにはYOLOフォーマットのtest.txtが必要となります)。

./cats/images
             /train
             /valid
        / labels
             /train
             /valid

上記のサンプルのyamlファイルでは、クラス数ncは1、クラス名はcatになります。2クラスでdog, catの場合は、以下のようになります。

nc: 2
names: ['dog', 'cat']

実行すると結果がruns/detect/trainxxフォルダに記録されます(xxは、train2, train3のように数字が入ります)。

yolov8で推論し、結果を保存する

ここでは、画像データがsampleフォルダにある前提で説明します。推論を行う場合は以下のコマンドを実行します。モデルは、トレーニングした結果のモデルを指定してください。yolov8で学習を行った場合は、./runs/detect/train/weights/best.ptが学習結果のモデルです(何度も実行した場合は、trainxxと番号がついています)。save_txt=Trueを設定することでYOLO形式で結果が保存されます。

結果は、run/detect/predictフォルダにlabelsという形で保存されます。

yolo detect predict model=モデル source='sample' save_txt=True

推定をアノテーションに利用する場合は、結果画像は必要ありませんので、save=Falseと指定すれば出力データがテキストだけになり、ディスク容量を節約できます。この場合のコマンドは以下の通りです。

yolo detect predict model=モデル source='sample' save_txt=True save=False

推定結果を見ながら修正する(labelImg)

画像が./sampleに、推論した出力が./runs/detect/predict/labelsにある場合で説明します。

まず、classes.txtを作る必要があります。labelImg起動時のコマンドラインのオプションで指定できるはずですが、自分の環境ではなぜかうまく動作しません。./runs/detect/predict/labelsフォルダに置くのが確実みたいですので、このフォルダにclasses.txtを作成して配置します。

classes.txtは、クラス名を羅列したファイルになります。nc=1, names=[‘cat’]で学習させたので、クラス名はcatだけになります。この場合、classes.txtは以下のように1行だけになります。

cat

ファイルが準備できたら、以下のコマンドでlabelimgを立ち上げます。

labelImg ./sample ./runs/detect/predict/labels/classes.txt ./runs/detect/predict/labels

これで、labelImgが立ち上がりますので、結果を見ながら必要な箇所の修正をしていきます。修正の前に、「自動で保存する」をチェックしておくと楽かもしれません。

labelImgのメニュー

修正が完了したらlabelImgを終了し、画像とラベルを、学習用のデータとして追加します。

なお、新しくラベル付したデータは、全てtrain加えても、train/validに分割して加えても良いです

何度も繰り返す場合は、修正が必要だったものだけtrainデータに加えるというやり方もありです修正が必要だったということは、そのデータに対して学習できていないということです。なので、学習に加えればバリエーションの増加が期待できます。一方、修正が必要ないものは既存の学習データで既に習得済みと考えることもできます

学習データセットを変えると、学習結果も変化するので、修正が必要だったやつだけ入れるのが正解かどうかはわからないです。ここはやっぱり試行錯誤かなと思います。

まとめ

アノテーションの大変さを少しでも減らす方法として、一部だけアノテーションして学習・推論し、推論結果の間違いを修正して再び学習させるという方法について説明しました。

ツールによっては、これをサポートしているものもあるのですが、モデルが固定されていたり、モデルは入れ替えられても手順が面倒だったりします。

ここで紹介したやり方は、自身の作成したモデルの出力を使うので、どんなモデルでも行うことができますし応用性が高いと思います。

大量のアノテーションに疲れている人は、ぜひトライしてみてください。

おすすめ書籍

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

記事URLをコピーしました