0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

画面内特定文字列の表示位置探索のテスト

Posted at

前回の続き

前回(https://qiita.com/tanakah/items/ee41c592cc4f2caaf56d) のツールでは、
ゲーム画像のチャット文字に特定文字列が表示されたかどうか(及びその位置)の検出方法として、
2値化した画像のパターン(高さ16ドットの列を2バイト=16bitで符号化)の辞書比較による探索でやっていました。
ゲーム画像ということで、フォント種類、文字幅が固定され、ノイズもないという緩い条件なので、
高速で確実に検出することができています。
ただ、この方法だと上下に1ドットでも探索ラインがずれると検出できないのですよね。
あらかじめ探索開始ラインを調整しておかないといけない。
そこでもうちょっと画像処理らしくやってみたいなと思っていました。

パターンマッチングへの拡張

要するに、今までは特定ラインだけ走査して相関値を求めていたのを、複数ラインに拡張すればいいだけです。
(時間がかかるから手抜きしてました^^;)
例えば5×5のガウシアンフィルタで画像全体を走査するように、
相関値を求めるフィルタで画像を走査して画素値を逐一求める処理します。

で、このような空間フィルタリングは周波数領域での演算と同等なわけで
(というか、周波数領域で意味を持った処理を時間領域に変換することによって、フィルタサイズに応じた係数が決まる)
フーリエ変換を使った演算で位置検出できることを確認してみたくなりました。

テスト

OpenCV2.4系でざっくり書いてみました。

  IplImage *image_co, *image_re, *image_im;
  IplImage *dict_co, *dict_re, *dict_im;
  IplImage *temp_re, *temp_im;
  IplImage *disp_gr;
...
  //// DFT(1)
  cvDFT(image_co, image_co, CV_DXT_FORWARD, dft_size);
  {
    cvSplit(image_co, image_re, image_im, NULL, NULL);
    //
    cvSplit(image_co, temp_re, temp_im, NULL, NULL);
    cvPow (temp_re, temp_re, 2.0); cvPow(temp_im, temp_im, 2.0);
    cvAdd(temp_re, temp_im, temp_re, NULL); cvPow(temp_re, temp_re, 0.5);
    // normalize
    cvDiv(image_re, temp_re, image_re); cvDiv(image_im, temp_re, image_im);
    cvMerge(image_re, image_im, NULL, NULL, image_co);
  }

  //// DFT(2)
  cvDFT(dict_co, dict_co, CV_DXT_FORWARD, dft_size);
  {
    cvSplit(dict_co, dict_re, dict_im, NULL, NULL);
    //
    cvSplit(dict_co, temp_re, temp_im, NULL, NULL);
    cvPow (temp_re, temp_re, 2.0); cvPow(temp_im, temp_im, 2.0);
    cvAdd(temp_re, temp_im, temp_re, NULL); cvPow(temp_re, temp_re, 0.5);
    // normalize
    cvDiv(dict_re, temp_re, dict_re); cvDiv(dict_im, temp_re, dict_im);
    cvMerge(dict_re, dict_im, NULL, NULL, image_co);
  }

  cvMulSpectrums(image_co, dict_co, image_co, CV_DXT_MUL_CONJ);

  //// IDFT
  cvDFT(image_co, image_co, CV_DXT_INVERSE);
  cvSplit(image_co, image_re, image_im, NULL, NULL);
  mycvSwapQuadrant(image_re, image_re);

  //// convert scale
  double re_min=0.0, re_max=1.0;
  CvPoint maxloc, minloc;
  cvMinMaxLoc(image_re, &re_min, &re_max, &minloc, &maxloc, NULL);
  Printf("maxpoint(%d,%d)\n", maxloc.x, maxloc.y);
  cvConvertScale(image_re, disp_gr, 255.0/(re_max-re_min), 255.0*(-re_min)/(re_max-re_min));

結果

入力画像 と 検出文字列画像
yahoo_capture.png yahoo_capture_words.png

DFT画像(normalize前)
yahoo_capture_dft.png yahoo_capture_words_dft.png

IDFT(DFT×DFT) 画像 (わかりにくいですが、"おそれ"の位置に輝点)
yahoo_capture_idft.png

検出条件を絞っていったときにこういう方法もあるわな、と覚えておくことにします。
(ちなみに、入力画像の太字の"おそれ"が検出できないように、この方法だと拡大縮小には対応しないんですよね、
対応するためにはLogPolar変換使ったりするんでしょうけど、まぁそこまでいいわっていう)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?