テンプレートマッチング中にOpenCVが画像の透明度を処理する方法は何ですか?
問題は、元の画像ではそれらの場所に何かが存在する可能性があるため、テンプレート画像に透明な部分が必要なことです。
私はすべての方法を試しましたが、どれも肯定的な結果をもたらしませんでした (たとえば、元の画像のテンプレートの位置が正しく検出されませんでした)。
テンプレートマッチング中にOpenCVが画像の透明度を処理する方法は何ですか?
問題は、元の画像ではそれらの場所に何かが存在する可能性があるため、テンプレート画像に透明な部分が必要なことです。
私はすべての方法を試しましたが、どれも肯定的な結果をもたらしませんでした (たとえば、元の画像のテンプレートの位置が正しく検出されませんでした)。
OpenCV が希望どおりにアルファを処理しているようには見えません。
次の 2 つのオプションがあります。
最初のオプションは簡単なので、ここでは 2 番目のオプションを検討します。以前に同様の質問に提供したサンプル コードを再利用します。相互相関を画像に直接適用すると、背景がテンプレート マッチングに干渉します (特に、明るい背景部分)。カラー チャネルをいじってみると、青チャネルで一致させると正しい結果が得られることがわかります。これは画像の内容によって異なり、問題を解決するための一貫した方法ではありません。
もう 1 つのオプションは、画像とテンプレートに対してエッジ検出 (例: Sobel ) を実行し、次に相互相関を実行することです。これがエッジ検出画像です (私は GIMP の Luma チャネルでソーベル エッジ検出器を使用し、強度ストレッチングを行いました)。
ご覧のとおり、ここでのアルファ チャネルは無関係になりました。地形のほとんどがゼロ強度になり、相互相関の計算に寄与しないためです。したがって、相互相関を直接適用して、目的の結果を得ることができます。
misha@misha-desktop:~/Desktop/stackoverflow$ python cross-correlation.py map-blue.png building-maskz-blue.png
(163, 244)
最後に、別の関連する質問があります。
PS。これは何のゲームですか?
この問題に対して、実際にはかなりうまく機能しているように見えるもう少し脳死の解決策があります。テンプレート画像のアルファチャンネルをノイズに置き換えます。これにより、マッチングプロセス中に透明領域が統計的に重要ではなくなります。
たとえば、私のユース ケースでは、iOS からのスクリーン キャプチャで絵文字を検索しました。iOS キーボードの背景はコンテキストに応じて色が変わるため、テンプレート イメージで特定の背景色を使用すると、マッチング プロセスが問題になります。
アルファの生のテンプレート画像は次のとおりです。
アルファ チャネルにノイズを追加した処理済みテンプレートを次に示します。
OpenCV ドキュメントで提供されているテンプレート マッチングのサンプル コードを使用して、処理済みのテンプレート イメージを送信しました。暗い背景でも明るい背景でも、一致は妥当な信頼度で検出されます。
暗い背景での検索:
明るい背景での検索:
対照的に、テンプレートのアルファ チャネルを透明のままにしておくか、暗い背景または明るい背景にコミットすると、許容できる一致が返されませんでした。
OpenCV 3.0 は、マスクされたテンプレートとのテンプレート マッチングのネイティブ サポートを提供します。新しいドキュメントを参照してください:
パラメーター:
画像 ...
テンプル ...
結果 ...
方法 ...
mask 検索されたテンプレートのマスク。templ と同じデータ型とサイズである必要があります。デフォルトでは設定されていません。
【余談】
ただし、マスクされた参照画像 (大きい方の画像) とのテンプレート マッチングはできないことに注意してください。OpenCV が FFT ベースのテンプレート マッチングを使用していることを考えると、これは理にかなっています。
したがって、参照画像の特定の領域でのみテンプレート マッチングを実行する必要がある場合は、そのための独自のメソッドを実装するか、cv::matchTemplate の出力をマスクする必要があります。
テンプレートを最初から実装することで、非常に特定の領域 (つまり、ハリス コーナー周辺) でのみテンプレートを検索したい場合を補うことができます。
このSQDIFF/SQDIFF_N
オプションは、アルファ チャネルを黒の RGB カラーに置き換えようとした場合の解決策になります。少なくともこれは同じ問題に対する私の解決策でした。私の結果から、この方法はより明るいピクセル値に敏感であることが明らかであり、私はそれを利用しました。
わかりませんが、透明度チャンネルは他のチャンネルと同じように扱われます。テンプレート内のピクセルが「透明」である場合、メイン画像でも「透明」である必要があります。私はここで推測しています。
OpenCVでマスクとのテンプレートマッチングと呼ばれるものをやろうとしていると思います。テンプレートに ROI (関心領域) を設定してみるとよいと思います。This SO question は、その方法を示しています。(その質問では、ROI はテンプレートではなくターゲット画像に設定されていますが、手順は同じであることに注意してください)。
私は同じ問題に遭遇し、解決策を考えました。referenceImageMask と templateMask の良いピクセルには 1 があり、悪いピクセルには 0 があると仮定します。そして、その referenceImage と templateImage は既にマスクされており、不良ピクセルにも 0 があります。
次に、テンプレート マッチングの最初の結果は、画像間の正規化されていない相互相関を示します。ただし、ピクセルの束はゼロでした。
2 番目のテンプレート マッチングでは、可能なオフセットごとに、両方の画像で同時にゼロとは異なる (マスクされていない) ピクセル数が示されます。
次に、その数値で相関を正規化すると、あなた(および私)が望んでいた値が得られます。両方の画像でマスクされていないピクセルの平均積。
Image<Gray, float> imCorr = referenceImage.MatchTemplate(templateImage, Emgu.CV.CvEnum.TM_TYPE.CV_TM_CCORR);
Image<Gray, float> imCorrMask = referenceImageMask.MatchTemplate(templateMask, Emgu.CV.CvEnum.TM_TYPE.CV_TM_CCORR);
_imCorr = _imCorr.Mul(_imCorrMask.Pow(-1));
更新: 実際には、このソリューションは機能しません。opencv での相互相関の実装は DFT を使用するため、数値の問題が発生し、2 番目の相互相関を使用して最初の相互相関を修正することはできません。