スクショから局面解析！YOLOx将棋エンジンで詰み筋探索アプリを作った話

# TL;DR

将棋アプリのスクリーンショットから局面を読み取り、将棋エンジンに詰み筋を探索させるアプリを作成しました。

この記事では、作成したアプリの概要と技術的詳細について共有したいと思います。

https://tsumeshogi-loser.web.app/

# 背景: 詰将棋とけない😇

スマホアプリで詰将棋を解いていると、どうしても解けない局面に出会うことがあります。特に解答が付いていない場合、「本当に詰むのか」「どの手順が正解なのか」と気になってしまい、つい夜も眠れなくなることもあります。

理論上、人間の脳内で全ての指し手を探索すれば詰み筋を発見できるはずですが、実際には思考が凝り固まったりすることによって、詰み筋が発見できないことがあるかと思います。

このような課題を解決するため、将棋アプリのスクリーンショットから局面を読み取り、将棋エンジンに詰み筋を探索させるアプリを作成しました。

# アプリ概要

まず、アプリ名ですが、
詰将棋の答えが導けないときの哀れな気持ちに寄り添って「詰将棋敗北者Web」と命名しました😇

使い方は、
[詰将棋敗北者Web](https://tsumeshogi-loser.web.app/)で将棋のスクリーンショットを開くことによって詰み筋を確認することができます。

![スクリーンショット 2024-12-11 1.44.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422592/b0a575e1-cb04-ddac-e828-b7d570d5c780.png)

# システム構成・開発過程

アプリのシステム構成は以下のようになっています。
バックエンドサーバーは存在せず、本番環境は静的ホスティングのみで動いています。[^1]
機械学習モデルはオフライン機械学習で用意して、TensorFlow JSで動かしています。

[^1]: サーバー費用等を加味して、静的ホスティングだけで処理を完結させたかったためです。当アプリは、Firebaseの無料枠で動かしています。

![名称未設定ファイル.drawio (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422592/a60bb4b9-647a-58fe-9d2d-08f48e4fb171.png)

ざっくり説明しますと、
クラウド機械学習で将棋の局面を検出する学習済みモデルを作成し、それをTensorFlow JS経由で利用します。そして、検出した将棋の局面を将棋エンジンにインプットすることによって、詰み筋を求めます。

### 機械学習周りの処理

スクリーンショット画像から将棋の局面を検出するところでは、YOLOという深層学習アルゴリズムを使っています。

#### 学習データ生成

学習データは、[Label Studio](https://labelstud.io/)というOSSのラベリングツールを使い、人手で画像にラベルを貼ることにより、用意します。作成した学習データは全部で100画像ほどです。

Label Studioには、[学習済みモデルを使って、ラベルを貼る作業を支援する機能](https://labelstud.io/guide/labeling.html#Perform-ML-assisted-labeling-with-interactive-preannotations)があります。
当アプリの制作過程では、20画像ほどの学習データを作った時点で、学習済みモデルをクラウド機械学習によって用意し、ラベルを貼る作業を半自動化しました。

![スクリーンショット 2024-12-11 14.06.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422592/b032f37b-30e3-9ad2-91af-b335c39b5196.png)

YOLO + Label Studioでラベルを貼る作業を支援させるには、それ専用の機械学習サーバーを立てる必要があります。

Label Studioが公式で提供している[参考実装](https://github.com/HumanSignal/label-studio-ml-backend/blob/master/label_studio_ml/examples/yolo/README.md)がありますので、
当アプリの制作過程では、参考実装に学習済みモデル(PyTouchファイル)を組み入れることによって、
ラベル支援を実現しました。

#### クラウド機械学習

Label Studioから学習データをExportして、それを[Ultralytics HUB](https://hub.ultralytics.com/)にアップロードし、学習モデルを生成しました。

複数回学習を行いましたが、従量課金でかかった費用は5ドル以下でした。
(別途月額サブスク料20ドルかかりました)

無給で個人開発する上で25ドルかかるのは、やや痛ですが、
画面をポチポチするだけで学習済みモデルが手に入るので、開発者エクスぺリンスは非常によかったです。

また、さまざまな形式で学習モデルをエクスポートできるというのも魅力的でした。

エクポート可能な形式:

![スクリーンショット 2024-12-11 14.35.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422592/84f159c2-b704-0f30-f053-4a479188ec49.png)

メトリクスもWebから確認可能:

![スクリーンショット 2024-12-11 14.36.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422592/ab154a98-6b6d-4292-5118-acc784bb312e.png)

### 将棋エンジン

将棋エンジンには[やねうら王](https://yaneuraou.yaneu.com/)の[詰将棋エンジン](https://yaneuraou.yaneu.com/2020/12/29/yaneuraou-mate-solver/)を拝借させていただき、
詰み筋の探索を実現しました。

やねうら王自体にはC++が採用されいるようですが、当アプリではブラウザで処理を完結させたかったため、
やねうら王の詰将棋エンジンをWASMでビルドして、アプリに組み入れました。

また、WASM化のビルドには、以下の実装を参考にさせていただきました。

* https://github.com/mizar/YaneuraOu.wasm
* https://github.com/usumerican/yaneuraou-suisho-petite/
* https://github.com/usumerican/shogimate

### フロントエンド

フロントエンドは、[YOLO8をTensorflowJSで動かすオープンソースプロジェクト](https://github.com/Hyuto/yolov8-tfjs)にパッチを当てる指針で開発しました。

フロントエンド開発では、UIの実装を行い、
画面のコアなロジック部分では、学習済みモデルおよび詰将棋エンジンを呼び出すようにしています。

# 課題: 画像解析の精度 vs データ容量

当アプリには、YOLOによる画像解析に「精度面」と「データ容量の面」で課題があります。

まず、駒の認識ですが、YOLOという深層学習アルゴリズムを使っているため学習データに多数存在する駒表記しか認識できません。

* 認識できないものの例
  * 「王将」、「玉将」、「龍馬」、「龍」、2文字フォント全般、崩しが強い書体、etc
* 認識できるものの例(1文字フォントであれば大体いける)
  * 「玉」、「竜」、「馬」、成桂/成香の1文字フォント、etc
  * 「王」は学習データにはないが、「玉」と文字が似てるのでたまに認識できる

この認識精度の問題については、単に学習データを増やせば解決しそうな見込みがありますが、
学習データを増やすと、学習済みモデルのデータ容量が増えたり、詰将棋敗北者Webの画面が重くなったりするトレードオフがあります。

本職で機械学習エンジニアをやってる人であれば、
学習済みモデルを容量を抑えつつ、精度を向上させるノウハウがあるかもしれないですが、
私は非機械学習エンジニアなので、ちょっと厳しそうな感じです。

# おわりに

本記事では、将棋アプリのスクリーンショットから局面を読み取り、詰み筋を探索するアプリの開発過程について共有しました。このアプリは個人的な課題から着想を得たものであり、詰将棋を楽しむ多くの人々の役に立てることを願っています。

開発を進める中で、機械学習モデルの精度向上や計算負荷とのトレードオフ、フロントエンドの最適化など、さまざまな技術的課題に直面しました。
今後は[詰将棋敗北者Web](https://tsumeshogi-loser.web.app/
)をドッグフーディングすることによって、改善していきたいと考えています。