inosyanのブログ

プログラム、家庭菜園、僕が興味を持ったことを書いていきます

ウルティマオンラインの画像解析ツール「Ultima Online image analysis tool」公開

先日の記事「ウルティマオンライン月額課金無料化した記念にjsで画像解析ツールを作成」で紹介したツールを改良したものを公開しました。

f:id:inosyan:20180428151746p:plain

「Ultima Online image analysis tool」

画面上部に説明文があります。 f:id:inosyan:20180428151813j:plain

このアプリはオンラインゲーム「ウルティマ オンライン」のツールです。

まず、プレイ中にゲーム画面のスクリーンショットを撮ります。
画像ファイルを下の領域にドラッグ&ドロップして画像を解析し、ステータス、スキル、ペーパードール画像を見ることができます。

ウルティマ オンラインのクライアントアプリには、「クラシック クライアント」と「エンハンスド クライアント」の2つのバージョンがありますが、このアプリは「クラシック クライアント」専用です。

スクリーンショットには、1つのペーパードールウィンドウ、ステータスウィンドウ、およびスキルウィンドウが含まれている必要があります。

・スキルウィンドウの各スキルを展開する必要があります。グループ名は不要なので、最初のスキルを上にスクロールアップする必要があります。

・ペーパードールには、ペーパードールウィンドウの上部に星印が含まれている必要があります。

・画像に複数のペーパードールが含まれている場合は、最初に見つかったものだけが表示されます。

・分析後、結果の表の下に「Copy Columns(カラムのコピー)」と「Copy Values(値のコピー)」ボタンが表示されます。タップして結果をクリップボードにコピーし、スプレッドシートに貼り付けることができます。

下にスクロールすると、カバンの中に

Drop Screenshot Here!
OR
Tap To Select a File

と書かれています。ここにスクリーンショットをドラッグするか、タップしてファイルを選択します。

f:id:inosyan:20180428151856j:plain

デモ用にサンプルのゲーム画面のスクリーンショットを用意しました。「Show sample image」ボタンで見ることが出来ます。

f:id:inosyan:20180428151926j:plain

その隣のボタン「Perform demo」を押すと、サンプル画像を使って実行した結果を見ることが出来ます。

f:id:inosyan:20180428151944j:plain

分析結果の表の下に、「Copy Columns(カラムのコピー)」と「Copy Values(値のコピー)」ボタンが表示されますが、これは、スプレッドシートに結果を記録するためのものです。 ボタンを押すと、クリップボードにデータがコピーされます。

コピーされるデータはタブ区切りの文字列です。テキストエディタに貼り付けるとこのように見えます。 f:id:inosyan:20180428152021p:plain

スプレッドシートに貼り付けるとカラムがセルに入ります。
f:id:inosyan:20180428152035p:plain

「Copy Values(値のコピー)」の結果をカラムの下に貼り付けていけば、カラムのセルの下にそれぞれの値が入ります。 f:id:inosyan:20180428152050p:plain

スプレッドシートに貼り付けたあとは、デザインを整えたり、目標値と比較するのも良いでしょう。 f:id:inosyan:20180428152107p:plain

プログラムの説明

プログラムについて少し説明します。 前回の記事の時点から、ペーパードールの画像分析を強化しました。

前回の時点では、ペーパードールの周りの黒い部分を除いた部分を切り抜くところま出来ていました。しかし、エッジ部分にジャギーが出ていました。
f:id:inosyan:20180428152135p:plain f:id:inosyan:20180428152208p:plain

ジャギーの原因はエッジ部分に半透明のピクセルが無いことです。なので、アンチエイリアシングの処理を行うことにしました。そのためにはエッジを半透明にすれば良いのですが、小さな画像ではすべてのエッジをすべて半透明にしてしまうとぼやけた画像になってしまいます。なので、出っ張っているピクセルだけ半透明にしてみました。
出っ張っているピクセルとは

  • 上と左が透明
  • 上と右が透明
  • 下と左が透明
  • 下と右が透明

のいずれかの場合のピクセルです。

f:id:inosyan:20180428152252p:plain f:id:inosyan:20180428152303p:plain

良くなりました。しかし、まだジャギー感があります。なので、出っ張っているピクセルの隣のピクセルも弱めの半透明にしました。ただし、赤で印を付けた箇所のように窪んでいるところは避けないと、その部分がえぐれたような結果になってしまいます。

f:id:inosyan:20180428152316p:plain f:id:inosyan:20180428152328p:plain

だいぶ良くなりました。大きな画像ではもっと入念な処理が必要ですが、これくらいの大きさの画像ではこの程度のアンチエイリアシング処理で十分です。

しかし、他のキャラクターの画像を解析した時に困ったことがおきました。このキャラクターはローブを着ているのですが、右下が変です。
f:id:inosyan:20180428152401p:plain

もとの画像はこちらです。キャラクターの画像だけ抜き出したいので余分なものを除去しているのですが、カバンの後ろに衣装が隠れていたため、カバンの形にくり抜かれています。
f:id:inosyan:20180428152419j:plain

これを解決するに、まず、このペーパードールがローブを着ているのかどうかを調べます。
マッチング用の画像を用意し、アンチエイリアシング処理をする前の状態の画像を比較します。アルファで抜かれている箇所が一致すればローブを着ていることになります。
f:id:inosyan:20180428152437p:plain

次に、抜けている穴を埋めるのですが、単純に塗りつぶすわけにはいかないので画像を使います。その画像はフォトショップで埋められている状態を想像しながら描きました。ローブの色は赤以外にもたくさんあります。すべての色に対応するためにグレースケールの画像を用意し、穴埋め処理の際にローブの色にあうように調整します。
f:id:inosyan:20180428152449p:plain

グレー画像から描画するピクセルの色を求めるのは、次の式です。

ピクセルの色 = その位置のグレー画像の色 / 基準となるグレーの色 * 対象画像から採取した色

はじめ、赤いローブをもとにグレー画像を作ったのですが、その画像だと暗すぎて、ピンク色のローブの時には合いませんでした。
グレーにも明るさやコントラストによって結果が変わってきます。なるべく平均的な明るさで作るほうが良さそうです。
どの色にもあうようにするためには、適切な明るさとコントラストのグレー画像と、基準となるグレーの色を調整する必要があります。
今回はトライアンドエラーで調整し、赤とピンクのローブではうまくいくことを確認しましたが、もしかしたらこれらを調整するうまい方法があるのかもしれません。

f:id:inosyan:20180428152511p:plain

ツールのjavascriptは小さく軽量化の必要はないため、改行や空白はそのまま残っています。ご興味のある方は御覧ください。
javascriptソース