0

I need find all images within image, for this idea I have found great solution:

import cv2
import numpy as np

img_rgb = cv2.imread('source.png')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('block.png', 0)
w, h = template.shape[::-1]

res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF)

threshold = 0.8
loc = np.where(res >= threshold)

for pt in zip(*loc[::-1]):
    cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2)

# cv2.imwrite('res.png', img_rgb)
cv2.imshow('output', img_rgb)
cv2.waitKey(0)

Source data:

https://i.sstatic.net/cE5bM.png (source)

https://i.sstatic.net/BgzAA.png (template)

I tried to use this code but failed.

What I see now: enter image description here

What I expected to get: enter image description here

What's wrong? I am using python 3.5 and opencv 3.3.0.10

PS: very interesting thing that another solution works perfect but finds only 1 match (best one)

4
  • tune your threshold. In addition, openCV's template matching doesn't consider alpha channel or masks, which might be much better in your task.
    – Micka
    Commented Oct 14, 2017 at 8:16
  • threshold tuning will works for concrete image, but I have different kind of images, need universal solution
    – ValueError
    Commented Oct 15, 2017 at 2:47
  • 1
    try coding your own template matching with support of alpha channel or masks.
    – Micka
    Commented Oct 15, 2017 at 6:38
  • thanks, I will try
    – ValueError
    Commented Oct 22, 2017 at 6:44

1 Answer 1

1

I am definitely no expert on OpenCV and it's various template matching methods (though coincidentally I had started to play around with it).

However, a couple of things in your example stand out.

You use the cv2.TM_CCOEFF method which gives results that are universally way above the 0.8 threshold. So everywhere in the image matches giving a massive red rectangle blob. If you want to use this method try cv2.TM_CCOEFF_NORMED to normalise the results to below 1.

But my best 10 minute attempt was using;

method = cv2.TM_CCORR_NORMED

and setting

threshold = 0.512

which gave;

enter image description here

This is fairly unsatisfactory though because the threshold had to be 'tuned' fairly precisely to remove most of the mismatches. There is undoubtedly a better way to get a more reliable stand-out match.

3
  • Thanks a lot for participation, but I will use different images and it's not acceptable to tune threshold for each image, so that solution not ready to work.
    – ValueError
    Commented Oct 15, 2017 at 2:50
  • Also interesting thing [stackoverflow.com/a/15147009/6578528](that this solution) works perfect but find only 1 image instead of all, could you please change that solution to find all images? my skills too low here
    – ValueError
    Commented Oct 15, 2017 at 2:51
  • 1
    To be fair I was not trying to produce a complete solution for you. You asked why you got the solid red image result and that's what my answer attempted to explain. I think this template approach should still work well on your images, but it might take some additional research to work out how best to apply it.
    – Paul
    Commented Oct 16, 2017 at 0:07

Not the answer you're looking for? Browse other questions tagged or ask your own question.