Skip to content

Add mask to match template demo#6773

Merged
opencv-pushbot merged 4 commits intoopencv:masterfrom
acinader:add-mask-to-match-template-demo
Jul 18, 2016
Merged

Add mask to match template demo#6773
opencv-pushbot merged 4 commits intoopencv:masterfrom
acinader:add-mask-to-match-template-demo

Conversation

@acinader
Copy link
Copy Markdown

@acinader acinader commented Jul 5, 2016

Accept and use optional mask argument for MatchTemplate_Demo.

Useful for visualizing effect of a mask on template matching.

this replaces #6758 which was giving me some problems with github.... you can close this if you want to re-open #6758 instead?

@acinader
Copy link
Copy Markdown
Author

acinader commented Jul 5, 2016

I can rebase if you prefer, but i think it makes sense to have two commits

template image (patch).

While the patch must be a rectangle it may be that not all of the
rectangle is relevent. In such a case, a mask can be used to isolate the portion of the patch
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

relevAnt

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ugh. installing spell checker. thanks.

@apavlenko apavlenko self-assigned this Jul 8, 2016
@acinader
Copy link
Copy Markdown
Author

acinader commented Jul 11, 2016

@apavlenko thanks for the feedback. I think i've covered all your issues in b53b8d9

1. Explain grayscale input still read as three channel
2. Fix typo
3. Add more details to image match explanation to include the use of masks
@acinader acinader force-pushed the add-mask-to-match-template-demo branch from b53b8d9 to 0ed250c Compare July 11, 2016 19:22
@snosov1
Copy link
Copy Markdown
Contributor

snosov1 commented Jul 14, 2016

Although, it's not necessarily the issue of this PR, but a wording in the documentation made me wonder about the implementation. The statement that took my attention was:

A value between black and white will include some of the match in proportion to how dark the pixel is.

  1. According to the implementation this statement is incorrect for masks of CV_8U depth, see https://github.com/opencv/opencv/blob/master/modules/imgproc/src/templmatch.cpp#L860 . The compare call makes all non-zero values equal to 255, the consequent conversion makes them equal to 1.
  2. Then, for CV_32F masks this statement seems to hold (which is already strange, since the 2 options don't work the same). But looking at the implementation, I don't think it's implemented correctly (or I just don't get it):
    1. For CV_TM_CCORR_NORMED metric, I would expect that the implementation will simply multiply the template by mask. But it does something more involved.
    2. For CV_TM_SQDIFF metric, I would expect it to multiply the squared bracket by mask. It looks like the implementation tries to replace the square of sum into separate units and multiply them by mask individually. But to me, the evaluation doesn't look correct.

So, @acinader are you familiar with the implementation and can you confirm whether it works correctly?

Also, it looks like @wangyan42164 is the author of the implementation. Is that so? If yes, can you, please, comment as well?

@acinader
Copy link
Copy Markdown
Author

@snosov1 I am not familiar with the implementation. I am coming at it as a user and trying to figure out how templates and masks work by trial and error (which is why I am adding the mask to the sample so I can play and see the results.)

FWIW, it would be helpful to have some docs and unit tests with some sample images that could be a guide for how to prepare a template and mask. Unfortunately, I don't have enough understanding of what is going on to drive that process, but I'd be glad to help.

@snosov1
Copy link
Copy Markdown
Contributor

snosov1 commented Jul 15, 2016

Ok, then. I think we can merge this particular PR after a couple of small changes in wording. However, we'll probably need to submit a separate ticket about the issues I highlighted (different behavior for CV_8U and CV_32F, correctness of implementation).

So, I suggest that you replace the following paragraph with the proposed text, and if you agree with it - please, update the PR and we'll merge it.

The mask should be a grayscale image where each pixel contains some value from black to white.
Pixels that are white are fully included in calculating the best match. Pixels that are black
are excluded from the match. A value between black and white will include some of
the match in proportion to how dark the pixel is. Although the image should be a grayscale whose
output from the file command should look something like: "PNG image data, 128 x 128, 8-bit gray
+alpha, non-interlaced", opencv will read the image into an rgb matrix that will be applied
during the image match.

