То, что вы делаете в своем коде, на самом деле вовсе не корреляция. Вы используете шаблон и выполняете свертку с входным изображением. Если вы помните из преобразования Фурье, умножение спектров двух сигналов эквивалентно свертке двух сигналов во временной/пространственной области.
По сути, вы используете шаблон в качестве ядра и используете его для фильтрации изображения. Затем вы находите максимальный ответ этого вывода, и это то, что считается тем, где находится шаблон. Когда ответ помещается в коробку, это имеет смысл, потому что эта область полностью белая, и использование шаблона в качестве ядра с полностью белой областью даст вам очень большой ответ, поэтому он, скорее всего, идентифицировал эту область как максимальную. отклик. В частности, область будет иметь много высоких значений (~ 255 или около того), и естественное выполнение свертки с патчем шаблона и этой областью даст вам очень большой результат из-за операции, являющейся взвешенной суммой. Таким образом, если вы использовали шаблон в темной области изображения, вывод был бы небольшим, что неверно, поскольку шаблон также состоит из темных пикселей.
Однако вы, безусловно, можете использовать преобразование Фурье, чтобы определить, где находится шаблон, но я бы рекомендовал вам использовать фазовую корреляцию вместо этого. По сути, вместо вычисления умножения двух спектров вы вычисляете спектр перекрестной мощности. Взаимный спектр мощности R
между двумя сигналами в частотной области определяется как:
![](https://upload.wikimedia.org/math/8/8/3/88357aa1d55f79979d1f88b5c6a2678f.png)
Источник: Википедия
Ga
и Gb
— исходное изображение и шаблон в частотной области, а *
— сопряженное. o
— это то, что известно как произведение Адамара или поэлементное произведение. Еще хочу отметить, что деление числителя и знаменателя этой дроби тоже поэлементное. Используя спектр перекрестной мощности, если вы найдете здесь место (x,y)
, которое дает абсолютный максимальный отклик, это то место, где шаблон должен располагаться на фоновом изображении.
Таким образом, вам просто нужно изменить строку кода, которая вычисляет «корреляцию», чтобы вместо этого она вычисляла перекрестный спектр мощности. Однако я хотел бы отметить нечто очень важное. Когда вы выполняете normxcorr2
, корреляция начинается прямо в верхнем левом углу изображения. Сопоставление с шаблоном начинается в этом месте и сравнивается с окном размером с шаблон, где левый верхний угол является источником. При поиске местоположения совпадения шаблона местоположение определяется по отношению к верхнему левому углу сопоставленного окна. После вычисления normxcorr2
вы обычно добавляете половину строк и половину столбцов максимального отклика, чтобы найти центральное местоположение.
Поскольку мы выполняем более или менее те же операции для сопоставления шаблонов (скользящие окна, корреляция и т. д.) с БПФ/частотной областью, когда вы закончите поиск пика в этом массиве корреляции, вы должны также принять это во внимание. . Однако ваш вызов imrect
для рисования прямоугольника вокруг того места, где совпадает шаблон, в любом случае занимает верхний левый угол ограничивающей рамки, поэтому здесь нет необходимости делать смещение. Таким образом, мы собираемся немного изменить этот код, но помните о логике смещения при использовании этого кода на будущее, если хотите найти центральное местоположение совпадения.
Я также изменил ваш код, чтобы читать изображения непосредственно из StackOverflow, чтобы он воспроизводился:
clear all; close all;
template = rgb2gray(imread('http://i.stack.imgur.com/6bTzT.jpg'));
background = rgb2gray(imread('http://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);
При этом я получаю следующее изображение:
![введите описание изображения здесь](https://i.stack.imgur.com/4KcnK.png)
Я также получаю следующее, когда показываю поверхностный график перекрестного спектра мощности:
![введите описание изображения здесь](https://i.stack.imgur.com/FqdgB.png)
Существует четко определенный пик, где остальная часть выходного сигнала имеет очень маленькую характеристику. На самом деле это свойство фазовой корреляции, и поэтому очевидно, что положение максимального значения четко определено, и именно здесь находится шаблон.
Надеюсь это поможет!
person
rayryeng
schedule
19.09.2015