📘

学マスで手持ちのサポカを最適にするためにYOLOv8触ってみた

2024/12/30に公開

この記事は「あらた界隈とそのまわりとそのまわりとそのまわり 訳: だれでも参加可能 なアドカレ 2024 ドキッ!?オタクだらけのアドベントカレンダー(完走するとは言っていない)」、通称あらた界隈 Advent Calendar 17日目の記事です(やけくそ)。

https://adventar.org/calendars/10239

やりたいこと

学園アイドルマスターというゲームのサポートカード計算機を作られた方がいます。

https://www.youtube.com/watch?v=_c6vv6P2V6M

これを使って最適なサポートカードを選んでいたんですが、おおまかに分けて2つの面倒な点がありました。

  • 各カードの上限解放数(凸数)を集計してスプレッドシートに入力する必要がある
  • 元のスプレッドシートが更新される度に複製する必要がある

これらの問題のうち、1つ目の問題を解消することを当面の目標にし、問題をざっくり次のようなステップに分けました。

そして、各ステップで使えそうな技術を考えました。

プロセス 具体的な使用技術
カードの枠を探す 物体検知(Object Detection)
クロッピング OpenCVでちゃちゃっと
カード分類 教師なし学習(SVM?)
凸数の認識 テンプレートマッチング

今回の記事では、1番目の物体検知をやってみることにします。

YOLOv8で物体検知をしてみる

YOLOとは

「You Only Look Once」の略称。「You Only Live Once」をもじっている。
2019年くらいにどっかで聞いてからずっと頭の片隅にいました。今回のことで使えそうだなと思ったので、使ってみることにしました。

手順

僕はpoetryを使っているので、poetryでいろいろ入れました。

$ poetry add label-studio ultralytics
$ poetry add jupyterlab # Jupyter Notebookでやりたい場合

まずはデータセットを用意します。僕は、実際に学マスのサポートカード一覧画面をスクリーンショットしたものを、label-studioでアノテーションしました。

撮ったスクリーンショット4枚のうち3枚を学習用、1枚を評価用にして、次のように配置しました。

datasets
├── gkmas_data
│   ├── classes.txt
│   ├── notes.json
│   ├── train
│   │   ├── images
│   │   │   └── (画像).PNG
│   │   └── labels
│   │       └── (アノテーション結果).txt
│   └── val
│       ├── images
│       │   └── (画像).PNG
│       └── labels
│           └── (アノテーション結果).txt
└── gkmas_data.yaml

次に、データセットのメタデータを用意します。
先ほどのファイル構造にあるgkmas_data.yamlを次のように編集します。

path: './gkmas_data' # 
train: 'train' # 学習用データ
val: 'val' # 評価用データ

nc: 1 # クラス数
names: ['card'] # クラス名の配列。複数クラスならば`classes.txt`に書かれている順番にする

これでデータの準備ができたので、次は学習をします。

from ultralytics import YOLO

model = YOLO('yolov8n.pt') # ベースとなるモデルの読み込み
model.train(data='./datasets/gkmas_data.yaml', epochs=50) # 学習

学習を行うと結果がptファイルで出てきます。

50 epochs completed in 0.045 hours.
Optimizer stripped from runs/detect/train/weights/last.pt, 6.2MB
Optimizer stripped from runs/detect/train/weights/best.pt, 6.2MB

このファイルパスの先にあるptファイルで、推論をさせてみます。

model = YOLO('runs/detect/train/weights/best.pt')
result = model.predict('<推論させたい画像のファイルパス>', save=True, conf=0.1)

すると結果がpngファイルとして出てきます。

image 1/1 <画像のファイルパス>: 640x320 15 cards, 100.8ms
Speed: 3.0ms preprocess, 100.8ms inference, 0.9ms postprocess per image at shape (1, 3, 640, 320)
Results saved to runs/detect/predict

見に行ったら、ちゃんと推論できてそうな感じになってました。

感想

こんなてきとうにやってもぱってできるもんなんですね。もっと早くやればよかった。
画像処理まわりは来年から色々触れる気がしているので、いい体験になったと思います。

Discussion