😀

ランダムフォレストを用いたテトリスの盤面画像の認識

に公開

テトリス Advent Calendar 2025 4日目の記事です。

今回は、テトリスの盤面認識をいかに楽で高精度で低負荷に行えるか、実験をしてみたのでそれをまとめました。

盤面画像をテト譜に起こす方法は、シンプルな条件分岐からニューラルネットワークを使うなど様々な手法が考えられると思います。
例えば、一番シンプルな方法はミノ画像の平均色を取りその色情報を条件分岐で分けていく方法でしょう。実際、この方法でも十分な精度を出すことができます。ただ、 人力で条件分岐を書きたくないですよね。

そこで、今回は基本的な方策は上記の通りで、条件分岐を自動化することに重点を置いた手法を提案します。

今回手法を提案していく上で、次のように条件を設定します。

  1. エフェクト部分の誤差は許容できる。
  2. ミノの色は単色に近く他のミノとかぶっていない。
  3. ミノ画像の種類(TETR.IOやぷよテトなど)は同じもの。
    → もし実際にアプリに組み込む場合はユーザーがどのモデルを使うか選択する必要がある。

3番目に関して、当初ユーザーに選択させるべきではないと思いニューラルネットワークなどを考えましたが、それぐらい選んでくれ…ということで妥協。

ということで、条件分岐を自動で作成してくれるアルゴリズム、決定木(今回は一応ランダムフォレスト)を用いた手法を提案します。

決定木・ランダムフォレストについて

決定木は、この画像を見たらなんとなくわかると思いますが、フローチャートのように条件分岐を繰り返して分類するというものです。a

これらの条件分岐はアルゴリズムが自動的に作ります。
そして、今回の問題に対してすごく適任そうです。
今回はランダムフォレストというアルゴリズムを用います。これは、決定木を複数組み合わせて多数決を取ることで局所解に陥りにくくするといったものです。
正直今回は決定木で十分な気がしていますが、JavaScriptのライブラリの都合で限りなく決定木に近いパラメータになったランダムフォレストを用いました。

提案するアルゴリズム

全体の流れとしては以下の通りです。

  1. ブロックごとの画像を切り抜く
  2. それぞれのブロックを、中心を基準に縦横半分にする
  3. ブロックのピクセルの色RGBの平均を求める
  4. HSVに変換する(Hはsinを用いる)
  5. HSVの情報を用いてランダムフォレストで学習、推論

一つずつ解説していきます。

1. ブロック画像切り抜き

まずは、盤面画像をそれぞれのブロック画像に切り抜きます。多少ズレて隣のブロックが入り込んでも大丈夫です。

2. ブロック画像縮小

先ほどブロック画像を切り抜いた際、ズレなどにより余計な情報が入っていることはあります。そのため、縦横それぞれ長さを半分にします。

3. 平均色を求める

それぞれのピクセルの色を取り平均を求めます。

4.

RGBでは今回解決する問題の形式に適していないため、HSVに変換します。
HSVを簡単に説明すると、RGBは赤緑青の色の成分量で最終的な色を決定するのに対して、HSVは色の種類・色の派手さ・色の明るさで決めるというものです。詳しくは調べてください。
この際注意してほしいのが、Hueは360度で一周するということです。0度と359度は実際はほぼ同じ値ですが、その差は大きく異なってしまいます。

そこで、三角関数を用います。
sin(0°) = 0sin(359°) = -0.017でこの問題を解決できます。

--- 追記
この方法だとsin(30°) とsin(150°)が同じ値になってしまいます。
当初このまま実装した際、思いのほか決定木がいい感じに分類してくれたので影響はなかったのですが、実装する際には0~360°を0~180°に圧縮する、h_cosをパラメータに追加するなどの対応をする必要があります。 ---

これによりミノ画像をh,s,v 3つの特徴量に変換することができました。
後はこの3つの特徴量で学習させるだけです。

訓練データ

クラス データ数
empty 268
garbage 41
I 13
J 7
L 22
O 12
S 7
T 6
z 18

シンプル機械学習のため、このデータ数で十分学習することができました。

まとめ

今回の手法では、当初目標としていたパラメータの決定を自動化するという点において有効的であることが分かりました。
決定木やランダムフォレストのライブラリさえあればかなり手軽に作ることが出来るのでぜひやってみてください。

(これは、fumen-rsという譜面検討ソフトに実際に実装しています。
学習や推論、モデルの読み書きなど実際に動く様子はこのソフトから確認することができます。)

Discussion