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

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

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

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

Python 3.x

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

5184閲覧

openCVを使い画面上に画像ファイルと一致する画像があるか調べるコードを作りました。しかし、黒い四角の画像が判定できません。

Aki1000

総合スコア78

OpenCV

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

Python 3.x

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2019/07/27 05:24

あちこち写経しながらですが、openCVを使い画面上に画像ファイルと一致する画像があるか調べるコードを作りました。
画像ファイルと一致する画像があれば、その座標を返す。また、画像の類似度の閾値を引数で渡せるようにしてあります。

普通の画像はファイルがBMPでもJPGでも問題なく動きます。

しかし、100×100ほどの黒一色ベタ塗りの四角の画像のファイルを作ったのですが判定できません。
画面上にそういう黒い塊を表示させるまでもなく、そういう画像が存在すると判定されてしまいます。

画像の閾値をthreshold=1.0としても、どうも画像の完全一致検索にはなってないみたいです。
それと、色の違いを認識できているのか………

画面上に100x100くらいの黒い画像が表示されたときに、分かるようにしたいのですが……。
完全画像一致にする方法とか、色の違いをきちんと認識させる方法とか、なにかの方法で黒一色の画像を認識出来るようになると嬉しいです。
よろしくお願いします。

作った画像識別コードImgcheckは以下の通りです。

Python

1import cv2 2import numpy as np 3from PIL import ImageGrab 4 5 6# OpenCVのcv2.imreadは日本語がつかえないなので画像をimedecodeでメモリに一度読み込む 7def imread(filename, flags=cv2.IMREAD_COLOR, dtype=np.uint8): 8 try: 9 n = np.fromfile(filename, dtype) 10 img2 = cv2.imdecode(n, flags) 11 return img2 12 except Exception as e: 13 print(e) 14 return None 15 16 17def chkimg(image, imgminx=0, imgminy=0, imgmaxx=0, imgmaxy=0, threshold=0.9, method=1, equalizeHist=0, gray =0): 18 if imgminx == imgminy == imgmaxx == imgmaxy == 0: 19 imgtemp = ImageGrab.grab() 20 21 else: 22 imgtemp = ImageGrab.grab((imgminx, imgminy, imgmaxx, imgmaxy)) 23 24 Screencap = np.asarray(imgtemp) 25 26 # カラー変換 27 Screenimg = cv2.cvtColor(Screencap, cv2.COLOR_RGB2BGR) 28 if gray ==1: 29 Screenimg = cv2.cvtColor(Screencap, cv2.COLOR_BGR2GRAY) 30 31 # temp = cv2.imread(finalname, 0) 32 #モノクロオプション削除 33 34 temp = imread(image) 35 if gray ==1: 36 temp = imread(image, 0) 37 38 if equalizeHist==1: 39 Screenimg = cv2.equalizeHist(Screenimg) 40 temp =cv2.equalizeHist(temp) 41 42 43 # 画像比較法 44 methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR', 45 'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED'] 46 47 # マッチングテンプレートを実行 48 # print(methods[method]) 49 Comp_result = cv2.matchTemplate(Screenimg, temp, eval(methods[method])) 50 51 min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(Comp_result) 52 # max_valが類似最大値の左上座標 53 54 if max_val < threshold: 55 # print(image + " 一致せず", methods[method],"equalizeHist=",equalizeHist) 56 print(image + " 一致せず") 57 return (0) 58 if max_val >= threshold: 59 print(max_loc) 60 return (max_loc) 61

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

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

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

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

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

guest

回答1

0

ベストアンサー

想像ですが,分母に画像のノルムを用いる評価関数だと全0の際に計算できないという話ではないでしょうか.
(_NORMEDと付くやつは,正規化のために画像のノルムによる除算が入るハズ)

正規化されない方法(TM_SQDIFFなど)の場合でも,うまくいかないのでしょうか?
(用いる評価関数によって計算値が小さいほうが良いか大きいほうが良いのかは異なるのではないでしょうかります.現コードでは常にmax側を見ているので,TM_SQDIFF等を使う場合にはそこを直さないとダメかもです)

投稿2019/07/28 00:51

編集2019/07/30 09:13
fana

総合スコア11632

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

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

Aki1000

2019/07/29 08:18

回答ありがとう御座います。写経して作ったので、Methodの違いとか意識しておりませんでした。 mithod=4としてTM_SQDIFFとしたところ今まで座標(0,0)に黒い四角あるとされていた表示が変わりました。一応なんかの座標を返してはくるのです。 しかしながら、method=4,threshold=1.0としても黒い四角なんか画面上に無いにもかかわらず、真っ白い画面のところとかに反応してヘンな値を返してきます……。
fana

2019/07/29 08:40

回答で述べたように,TM_SQDIFFの場合には,結果は小さい方が良い:すなわち「最小値」の箇所に関して判定を行うべきですが,そのようにしていますか? (当然,thresholdについても,計算される値の意味に対応した値にしないとダメ)
fana

2019/07/29 08:43

OpenCVのリファレンスでmatchTemplateについて調べてください.Method毎に何が計算されるのかが数式で書かれているハズです. テンプレートとの差(違い)を表す値を計算する場合は,結果の値は小さい方が良く, テンプレートとの相関(似具合)を表す値を計算する場合には,結果の値は大きい方が良い,ということになります.
fana

2019/07/29 08:51

matchTemplateの結果を把握するために,一度 Comp_result を可視化してみると良いのではないかと.
Aki1000

2019/07/30 09:12 編集

Comp_resultを可視化してみました。確かにMethod=1の時は全て1が並ぶ行列。逆に0だと全て0。 なのでimgcheckをいじって、Method=4についてはthresholdより小さい時が正解というように治しました。 Method=4の時のみ数値を出しましたがComp_resultの行列の要素は3.3784192e+09などと非常に高い値がでています。真っ黒い画像がある時と無いときで変わるかと思いましたが、どうにもやはり、テンプレートの画像は真っ黒いしかくなのに、真っ白い画面を正解として見てしまっている感じがします…… 画像の完全一致の判定……難しい
fana

2019/07/30 09:10 編集

TM_SQDIFFの場合,計算値はSSD(画素値の差の2乗を総和)なので,値はかなり大きいハズです. 真っ白い個所が最小値(min_val, min_loc)になってしまうということですか? 不思議です. TM_SQDIFF時のComp_resultを適当に正規化(例えば最小値~最大値を0~255にとか)して目視してみたら,白い個所と黒い個所とで結果の差が見えませんか?
Aki1000

2019/07/30 09:20

正規化……それやると便利そうですね……。けど、今一やり方が。 min_valで判定したのにmax_locの表示のままでした。 修正しました。これで試してみます。
Aki1000

2019/07/30 09:24

ところで、 CCOEFFは計算値が大きいほうが良い SQDIFFは計算値が小さいほうが良い ですよね? CCORRも大きい方が良い、でしょうか?
Aki1000

2019/07/30 09:33

動作は上手くいきました! TM_SQDIFFでthreshold=1.0e8としてやることで、出来ました。 うーむ、正規化出来ないと、Comp_resultの表示をいちいちしながらthrethholdの値決めないといけない…… これだけが少しネックです。 しかし、おかげさまで動きました。
fana

2019/07/30 09:48 編集

> 正規化 最小値と最大値が計算できているのですから,正規化後画像を8bit1chで用意して 正規化後の画素値 = (Comp_resultの画素値 - 最小値) * 255 / (最大値-最小値) とすればよいのではないでしょうか. (pythonがわからんので,それをさくっと書く方法は示せませんけど)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問