The mask should have a CV_8U or CV_32F depth and the same number of channels
as the template image. In CV_8U case, the mask values are treated as binary,
i.e. zero and non-zero. In CV_32F case, the values should fall into [0..1]
range and the template pixels will be multiplied by the corresponding mask pixel
values. Since the input images in the sample have the CV_8UC3 type, the mask
is also read as color image.

@acinader
Copy link
Copy Markdown
Author

@snosov1 updated to reflect your suggestion. FYI, your explanation is very helpful to me, so a good change!

thanks.

@snosov1
Copy link
Copy Markdown
Contributor

snosov1 commented Jul 15, 2016

@apavlenko, I'm ok with this PR.

I'll create a separate issue with my concerns about the implementation.

@apavlenko
Copy link
Copy Markdown
Contributor

👍

@Cartucho
Copy link
Copy Markdown
Contributor

Cartucho commented Feb 19, 2017

@acinader could you send me the images you used for the mask part?
I'm trying to do a Python and Java version on this

The images I need are these 3:
screenshot from 2017-02-19 18-11-03

@sturkmen72
Copy link
Copy Markdown
Contributor

@Cartucho
Copy link
Copy Markdown
Contributor

Thanks! @sturkmen72

@ai-snow
Copy link
Copy Markdown

ai-snow commented Aug 29, 2017

@Cartucho Did you get this to work? When I run these images through the matchTemplate function I get incorrect results (see red dot in image where the result deemed match):

image

My test code:

OpenCV => 3.3
Operating System => Windows

import numpy as np

im_main = cv2.imread(r'D:\Code\Python\TestTemplateMatchMask\lena_tmpl.jpg', cv2.IMREAD_UNCHANGED)
im_temp = cv2.imread(r'D:\Code\Python\TestTemplateMatchMask\tmpl.png', cv2.IMREAD_UNCHANGED)
im_mask = cv2.imread(r'D:\Code\Python\TestTemplateMatchMask\mask.png', cv2.IMREAD_UNCHANGED)

sp = cv2.split(im_main)
a = np.zeros_like(sp[0])
im_main = cv2.merge([np.array(sp[0]),np.array(sp[1]),np.array(sp[2]),a])

res = cv2.matchTemplate(im_main, im_temp, cv2.TM_SQDIFF, im_mask)

min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

cv2.rectangle(im_main, (min_loc[0],min_loc[1]),(min_loc[0]+10,min_loc[1]+10),(0,0,255), 10)

print(min_val)
print(min_loc)

cv2.imshow('dfjai', im_main)
cv2.waitKey(0)

@apavlenko
@snosov1
@acinader
Any thoughts? I've also commented on #6919

And by the way, remove the mask from the function call and the results do not change at all. As I mentioned in #6919, I don't think this code is implemented correctly.

@Cartucho
Copy link
Copy Markdown
Contributor

@ai-snow Did you have a look at this tutorial?

@ai-snow
Copy link
Copy Markdown

ai-snow commented Aug 29, 2017

@Cartucho

Thanks for referring to that document. However, this does not change my opinion that the implementation in OpenCV for match templates with a mask is incorrect. (I'm not asking a question about my implementation in my comment; that was there for completeness)

@ai-snow
Copy link
Copy Markdown

ai-snow commented Aug 29, 2017

@Cartucho
Did you get it to work in python? I used that tutorial as a starting point. Seemed pretty straightforward in terms of seeing it up.

@Cartucho
Copy link
Copy Markdown
Contributor

Cartucho commented Aug 30, 2017

@ai-snow Shouldn't you use res = cv2.matchTemplate(im_main, im_temp, cv2.TM_SQDIFF, None, im_mask) instead of res = cv2.matchTemplate(im_main, im_temp, cv2.TM_SQDIFF, im_mask)?

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants