20

私はCVの基本に頭を悩ませようとしています。最初に興味を持ったのはテンプレートマッチング(CVとは関係のないPyconの講演で言及されていた)だったので、そこから始めようと思いました。

私はこの画像から始めました:

SMB3からのシーン

その中からマリオを検出したい。だから私は彼を切り取った:

配管工

テンプレートを画像の周りにスライドさせて最適なものを確認するという概念を理解しています。チュートリアルに従うと、次のコードでマリオを見つけることができます。

def match_template(img, template):
    s = time.time()
    img_size = cv.GetSize(img)
    template_size = cv.GetSize(template)

    img_result = cv.CreateImage((img_size[0] - template_size[0] + 1, 
                            img_size[1] - template_size[1] + 1), cv.IPL_DEPTH_32F, 1)
    cv.Zero(img_result)

    cv.MatchTemplate(img, template, img_result, cv.CV_TM_CCORR_NORMED)
    min_val, max_val, min_loc, max_loc = cv.MinMaxLoc(img_result)
    # inspect.getargspec(cv.MinMaxLoc)
    print min_val
    print max_val 
    print min_loc 
    print max_loc
    cv.Rectangle(img, max_loc, (max_loc[0] + template.width, max_loc[1] + template.height), cv.Scalar(120.), 2)
    print time.time() - s
    cv.NamedWindow("Result")
    cv.ShowImage("Result", img)
    cv.WaitKey(0)
    cv.DestroyAllWindows()

これまでのところ良いのですが、それから私はこれが信じられないほど壊れやすいことに気づきました。その特定の背景と、その特定のアニメーションフレームが表示されているマリオのみが検出されます。

マリオは常に同じマリオっぽい属性(サイズ、色)を持っているので、私は興味があります。彼の現在のフレームが静止しているか、さまざまな実行の1つであるかに関係なく、彼を見つけることができるテクニックがあります。サイクルスプライト?文字列に対して実行できるあいまいマッチングのようなものですが、画像に対して実行できます。

たぶん彼が唯一の赤いものなので、赤いピクセルを単純に追跡する方法はありますか?

他のすべての問題は、テンプレートから背景を削除することです。テンパテと完全に一致していなくても、MatchTemplate関数がマリオを見つけるのに役立つかもしれません。今のところ、それがどのように機能するかは完全にはわかりません(MatchTemplateにマスクパラメータがあることがわかりますが、さらに調査する必要があります)

私の主な質問は、テンプレートマッチングが、ほとんど同じであるが変化する(彼が歩いているときのように)画像を検出する方法であるかどうか、または私が調べる必要がある別の手法があるかどうかです。

アップデート:

他のマリオとのマッチングの試み


mmgpが他のものと一致させるために機能するはずであるという提案から離れて、私はいくつかのテストを実行しました。

私はこれを一致するテンプレートとして使用しました:

スーパーマリオ

次に、マッチングをテストするために2、3のスクリーンショットを撮りました。

最初に、私はマリオを見つけることに成功し、最大値1を取得しました。

ここに画像の説明を入力してください

ただし、ジャンプするマリオを見つけようとすると、完全に失火します。

失火

確かに、テンプレートのマリオとシーンのマリオは反対方向を向いており、アニメーションフレームも異なりますが、画像内の他の何よりもはるかに一致していると思います。色だけ。ただし、テンプレートに最も近いものとしてプラットフォームを対象としています。

これの最大値はであったことに注意してください0.728053808212

次に、マリオのいないシーンを試して、どうなるか見てみました。

ここに画像の説明を入力してください

しかし、奇妙なことに、私はマリオをジャンプした画像として正確な結果を取得します-類似性の値まで:0.728053808212写真に写っているマリオは、写真に写っていないマリオと同じくらい正確です。

本当に奇妙です!基礎となるアルゴリズムの実際の詳細はわかりませんが、標準偏差の観点から、テンプレートのマリオのスーツの赤と少なくとも一致するシーン内のボックスは、青よりも平均距離に近いと思いますプラットフォームですね。ですから、それが私が期待する一般的な領域にさえないことは、さらに混乱を招きます。

これは私の側のユーザーエラーか、あるいは単なる誤解だと思います。

同様のマリオがあるシーンが、マリオがまったくないシーンと同じくらい一致するのはなぜですか?

4

2 に答える 2

13

間違いのない方法はありませんが、テンプレート マッチングはそこで機能する可能性が高くなります。いくつかの前処理が必要になる場合があり、可能性のある問題を示すためのより大きなサンプル (短いビデオなど) ができるまでは、いくつかのライブラリがそれらを実装しているという理由だけで、より高度な方法を試す意味はあまりありません。どのような条件下で動作することが期待されるかわからない場合。

