web-dev-qa-db-ja.com

ビデオゲームのスクリーンショットからできるだけ多くのテキストを表示するための最良の方法は何ですか?

tesseract ocrツール を使用してビデオゲームからocrテキストを抽出しようとしています(スクリーンショットを前処理してコマンドラインツールのtsv出力に渡し、それを解析しています)。

Selenium Webテストと同じように、テストの自動化に使用したいと思います。つまり、スリープしてボタン(主にメニュー)をクリックする代わりに、要素が表示されるのを待つことができるようにしたいと思います。

そのためには、同じボタンのテキストを一貫して見つけ、さまざまなビデオゲームに対してできるだけ多くのテキストを見つけることができる必要があります。抽象化のために、前処理/テッセラクトのオプションはすべてのゲームで同じにすることをお勧めします。

おそらく、各ゲームで出会う各単語の辞書を追加できますが、追加したくないでしょう。

前処理/テッセラクトオプションのさまざまな組み合わせをテストし、結果の単語を確認できる設定を用意しています。

スクリーンショット(70〜90 dpi)を5倍に拡大し、テサレクトに渡す前にグレースケールにしてみました。

結果の数と精度を向上させるために他にどのようなテクニックを使用できますか?どのtesseractノブを見るべきですか?追加できる他の有用な前処理はありますか?

追伸画像を2倍に拡大した場合、画像のメモリが足りなくなったため、テッセラクトが見かけ上爆発したように見えます。静的な制限はありますか?最大サイズ近くの画像を爆破できるようにそれを見つけることができますか?調整できますか?

15

独自のtessdataをトレーニングする

これは、テッセラクトでの私の経験から学んだ最も重要な教訓です。箱から出してすぐにtesseractはスキャンされた本や新聞のテキストを認識するのに非常にうまく機能しますが、標準の本や新聞のフォント(Times New Romanなど)とは異なるフォントで使用すると、私の経験の精度は大幅に低下します。以前ははるかに困難なトレーニングでしたが、現在では tesstrain.sh が簡単になっています。ビデオゲームフォント(または少なくともそれらに類似しているフォント)を収集し、それらをトレーニングスクリプトへの入力として提供する必要があります。フォントが大きく異なっていても、tesseractは提供された画像に適切なフォントを実行時に驚くほど正確に選択できます。また、退屈であることは知っていますが、ビデオゲームで遭遇するすべての単語の単語リストをトレーニングスクリプトに提供すると有益です。独自のフォントと独自のワードリストを使用してtesseractをトレーニングすると、他にほとんど何もすることなく、ほぼ完璧な精度が得られます。

画像を前処理して認識

Tesseractのレイアウト分析に依存しないでください

可能であれば、独自のレイアウト分析を行い、テキストを含む部分に画像をトリミングします。 Teseractには、ページセグメンテーションエンジンが組み込まれていますが、特定のニーズに対して機能しない可能性が非常に高い幅広いユースケースをカバーする必要があります。また、私の経験では、画像を1行のテキストに分割し、セグメンテーションモード7(画像を1つのテキスト行として扱う)を使用すると、精度がさらに向上します。

入力テキストのxの高さを上げる

入力テキストのxの高さを、テッセラクトのトレーニングに使用したのと同じ高さに増やすと役立ちます(IIRCの場合、これは私の場合70ピクセルでした)。

入力テキストのDPIを上げる

Tesseract 本当に300 DPIが好き 。画像のDPIを変更することは、サイズを変更することと同じではないことに注意してください。 (たとえば、ImageMagickを使用すると -densityオプションを使用 して画像のDPIを変更します)。

使用するTesseract構成変数

私の経験では、一致する辞書の単語に関連するさまざまな「ペナルティ」設定を微調整することが、精度の向上に最も影響を与えました。私のために働いた設定:

language_model_penalty_non_dict_Word      0.975
language_model_penalty_non_freq_dict_Word 0.575
segment_penalty_dict_case_bad             1.3125
segment_penalty_dict_case_ok              1.1
segment_penalty_dict_nonword              10.25

ただし、明らかに自分で調整する必要があります。また、x-height設定は実行時に非常に役立つことがわかりました:textord_min_xheightおよびmin_sane_x_ht_pixels


Tesseractのメモリサイズの制限については知りません。独自の制限があるラッパーを通じてtesseractを使用しているのでしょうか?


注:この回答は、tesseract 3.05であるtesseractの最新の安定したビルドを使用していることを前提としています。 tesseract 4.0を使用している場合、独自のトレーニングとセグメンテーションを行うことは引き続き適用されますが、回答の他のセクションはOBEである可能性があります。

9
mnistic

tesseractから適切な品質の出力が得られない理由はたくさんあります。非常に変わったフォントや新しい言語を使用していない限り、tesseractを再トレーニングしても役に立たない可能性があることに注意することが重要です。

したがって、次のようなタスクについては ImproveQuality ツールを参照してください。

たとえば、次のスクリプトでは、色変換、変換、プロット操作を確認できます。

from __future__ import division, print_function
from skimage.transform import radon
from PIL import Image
from numpy import asarray, mean, array, blackman
import numpy
from numpy.fft import rfft
import matplotlib.pyplot as plt
from matplotlib.mlab import rms_flat

try:
    # More accurate peak finding from
    # https://Gist.github.com/endolith/255291#file-parabolic-py
    from parabolic import parabolic

    def argmax(x):
       return parabolic(x, numpy.argmax(x))[0]

except ImportError:
    from numpy import argmax

filename = 'skew-linedetection.png'

# Load file, converting to grayscale
I = asarray(Image.open(filename).convert('L'))
I = I - mean(I)  # Demean; make the brightness extend above and below zero
plt.subplot(2, 2, 1)
plt.imshow(I)

# Do the radon transform and display the result
sinogram = radon(I)

plt.subplot(2, 2, 2)
plt.imshow(sinogram.T, aspect='auto')
plt.gray()

# Find the RMS value of each row and find "busiest" rotation,
# where the transform is lined up perfectly with the alternating dark
# text and white lines
r = array([rms_flat(line) for line in sinogram.transpose()])
rotation = argmax(r)
print('Rotation: {:.2f} degrees'.format(90 - rotation))
plt.axhline(rotation, color='r')

# Plot the busy row
row = sinogram[:, rotation]
N = len(row)
plt.subplot(2, 2, 3)
plt.plot(row)

# Take spectrum of busy row and find line spacing
window = blackman(N)
spectrum = rfft(row * window)
plt.plot(row * window)
frequency = argmax(abs(spectrum))
line_spacing = N / frequency  # pixels
print('Line spacing: {:.2f} pixels'.format(line_spacing))

plt.subplot(2, 2, 4)
plt.plot(abs(spectrum))
plt.axvline(frequency, color='r')
plt.yscale('log')
plt.show()
1
ARGeo

Googleクラウドは動画にOCRを提供します。したがって、スクリーンショットを撮る必要はありません。ゲーム動画全体をGCPに更新し、APIを呼び出して処理するだけです。 APIは、動画の各テキストのタイムスタンプと境界ボックスを返します。これは非常に高速に処理され、生成される結果は非常に高密度で一貫しています。詳細は公式ドキュメントで確認できます: https://cloud.google.com/video-intelligence/docs/text-detection

1
Geoffrey Wu

https://matthewearl.github.io/2016/05/06/cnn-anpr/ のボタンテキストsu chasを検出するために、深層学習法、特にオブジェクト認識アルゴリズムを使用してみましたか?

0
A. Attia