麻雀牌を画像分類する方法|YOLO検出後にEfficientNetで牌種類を判定する

EfficientNet

前回までのYOLO編では、カメラ画像から麻雀牌を検出するモデルを作ってきました。

今回からは、検出した牌が

「一萬なのか」
「五筒なのか」
「東なのか」

といった牌の種類を判定する画像分類を作っていきます。

画像分類にはEfficientNet-B0を使用します。

ここで最初に書いておきたいのが、

YOLOでも牌の位置と種類を同時に判定できる

ということです。

今回はYOLOで種類を判定できなかったからEfficientNetを追加したわけではありません。

あえて、

YOLOは牌の位置を検出する
EfficientNetは牌の種類を分類する

という役割分担にしています。

今回は、その構成にした理由と画像分類全体の流れを紹介します。


YOLOだけでも牌の種類は判定できる

YOLOは物体がある場所を見つけるだけのモデルではありません。

例えば37種類の麻雀牌をそれぞれクラスとして学習させれば、

この位置に五筒がある
この位置に東がある
この位置に赤五萬がある

というように、位置と牌の種類を一度に取得することもできます。

つまり、

カメラ画像
↓
YOLO
↓
位置+牌種類

という構成でも麻雀牌認識は作れます。

それでも今回の麻雀CPUでは、この方法にはしませんでした。

YOLOには牌がどこにあるのかだけを検出してもらい、牌の種類については別の画像分類モデルに任せています。


あえて検出と分類を分ける

現在の構成は次のようになっています。

カメラ画像
↓
YOLO
麻雀牌の位置を検出
↓
牌画像を1枚ずつ切り出す
↓
EfficientNet
牌の種類を分類
↓
牌IDを決定

YOLO側では、

「これは麻雀牌である」

というところまで担当します。

その牌が何なのかは、切り出した画像をEfficientNetに渡して判定します。

こうすることで、

物体を見つける処理

牌の模様を見分ける処理

を別々に改善できます。

例えば実際に使っていて「筒子の認識だけ間違えやすい」と分かった場合でも、YOLOを作り直す必要はありません。

画像分類側に学習データを追加して、EfficientNetだけを再学習できます。

実際の麻雀CPUを使いながら認識ミスを集め、少しずつ改善していく今回の使い方では、この構成の方が管理しやすいと考えました。


37種類をさらに二段階で分類する

今回の麻雀CPUでは、赤5も通常の5とは別の牌として扱っています。

そのため分類する牌は、

  • 萬子:1〜9+赤5
  • 筒子:1〜9+赤5
  • 索子:1〜9+赤5
  • 字牌:7種類

の合計37種類です。

EfficientNetで37種類を一度に分類することもできますが、ここでもさらに処理を分けています。

まずStage1で、

萬子
筒子
索子
字牌

の4種類に分類します。

例えば五筒なら、

五筒の画像
↓
Stage1
↓
筒子

となります。

次にStage2で、そのグループの中から具体的な牌を判定します。

筒子
↓
筒子用モデル
↓
五筒

つまり、

大分類 → 詳細分類

という二段階です。


なぜ37種類を一度に分類しないのか

麻雀牌には、萬子・筒子・索子・字牌それぞれに共通した特徴があります。

そこで最初から37種類すべてを候補にするのではなく、

まず4グループに絞る
↓
そのグループの中から判定する

という構成にしました。

Stage2のモデルも、

  • 萬子用
  • 筒子用
  • 索子用
  • 字牌用

に分かれています。

そのため、特定の種類だけ認識精度に問題があったときにも、どこを改善すればよいか分かりやすくなります。


認識ミスを集めて再学習する

画像分類モデルは、一度作って終わりではありません。

麻雀CPUを実際に使っていて認識を間違えた場合、その牌画像を保存します。

その後、人間が正しい牌を指定して再学習用のデータとして使用します。

麻雀CPUを使う
↓
認識ミスを保存
↓
正しい牌を設定
↓
EfficientNetを再学習
↓
認識精度を改善

実際に間違えた画像は、現在のモデルが苦手としている画像でもあります。

今回の画像分類編では、この学習データを作るところから順番に紹介していきます。


まとめ

今回のポイントは、

YOLOでは牌の種類を判定できないからEfficientNetを使うわけではない

ということです。

YOLOでも、

「どこに」「何の牌があるか」

を同時に判定できます。

それでも今回は、

YOLO
牌の位置を検出
↓
EfficientNet Stage1
萬子 / 筒子 / 索子 / 字牌
↓
EfficientNet Stage2
具体的な牌を分類

と役割を分けました。

検出と分類を独立させることで、実際に麻雀CPUを使いながら画像分類部分だけを再学習しやすくしています。

次回は、実際に麻雀CPUから保存した牌画像を確認し、

正しく認識できた画像と誤認識した画像を学習データとして整理する方法

を紹介します。


関連記事

コメント

タイトルとURLをコピーしました