Apex Legendsの「トラッカー(成績)」画面のスクリーンショットをOCR(EasyOCR)で読み取り、シーズンごとの各種スタッツをCSVへ集計。さらにHTMLダッシュボードで推移をグラフ表示するツール。
注記: 本ツールはApex Legendsのファンメイドの非公式ツールであり、Electronic Arts Inc. / Respawn Entertainmentとは一切関係ありません。ゲーム画面のUIレイアウトが変更された場合、
config.jsonの座標がずれてOCRが正しく機能しなくなることがあります。
- 非公式APIやEAサーバーへの通信に依存しない: スクリーンショットの画像処理のみで完結するため、APIの仕様変更による突然の機能停止や、非公式API利用に伴うアカウントリスクがない
- 完全ローカル動作: 統計データは手元のPCにのみ保存され、外部サービスへ送信されることはない
- サーバー不要のダッシュボード: 生成されるHTMLは
apex_dashboard_latest.htmlをブラウザで開くだけで動作し、ホスティングやビルド手順が不要
apex_dashboard.html にCSVを読み込んだ際の表示例(サンプルデータ)。
- Python 3.10以上を推奨(開発・動作確認はPython 3.14.6)
- requirements.txt に記載の依存パッケージ(
opencv-python,easyocr,pandas)
pip install -r requirements.txt既にPython環境を他の用途で使っている場合は、依存パッケージの衝突を避けるため仮想環境(venv)の利用を推奨します。
python -m venv venv
venv\Scripts\activate
pip install -r requirements.txt- インターネット接続が必要(
main.py初回実行時、EasyOCRが認識モデルをネット経由でダウンロードするため。社内プロキシ・オフライン環境では失敗する) - 1920x1080・英語UIの成績画面を前提(
config.jsonのregions座標は解像度に応じてスケーリングされるが、アスペクト比やUI言語が異なると数値を正しく切り出せない場合がある)
- GitHubのリポジトリページを開く
- 緑色の「Code」ボタンをクリックし、「Download ZIP」を選択する
- ダウンロードした
ApexStatsOCR-main.zipを右クリック→「すべて展開」で好きな場所に展開する(以降、展開してできたフォルダを\ApexStatsOCRとして説明する)
-
コマンドプロンプトを起動する
- スタートメニューで「コマンドプロンプト」または「cmd」と検索して起動する
- もしくは
Win + Rキーを押し、cmdと入力してEnter
-
cdコマンドでApexStatsOCRフォルダへ移動する(保存場所が異なる場合は読み替える)cd \ApexStatsOCR
-
Pythonがインストールされているか確認する
python --version
バージョンが表示されない場合はPythonが未インストール。Python公式サイトからPython 3.10以上をインストールし、インストーラの「Add python.exe to PATH」にチェックを入れる
-
依存パッケージをインストールする
pip install -r requirements.txt
既に別の用途でPython環境を使っている場合は、依存パッケージの衝突を避けるため仮想環境(venv)の利用を推奨(詳細は動作要件を参照)
うまくいかない場合はトラブルシューティングを参照
-
Apex Legendsを起動する
-
Apex各シーズン毎のランク成績画面を開く
-
スクリーンショットを撮影する
注記: 以下はWindowsでの取得例。Windowsのバージョンやアップデートにより操作方法が変わることがあるため、最新の手順はMicrosoft公式サポートサイトで確認すること。
方法 操作 保存先 Win + PrtScn画面全体を撮影する 自動保存( ピクチャ\Screenshots)Win + Alt + PrtScn(Xbox Game Bar)アクティブウィンドウ(ゲーム画面)を撮影する。フルスクリーン専有モードで Win + PrtScnが効かない場合はこちら自動保存( ビデオ\Captures)Win + Shift + S(Snipping Tool)範囲・ウィンドウ・全画面を選択して撮影する クリップボードのみ(要貼り付け・保存) Alt + PrtScnアクティブウィンドウのみ撮影する クリップボードのみ(要貼り付け・保存) - ノートPCなどで
PrtScn単体のキーが反応しない場合はFnキーを併用する(例:Win + Fn + PrtScn) - サンプル画像のように、ゲーム画面全体が写るように撮影すること
- ノートPCなどで
-
撮影した画像(自動保存の場合は
ピクチャ\Screenshotsまたはビデオ\Capturesフォルダ、クリップボードの場合はペイント等に貼り付けて保存したファイル)のファイル名をシーズン番号.pngに変更する(例:15.png) -
上記ファイルを以下へ保存する:
\ApexStatsOCR\input\ -
2~5の作業を対象シーズン分繰り返す
-
手順2で開いたコマンドプロンプトで(閉じてしまった場合は再度開いて
ApexStatsOCRへ移動)、以下を実行するpython main.py
-
\ApexStatsOCR\output\apex_stats.csvにデータが作成される -
作成したCSVを埋め込んだダッシュボードがデフォルトブラウザで自動的に開く(
apex_dashboard_latest.htmlが生成される) -
\ApexStatsOCR\ocr.logを開き、WARNINGの行が無いか確認する2026-09-08 21:00:00 WARNING 異常値検出: 3件の疑わしい値を検出しました(要目視確認)問題が無ければ
異常値検出: 問題ありませんとだけ記録される。WARNINGがあった場合は、該当シーズンの元画像を目視確認した上で、必要なら訂正を記録する(詳細は異常値の自動検出・異常値の訂正を記録するを参照) -
うまくいかない場合はトラブルシューティングを参照
- 自動オープンが不要な場合は
config.jsonのdashboard.auto_openをfalseにする。その場合や、過去に生成した別のCSVを見たい場合は、apex_dashboard.htmlを直接起動し画面上部のファイル選択ボタンから該当のCSVを選ぶ(従来通りの手動運用) - 実行のたびに
apex_dashboard_latest.htmlは上書きされ、ブラウザには新しいタブが開かれる(既存タブは自動では閉じない)。設定の詳細はdocs/config.mdを参照 input/が空のまま実行してもエラーにはならず、ヘッダーのみの空CSVが生成される(一見動いていないように見えるだけなので注意)- 実行のたびに
apex_stats_<タイムスタンプ>.csvがoutput/に追加され、自動削除はされない。不要になったら手動で削除すること
| 症状 | 原因・対処法 |
|---|---|
コマンドプロンプトでpythonが「認識されていません」と表示される |
Pythonがインストールされていないか、PATHが通っていない。Pythonを再インストールし、インストーラで「Add python.exe to PATH」にチェックを入れる |
pip install -r requirements.txt が失敗する |
ネットワーク接続を確認する。社内プロキシ・オフライン環境の場合は接続可能な環境で実行するか、プロキシ設定を行う。それでも失敗する場合はエラーメッセージ末尾の内容を確認する |
python main.py 実行時に、モデルのダウンロードに関するエラーで止まる |
初回実行時、EasyOCRが認識モデルをインターネット経由でダウンロードするために発生。オフライン・社内プロキシ環境では失敗する。インターネットに接続できる環境で一度実行し、モデルをダウンロードさせる |
apex_stats.csv が作成されるが中身がヘッダーだけで空 |
input/ フォルダに画像が入っていない。手順3に従って画像を配置してから再実行する |
| CSVの数値がおかしい・OCRが正しく読み取れていない | 成績画面の解像度が1920x1080以外、またはUI言語が英語以外の可能性がある。config.jsonのregions座標(対応表)は解像度に応じてスケーリングされるが、アスペクト比やUI言語が異なると正しく切り出せない場合がある |
| その他、上記に当てはまらない不具合 | \ApexStatsOCR\ocr.log の内容を添えてGitHub Issuesへ報告してください |
main.py はCSV出力後、以下の3種類のルールで異常値を自動検出し、疑わしい値があれば ocr.log に WARNING として出力する(ネットワーク通信は行わないため、EasyOCRの初回モデルダウンロード以外はオフラインで完結する)。アルゴリズムの詳細はdocs/anomaly-detection.mdを参照。
| ルール | 対象列 | 検出内容 |
|---|---|---|
| 型チェック | 全列 | OCR変換に失敗し文字列のまま残っている値 |
| 単調性チェック | career_*の累積カウンタ列(比率列は対象外) |
シーズン順で値が前より減っている |
| 統計的外れ値検知 | season_*列 |
列内の他シーズンと比べて統計的に外れた値(中央値絶対偏差ベース) |
閾値は config.json の anomaly_detection.mad_z_threshold で調整できる。検出された異常値は自動修正されない(統計的な推測だけでCSVを書き換えることはしない、という意味。目視確認済みの訂正をcorrections.jsonに記録すれば次回実行時から自動で反映される。詳細は異常値の訂正を記録するを参照)。
統計的外れ値として検出された値については、小数点の桁ズレを想定した「修正候補」を各異常値の行に併記する(算出方法はdocs/anomaly-detection.mdを参照)。「要目視確認」の注記はサマリ行にまとめて出力される。
異常値検出: 3件の疑わしい値を検出しました(要目視確認)
season=9 column=season_kdr value=44.0 rule=statistical_outlier suggested_value=0.44
統計的外れ値についてcorrections.jsonへ貼り付け可能なJSONを出力します("要目視確認"の値は元画像を目視確認した上で書き換えてください):
{
"9": {
"season_kdr": {
"observed": 44.0,
"corrected": 0.44
}
}
}
修正候補はあくまで統計的な推測であり、正しさは保証されない。CSVを自動修正することはないため、必ず \ApexStatsOCR\input\シーズン番号.png で元画像を目視確認した上で、正しい値を異常値の訂正を記録するの手順でcorrections.jsonに記録すること(output/配下のCSVを直接書き換えても、次回実行時のOCR結果で上書きされるため注意。debug/<列名>.png は最後に処理した画像の分しか残らないため、特定シーズンの確認には使えない)。妥当な候補が見つからない場合はsuggested_value=なし(要目視確認)とログに記録され、貼り付け用JSONのcorrectedは"要目視確認"というプレースホルダーになる。
修正候補がどう算出されたか(中央値・修正z-scoreの計算結果)や、なぜその値になったのか(OCRの生テキスト・切り出した各項目の変換結果)を調べたい場合は、config.jsonのlog_levelを"DEBUG"に変更するとocr.logに詳細が出力される(既定はINFOで、この詳細は出力されない)。
input/の画像は毎回変わらないため、目視確認して直した値を実行のたびに手動でCSVへ書き直すのは手間になる。corrections.jsonに訂正を記録しておくと、main.pyが実行のたびに自動で適用してくれる。
統計的外れ値(rule=statistical_outlier)が1件でも検出された場合、ocr.logの最後にcorrections.jsonへそのまま貼り付け可能なJSONが出力される。
{
"9": {
"season_kdr": {
"observed": 44.0,
"corrected": 0.44
}
},
"24": {
"season_damage_avg": {
"observed": 1431.4,
"corrected": "要目視確認"
}
}
}✏️ 編集するのは
"corrected"の値だけ。"corrected"が"要目視確認"になっている行は、元画像を見て正しい数値に書き換えること。"observed"はOCRが実際に読み取った生値の記録であり、書き換える必要はない。
corrections.jsonはメモ帳などのテキストエディタで開いて編集する(ファイルを右クリック→「プログラムから開く」→「メモ帳」)。
-
初回(ファイルの中身が
{}のみの場合): 上記のJSONをそのまま全部貼り付けて上書き保存すればよい -
2回目以降(既に他シーズンの訂正が記録されている場合): ファイル全体を置き換えると既存の訂正が消えてしまうため、一番外側の
{と}はそのまま残し、既存のシーズンブロックの末尾にカンマ,を追加してから新しいシーズンのブロックを続けて貼り付ける例:既に
"9"の訂正がある状態で"24"を追記する場合{ "9": { "season_kdr": { "observed": 44.0, "corrected": 0.44 } }, "24": { "season_damage_avg": { "observed": 1431.4, "corrected": "要目視確認" } } }カンマを忘れる・
{と}の数が合わないなどで構文が壊れると、次回python main.py実行時にエラーで止まる。その場合はcorrections.jsonの中身を全て{}に書き換えて保存すれば(それまでの訂正は失われるが)クリーンな状態からやり直せる。
type・monotonicityルールの異常値(OCR変換失敗・累積値の減少)は対象外で、このJSONには含まれない。手動でocr.logのWARNING行を見ながら追記する場合は、以下の形式に従う。
observed:ocr.logのWARNING行に出ているvalue(訂正前のOCR生値)をそのまま転記するcorrected: 元画像を目視確認した上で決めた正しい値
- 次回実行時、該当seasonの現在のOCR生値が
observedと一致する場合のみ訂正を適用し、ocr.logにINFOで記録する - 一致しない場合(
input/の画像を差し替えて再OCRした等)は訂正を適用せず、最新のOCR結果をそのまま採用した上でocr.logにWARNINGを出す。古い訂正データより新しい画像データを優先するための挙動であり、この場合は改めて元画像を確認しcorrections.jsonを書き直す必要がある - 訂正はCSV出力・異常値検出より前に適用されるため、一度正しく訂正した項目が毎回の異常値検出で再び警告されることはない
現時点ではcorrections.jsonの作成・更新は手動(テキストエディタでの編集)のみサポートしている。個人の統計値を含むため.gitignore済みで、コミットには含まれない。
| ファイル | 役割 |
|---|---|
| main.py | OCRパイプライン本体。input/ 内の画像を読み込み、config.json の座標定義に従って各項目を切り出しOCR、output/apex_stats.csv へ出力する |
| config.json | 画像の基準解像度、入出力パス、OCR設定(言語・許可文字・拡大率など)、各スタッツ項目の切り出し座標(regions)、異常値検出の閾値(anomaly_detection.mad_z_threshold)を定義。各項目の意味はdocs/config.mdを参照 |
| apex_dashboard.html | 生成したCSVをブラウザで読み込み、Plotly.jsでシーズン推移(勝率・KDR・ダメージ等)をグラフ表示するダッシュボード。サーバ不要、ローカルで開くだけで動作 |
apex_dashboard_latest.html |
main.pyがapex_dashboard.htmlにCSVデータを埋め込んで自動生成するファイル。生成後にデフォルトブラウザで自動的に開かれる。個人データを含むため.gitignore済みで、実行のたびに上書きされる(バックアップは作られない) |
| version.js | apex_dashboard.htmlが表示するバージョン情報(DASHBOARD_VERSION/CSV_SCHEMA_VERSION)。ダッシュボード本体のソースにバージョンを埋め込まないよう分離している |
input/ |
OCR対象のスクリーンショット(シーズン番号.png)を置くディレクトリ。個人の成績画像のため.gitignore済み(.gitkeepのみ管理) |
output/ |
生成されたCSVの出力先。個人データのため.gitignore済み |
debug/ |
OCR時に切り出した各領域の画像が項目名ごとに保存される(config.jsonの座標調整用)。列名ごとに1枚のみ保持され、複数画像を一括処理すると最後に処理した画像の分で上書きされるため、特定シーズンの調査には使えない。.gitignore済み |
ocr.log |
実行時のOCRログ(読み取り結果・変換後の値)。.gitignore済み |
corrections.json |
異常値の訂正を記録するファイル。初回実行時に無ければ自動生成される。詳細は異常値の訂正を記録するを参照。個人の統計値を含むため.gitignore済み |
内部の処理フロー(座標スケーリング・OCR後処理の詳細)はdocs/processing-flow.mdを参照。
config.jsonのregions(1920x1080基準の切り出し座標)が、成績画面のどこを指しているかを示す図。番号は下表の列名に対応する(各列の意味はdocs/config.mdを参照)。
| # | 列名(career_) | # | 列名(season_) |
|---|---|---|---|
| 1 | games |
16 | games |
| 2 | wins |
17 | wins |
| 3 | top5 |
18 | top5 |
| 4 | damage |
19 | damage |
| 5 | damage_max |
20 | damage_max |
| 6 | damage_avg |
21 | damage_avg |
| 7 | kills |
22 | kills |
| 8 | deaths |
23 | deaths |
| 9 | kdr |
24 | kdr |
| 10 | max_kills |
25 | max_kills |
| 11 | knockdowns |
26 | knockdowns |
| 12 | assists |
27 | assists |
| 13 | win_streak |
28 | win_streak |
| 14 | revives |
29 | revives |
| 15 | respawns |
30 | respawns |
個人の成績データを含む実画像はテストに使えないため、tests/fixtures/generate_sample.py が
config.json の座標定義を使って生成した合成画像(tests/fixtures/sample_input/1.png、個人情報を含まない)を
サンプルとして使う。座標や後処理ロジック(convert_value等)を変更した際に壊れていないか確認できる。
pip install -r requirements-dev.txt
pytest tests/regions の座標を変更した場合は、python tests/fixtures/generate_sample.py でサンプル画像・期待値を再生成すること。
個人開発のホビープロジェクトですが、バグ報告・機能要望・PRは歓迎します。GitHub Issuesへどうぞ。
回帰テストを参照し、requirements-dev.txt をインストールしてください。
pytest tests/が通ることを確認するconfig.jsonのregionsを変更した場合はpython tests/fixtures/generate_sample.pyでサンプル画像・期待値を再生成する- 個人の成績スクリーンショット・実データのCSV・
apex_dashboard_latest.html(CSVデータを埋め込んだ生成物)・corrections.json(個人の訂正値)をコミットに含めない(.gitignoreで除外済みだが念のため)
READMEのスクリーンショット用のデモデータを更新したい場合は、python docs/demo-data/generate_demo_stats.py で架空データを生成できる(実データは使わないこと)。
- オフライン実行の特性を維持する(EasyOCRの初回モデルダウンロード以外は新規のネットワーク依存を持ち込まない)
- 異常検知等の判定ロジックは固定閾値より統計的手法を優先する
変更は CHANGELOG.md(Keep a Changelog形式)への追記と、SemVerに従ったgitタグ(git tag -a vX.Y.Z)をセットで行ってください。プロジェクトのバージョンを上げた場合は、version.js の DASHBOARD_VERSION も合わせて更新してください(CSV_SCHEMA_VERSION は config.json の regions の列構成が変わった時のみ更新)。
CHANGELOG.md を参照。バージョンは Semantic Versioning に従う。




