Шаблон соответствия Matlab с использованием FFT

Я борюсь с совпадением шаблонов в домене Фурье в Matlab. Вот мои изображения (художник - РамаламаКурезы на DeviantArt):

possum.jpg possum_ear.jpg

Моя цель - разместить ограничительную рамку вокруг уха опоссума, как этот пример (где я выполнил сопоставление шаблонов с помощью normxcorr2):

Цель: опоссума опоссума

Вот код Matlab, который я использую:

clear all; close all;

template = rgb2gray(imread('possum_ear.jpg'));
background = rgb2gray(imread('possum.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)));

%% 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;
position = [xpeak(1)-tx, ypeak(1)-ty, tx, ty];
imshow(background, 'Parent', hAx);
imrect(hAx, position);

Код не функционирует должным образом - он не определяет правильный регион. Это неудачный результат - неправильная область помещена в коробку:  сбой соответствия шаблонов

Это поверхностный график корреляций для неудачного совпадения: график сюжета для неудачного сопоставления шаблонов

Надеюсь, ты можешь помочь! Благодарю.

Ответ 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);

С этим я получаю следующее изображение:

введите описание изображения здесь

Я также получаю следующее при отображении поверхностного графика спектра поперечной мощности:

введите описание изображения здесь

Существует четкий определенный пик, где остальная часть вывода имеет очень малый отклик. Это на самом деле свойство фазовой корреляции, и, очевидно, расположение максимального значения четко определено, и именно там находится шаблон.


Надеюсь, это поможет!