読者です 読者をやめる 読者になる 読者になる

備忘録

イケイケエンジニアになるために自己嫌悪と戦う大学院生のメモ兼モチベーション維持。

スコア部分の文字列切り出し

前回まででスコア表示部分のヘッダーが取れたので、その下のスコア表示部分を切り抜き、文字認識に繋げる

スコア表示部分切り抜き

  • ヘッダ検出結果から、その下部の領域を適当に切り出す
  • 欠けてしまうと文字認識が失敗するため、無駄な部分が入ろうとも大きめに切り出す方針

いい感じの切り抜き f:id:reverent_f:20170109154200p:plain

別部分も入った切り抜き f:id:reverent_f:20170109154205p:plain

2値化

文字位置特定や文字認識の処理を行うために2値化する。

対象画像の特性

  • 背景白に青色・縁取りありの数字が並ぶ
  • 切り抜きで余分な部分(青系統の色)が含まれる可能性が高い
  • ゲームセンターごとに環境光の影響で色味が変わる

試した2値化処理

  • 普通にcv2.THRESH_OTSUcv2.threshold()
    • 画像によって文字部分が欠けるなど安定しない
  • 適応的2値化処理cv2.adaptiveThreshold()
    • 同上
  • HSV変換→青色検出
    • 環境光の影響で安定せず
  • 白色検出→反転
    • 同上
  • (Bのみグレースケール) - (Gのみグレースケール) - (Rのみグレースケール)
    • うまくいきそうな気がしたけどダメ
  • 上記結果の組み合わせ(加算減算etc)
    • ダメなものを重ねてもダメ

最終的な2値化処理

画像のRのみ取り出してグレースケール化

 →大津の方法で2値化

が一番安定して文字部分を保持したまま2値化できた

red = img[:,:,2]
ret,bin_red = cv2.threshold(red,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

# オープニングで白色ノイズ除去
kernel = np.ones((3,3),np.uint8)
bin_red = cv2.morphologyEx(bin_red, cv2.MORPH_OPEN, kernel)

結果

こんな感じ

f:id:reverent_f:20170109155622p:plain

f:id:reverent_f:20170109155629p:plain

文字位置特定

2値化結果にノイズが乗っていた時期から色々試していたため、かなり苦労した。

試したこと

  1. 輪郭抽出

輪郭抽出 → 矩形に近似 → アスペクト比から文字候補検出

f:id:reverent_f:20170109160558p:plain f:id:reverent_f:20170109160602p:plain

問題点: - 2値化結果で1文字が2つの領域に分断されていると失敗

  1. ヒストグラムから判断

    X軸/Y軸ごとのヒストグラムを作成し、そこから文字位置を特定する

  2. Y軸のヒストグラムから文字が存在する範囲のyを特定・切り出し

  3. 切り出した部分に対してのX軸方向ヒストグラムを作成・文字位置特定

f:id:reverent_f:20170109161155p:plain f:id:reverent_f:20170109161158p:plain

文字以外の枠も検出されているが、仮にその後の文字認識処理においてこの部分が"1"と認識されたとしても、スコアの桁数が固定のため補正できると思う。

Tesseract-OCRを試したが認識率が安定しない。 学習データを集めてkNNで文字認識する。

あと横方向エッジ検出結果から画像の水平化もする必要がある