您在代码中所做的实际上根本不相关。您正在使用模板并且执行卷积与输入图像。如果您还记得傅里叶变换,两个信号的频谱相乘相当于两个信号在时间/空间域中的卷积。
基本上,您所做的就是使用模板作为内核并使用它来过滤图像。然后,您将找到此输出的最大响应,这就是模板所在的位置。响应被装箱的地方是有意义的,因为该区域是完全白色的,并且使用模板作为具有完全白色区域的内核会给您一个非常大的响应,这就是为什么它最有可能确定该区域是最大的回复。具体来说,该区域将具有很多高值(~255 左右),并且自然地与模板补丁执行卷积,并且由于操作是加权和,该区域将为您提供非常大的输出。因此,如果您在图像的暗区域使用模板,则输出会很小 - 这是错误的,因为模板也由暗像素组成。
但是,您当然可以使用傅立叶变换来定位模板的位置,但我建议您使用相位相关性 https://en.wikipedia.org/wiki/Phase_correlation反而。基本上,您不是计算两个谱的乘积,而是计算互功率谱。互功率谱R
频域中两个信号之间的关系定义为:
Source: Wikipedia https://en.wikipedia.org/wiki/Phase_correlation
Ga
and Gb
是频域中的原始图像和模板,并且*
是共轭。这o
就是所谓的哈达玛积或元素积。我还想指出,该分数的分子和分母的除法也是逐元素的。使用互功率谱,如果您发现(x,y)
产生绝对最大响应的位置,这是模板应位于背景图像中的位置。
因此,您只需更改计算“相关性”的代码行,以便它计算互功率谱。不过,我想指出一些非常重要的事情。当你表演时normxcorr2
,相关性从图像的左上角开始。模板匹配从该位置开始,并与以模板大小为原点的窗口进行比较。当查找模板匹配的位置时,该位置相对于匹配窗口的左上角。一旦你计算normxcorr2
,传统上将最大响应的一半行和一半列相加来找到中心位置.
因为我们或多或少在 FFT/频域中对模板匹配(滑动窗口、相关性等)进行相同的操作,所以当您完成在该相关数组中找到峰值时,您还必须考虑到这一点。但是,您致电imrect
无论如何,要在模板匹配的位置周围绘制一个矩形,都会在边界框的左上角进行绘制,因此无需在此处进行偏移。因此,我们将稍微修改该代码,但在使用此代码时要记住偏移逻辑,以便稍后找到匹配的中心位置。
我还修改了您的代码,以直接从 StackOverflow 读取图像,以便其可重现:
clear all; close all;
template = rgb2gray(imread('https://i.stack.imgur.com/6bTzT.jpg'));
background = rgb2gray(imread('https://i.stack.imgur.com/FXEy7.jpg'));
%% calculate padding
bx = size(background, 2);
by = size(background, 1);
tx = size(template, 2); % used for bbox placement
ty = size(template, 1);
%% fft
%c = real(ifft2(fft2(background) .* fft2(template, by, bx)));
%// Change - Compute the cross power spectrum
Ga = fft2(background);
Gb = fft2(template, by, bx);
c = real(ifft2((Ga.*conj(Gb))./abs(Ga.*conj(Gb))));
%% find peak correlation
[max_c, imax] = max(abs(c(:)));
[ypeak, xpeak] = find(c == max(c(:)));
figure; surf(c), shading flat; % plot correlation
%% display best match
hFig = figure;
hAx = axes;
%// New - no need to offset the coordinates anymore
%// xpeak and ypeak are already the top left corner of the matched window
position = [xpeak(1), ypeak(1), tx, ty];
imshow(background, 'Parent', hAx);
imrect(hAx, position);
这样,我得到了以下图像:
在显示交叉功率谱的曲面图时,我还得到以下结果:
有一个明确定义的峰值,其余输出的响应非常小。这实际上是相位相关性的一个属性,很明显,最大值的位置是明确定义的,这就是模板所在的位置。
希望这可以帮助!