たとえば、テンプレート マッチング (赤い四角形) を使用して取得した結果は次のとおりです。最後のものでも、すべてテンプレートhttp://i.stack.imgur.com/EYs9B.pngを使用しています。

ここに画像の説明を入力 ここに画像の説明を入力 ここに画像の説明を入力 ここに画像の説明を入力

これを実現するために、テンプレートと入力画像の両方の赤チャネルのみを考慮することから始めました。そこから、内部の形態学的勾配を簡単に計算してから、マッチングを実行します。マリオが存在しないときに四角形を取得しないようにするには、マッチングの最小しきい値を設定する必要があります。これら 2 つの変換後のテンプレートとイメージの 1 つを次に示します。

ここに画像の説明を入力 ここに画像の説明を入力

そして、これを実現するためのサンプルコードを次に示します。

import sys
import cv2
import numpy

img = cv2.imread(sys.argv[1])

img2 = img[:,:,2]
img2 = img2 - cv2.erode(img2, None)
template = cv2.imread(sys.argv[2])[:,:,2]
template = template - cv2.erode(template, None)

ccnorm = cv2.matchTemplate(img2, template, cv2.TM_CCORR_NORMED)
print ccnorm.max()
loc = numpy.where(ccnorm == ccnorm.max())
threshold = 0.4
th, tw = template.shape[:2]
for pt in zip(*loc[::-1]):
    if ccnorm[pt[::-1]] < threshold:
        continue
    cv2.rectangle(img, pt, (pt[0] + tw, pt[1] + th),
            (0, 0, 255), 2)

cv2.imwrite(sys.argv[2], img)

もっとさまざまな状況で失敗すると思いますが、簡単な調整がいくつかあります。

于 2013-02-10T15:16:49.743 に答える
12

テンプレート マッチングは常に良い結果をもたらすとは限りません。キーポイントの一致を調べる必要があります。

Step1: キーポイントを見つける

マリオを切り取るか、マリオの ROI イメージを取得できたとします。この画像をテンプレート画像にします。次に、メイン画像とテンプレートでキーポイントを見つけます。これで 2 セットのキーポイントができました。1 つは画像用、もう 1 つはマリオ (テンプレート) 用です。

好みに応じてSIFTSURFORBを使用できます。

[編集]:

これは、SIFT と flann ベースの knn マッチングでこの方法を使用して得たものです。バウンディングボックスの部分はやっていません。

ここに画像の説明を入力

テンプレートが非常に小さいため、SIFT と SURF では多くのキーポイントが得られません。しかし、十分な数の特徴点を取得するには、Harris Corner 検出器を試すことができます。画像にハリスコーナーを適用したところ、マリオにかなり良い点が取れました。

ここに画像の説明を入力

ステップ 2: キーポイントを一致させる

SIFT または SURF を使用したことがある場合は、画像とテンプレートの両方の記述子が存在します。KNN またはその他の効率的なマッチング アルゴリズムを使用して、これらのキーポイントを一致させます。OpenCV を使用している場合は、フランベースのマッチャーを調べることをお勧めします。キーポイントを一致させた後、不適切な一致を除外する必要があります。これは、K- 最近傍で行うことができ、最も近い一致の距離に応じて、キーポイントをさらに除外できます。Forward-Backward Error を使用して、一致をさらにフィルタリングできます。

前方後方誤差推定:

  1. テンプレートのキーポイントを画像のキーポイントに一致させる これにより、一連の一致が得られます。
  2. 画像のキーポイントをテンプレートのキーポイントに一致させます。これにより、別の一致セットが得られます。
  3. これら両方のセットの共通セットは、不正確な一致を除外します。

ここに画像の説明を入力

[編集]: Harris Corner 検出器を使用している場合は、キーポイントではなくポイントのみが取得されます。それらをキーポイントに変換するか、独自のブルートフォース mathcer を作成することができます。それほど難しいことではありません。

Step3: お見積り

キーポイントをフィルタリングした後、オブジェクト (この場合はマリオ) の近くにキーポイントのクラスターがあり、いくつかの散在するキーポイントがあります。これらの散在するキーポイントを排除するには、クラスタリングを使用できます。DBSCAN クラスタリングは、ポイントの適切なクラスターを取得するのに役立ちます。

step4: バウンディングボックス推定

これで、キーポイントのクラスターができました。k-means を使用して、クラスターの中心を見つけようとする必要があります。クラスターの中心を取得したら、境界ボックスを推定できます。

これが役立つことを願っています。

[編集]

Harris Cornersを使用してポイントを一致させようとしています。ハリス コーナーをフィルタリングした後、ブルート フォース メソッドを使用してポイントを一致させています。より良いアルゴリズムを使用すると、より良い結果が得られる場合があります。

ここに画像の説明を入力

于 2013-02-10T12:26:42.763 に答える