Amitay is correct in his assessment. BTW, the code that you took comes from the following post: Matlab Template Matching Using FFT.
The code is only designed to detect one match from the template you specify. If you wish to detect multiple templates, there are various methodologies you can try each with their own advantages and disadvantages:
- Use a global threshold and from the cross power spectrum, any values that surpass this threshold deem that there is a match.
- Find the largest similarity in the cross power spectrum, and anything that is some distance away from this maximum would be deemed that there is a match. Perhaps a percentage away, or one standard deviation away may work.
- Try to make a histogram of the unique values in the cross power spectrum and find the point where there is a clear separation between values that are clearly uncorrelated with the template and values that are correlated. I won't implement this for you here because it requires that we look at your image then find the threshold by examining the histogram so I won't do that for you. Instead you can try the first two cases and see where that goes.
You will have to loop over multiple matches should they arise, so you'll need to loop over the code that draws the rectangles in the image.
Case #1
The first case is very simple. All you have to do is modify the find
statement so that instead of searching for the location with the maximum, simply find locations that exceed the threshold.
Therefore:
%% find peak correlation
thresh = 0.1; % For example
[ypeak, xpeak] = find(c >= thresh);
Case #2
This is very similar to the first case but instead of finding values that exceed the threshold, determine what the largest similarity value is (already done), and threshold anything that is above (1 - x)*max_val
where x
is a value between 0 and 1 and denotes the percentage you'd like away from the maximum value to be considered as match. Therefore, if you wanted at most 5% away from the maximum, x = 0.05
and so the threshold now becomes 0.95*max_val
. Similarly for the standard deviation, just find what it is using the std
function and ensuring that you convert it into one single vector so that you can compute the value for the entire image, then the threshold becomes max_val - std_val
where std_val
is the standard deviation of the similarity values.
Therefore, do something like this for the percentage comparison:
%% find peak correlation
x = 0.05; % For example
[max_c, imax] = max(abs(c(:)));
[ypeak, xpeak] = find(c >= (1-x)*max_c);
... and do this for the standard deviation comparison:
std_dev = std(abs(c(:)));
[max_c, imax] = max(abs(c(:)));
[ypeak, xpeak] = find(c >= (max_c - std_dev));
Once you finally establish this, you'll see that there are multiple matches. It's now a point of drawing all of the detected templates on top of the image. Using the post that you "borrowed" the code from, the code to draw the detected templates can be modified to draw multiple templates.
You can do that below:
%% display best matches
tx = size(template, 2);
ty = size(template, 1);
hFig = figure;
hAx = axes;
imshow(background, 'Parent', hAx);
hold on;
for ii = 1 : numel(xpeak)
position = [xpeak(ii), ypeak(ii), tx, ty]; % Draw match on figure
imrect(hAx, position);
end