Ответ 1
То, что вы делаете в своем коде, на самом деле не является корреляцией. Вы используете шаблон и выполнение свертки с входным изображением. Если вы помните из преобразования Фурье, умножение спектров двух сигналов эквивалентно свертке двух сигналов во временной/пространственной области.
В основном, что вы делаете, так это то, что вы используете шаблон в качестве ядра и используете его для фильтрации изображения. Затем вы находите максимальный ответ этого результата и то, что считается тем, где находится шаблон. Если ответ в коробке имеет смысл, потому что этот регион полностью белый, и использование шаблона в качестве ядра с полностью белым регионом даст вам очень большой ответ, поэтому он скорее всего определил, что область будет максимальной ответ. В частности, область будет иметь множество высоких значений (~ 255 или около того) и, естественно, выполнение свертки с шаблоном патча, и этот регион даст вам очень большой результат из-за того, что операция является взвешенной суммой. Таким образом, если вы использовали шаблон в темной области изображения, результат был бы небольшим - это неверно, потому что шаблон также состоит из темных пикселей.
Однако вы можете использовать преобразование Фурье, чтобы определить, где находится шаблон, но я бы рекомендовал вместо этого использовать Phase Correlation. В принципе, вместо вычисления умножения двух спектров вместо этого вы вычисляете спектр поперечной мощности. Спектр поперечной мощности R
между двумя сигналами в частотной области определяется как:
Источник: Wikipedia
Ga
и Gb
- это исходное изображение и шаблон в частотной области, а *
- сопряженный. o
- это то, что известно как продукт Адамара или элементный продукт. Я также хотел бы отметить, что деление числителя и знаменателя этой фракции также элементарно. Используя спектр поперечной мощности, если вы найдете здесь (x,y)
местоположение, которое дает абсолютный максимальный ответ, здесь шаблон должен быть расположен в фоновом изображении.
Таким образом, вам просто нужно изменить строку кода, которая вычисляет "корреляцию", чтобы вместо этого вычислять спектр поперечной мощности. Однако я хотел бы указать на что-то очень важное. Когда вы выполняете normxcorr2
, корреляция начинается прямо в верхнем левом углу изображения. Соответствие шаблону начинается в этом месте, и оно сравнивается с окном, которое является размером шаблона, где верхний левый угол является началом. При поиске местоположения совпадения с шаблоном местоположение относится к верхнему левому углу совпадающего окна. После вычисления normxcorr2
вы обычно добавляете половину строк и половину столбцов максимального ответа, чтобы найти центральное расположение.
Поскольку мы более или менее выполняем те же операции для сопоставления шаблонов (скользящие окна, корреляции и т.д.) с FFT/частотной областью, когда вы заканчиваете поиск пика в этом массиве корреляции, вы должны также принимать это во внимание. Тем не менее, ваш вызов 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);
С этим я получаю следующее изображение:
Я также получаю следующее при отображении поверхностного графика спектра поперечной мощности:
Существует четкий определенный пик, где остальная часть вывода имеет очень малый отклик. Это на самом деле свойство фазовой корреляции, и, очевидно, расположение максимального значения четко определено, и именно там находится шаблон.
Надеюсь, это поможет!