質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

2回答

1873閲覧

テンプレートマッチングで検出した範囲を白抜きしたい

branch

総合スコア70

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2020/06/29 04:38

編集2020/06/29 08:21

Google ColabにてPython 3.8 + OpenCV 4.2.0 で画像処理をしています.
img1から一部を切り出して保存したimg2に対して,テンプレートマッチングによりimg1上のimg2部分を白塗りする関数を作成しようとしているのですが,うまく動きません.
引数image1,image2は画像パスで,返り値は白抜き後画像の配列情報img1を想定しています.
画像はイメージです
##試したこと
それぞれ下記スクリプトのif Judg == True: 内の中身です.
0. img2と同じサイズの白い画像(blank_img)を用意し,テンプレートマッチング結果maxLocから得られたマッチング部分に白い画像を貼り付ける
0. テンプレートマッチング結果maxLocから,img2と同じ大きさの部分を255(白)にする
0. maxLocから得られた部分にimg2と同じ大きさのcv2.rectangleで塗りつぶす

特にエラーが出ることもなく,処理に成功しないまま実行完了します...

python

1def erase_img(image1 , image2): #img1上でimg2と一致するものがあればそこを白塗りする関数 2#引数はimg1,img2のパス 3 4 img1 = cv2.imread(image1 , cv2.IMREAD_GRAYSCALE) #デカい方 5 img2 = cv2.imread(image2 , cv2.IMREAD_GRAYSCALE) #ちっこい方 6 blank_img = np.zeros(img2.shape , np.uint8) + 255 #ちっこい方と同じサイズの白画像作成 7 8 9 #ちっこいの検索開始 10 result = cv2.matchTemplate(img2, img1, cv2.TM_CCORR_NORMED) 11 12 #最も類似度が高い位置と低い位置を取得 13 minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(result) 14 15 #類似度が閾値を超えているか判定(後述) 16 Judg = Judge_Matching(maxVal) 17 18 if Judg == True: 19 img1[ maxLoc[1]: maxLoc[1] + img2.shape[1] , maxLoc[0] : maxLoc[0] + img2.shape[0] ] = blank_img 20 img1[ maxLoc[1]: maxLoc[1] + img2.shape[1] , maxLoc[0] : maxLoc[0] + img2.shape[0] ] = 255 #白塗りして保存 21 cv2.rectangle(img1, maxLoc , img2.shape , (0, 0, 255), -1) #黒塗りはどうや? 22 return img1 #返り値は処理後の画像

上記のJudge_Matchingは以下の単純な判定関数です.

python

1def Judge_Matching(num): 2 if num == 1: 3 return True 4 else: 5 return False

##main文

main

1targetimgs = glob.glob("./hoge/*.jpg") 2for targetimg in targetimgs: 3 print(targetimg) 4 baseimg = targetimg.replace("hoge" , "fuga") 5 print(baseimg) 6 img_out = erase_img( baseimg , targetimg ) 7 cv2_imshow(img_out) 8 cv2.imwrite(baseimg , img_out)

カレントディレクトリ内にhogeとfugaがあり,その中に一定の命名規則に従った画像が保存されています.hoge内の画像image1fuga内のimage1からトリミングしたもの であり.上の例だとhoge内にLennaの目が,fuga内にLennaの全体がそれぞれ保存されています.
対応関係を整理しやすいように各画像の命名規則は揃えています.
最終行では関数からの返り値img_outでbaseimgを上書きしています.

かなり初歩的な点かもしれませんが,ここで5日ほど詰まっております.
ご教授のほど,よろしくお願いいたします.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuki23

2020/06/29 06:00

どうやって実行しましたか? また、関数定義だけでなく、プログラム全体を載せてください
branch

2020/06/29 07:45

早速のご回答ありがとうございます. >どうやって実行しましたか? に関しては追記しましたが,念のためお知らせします. `Google Colab Python 3.8 + OpenCV 4.2.0`です.Ubuntuです. Google Colabの仕様で`cv2.imshow`は使えないので,main文の中では`cv2_imshow`としております. よろしくお願いいたします.
guest

回答2

0

ベストアンサー

img2.shape は (W, H) ではなく、(H, W) なので、img2.shape[0]img2.shape[1] が逆です。

pythn

1 if Judg == True: 2 img1[ 3 maxLoc[1] : maxLoc[1] + img2.shape[0], maxLoc[0] : maxLoc[0] + img2.shape[1] 4 ] = 255 # 白塗りして保存

それはそうとして、if num == 1、つまり、類似度が厳密に1になるというのは、テンプレート画像と全く同じ画素を持つ領域が検索対象の画像にある場合ですので、まずこの条件には引っかからないでしょう。
if maxVal >= 0.8: のように条件をゆるめてみてはどうでしょうか

修正後のコード

python

1import cv2 2 3def erase_img(img_path, templ_path): 4 img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE) 5 templ = cv2.imread(templ_path, cv2.IMREAD_GRAYSCALE) 6 7 result = cv2.matchTemplate(img, templ, cv2.TM_CCORR_NORMED) 8 9 # 最も類似度が高い位置と低い位置を取得 10 minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(result) 11 12 13 if maxVal >= 0.8: 14 img[ 15 maxLoc[1] : maxLoc[1] + templ.shape[0], 16 maxLoc[0] : maxLoc[0] + templ.shape[1], 17 ] = 255 18 19 return img

投稿2020/06/30 19:40

編集2020/06/30 19:53
tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

branch

2020/07/01 02:40 編集

おはようございます. ご回答ありがとうございます. 無事実装できました!(本当に本当に初歩的なところだったとは....!) 類似度に関してはトリミング元との比較なので100%では?と思っていたのですが,少し実験的に閾値を探ってみます. OpenCV公式によると,どうやら二次元畳み込みを内部的に処理しているようですね. http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_template_matching/py_template_matching.html ひとまず,ご忠告通り少し閾値を下げて実行します. ありがとうございました.
tiitoi

2020/07/01 01:54

類似度算出の式を見ればわかりますが、テンプレート画像が元画像の一部を切り出したものであれば、理論的には1になる箇所はあります。 https://docs.opencv.org/master/df/dfb/group__imgproc__object.html#gga3a7850640f1fe1f58fe91a2d7583695dab65c042ed62c9e9e095a1e7e41fe2773 ただ、その場合でも類似度は浮動小数点演算で丸め誤差を含むので、浮動小数点数の比較で == を使ってしまうのはまずいですね https://note.nkmk.me/python-math-isclose/
branch

2020/07/01 03:36

ご丁寧にありがとうございます. 95%~90%で固めていこうと思っております. また,私事ではございますが,フォローさせていただきました. また機会がございましたら,ぜひよろしくお願いします.
guest

0

この入力は誤りです.

投稿2020/06/30 22:11

編集2020/06/30 22:16
branch

総合スコア70

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問