Это производная от предыдущего сообщения, где я дал ответ здесь: шаблон Matlab, соответствующий только 0 (или 1) в матрице
Однако в этом решении использовались циклы for
, что весьма неэффективно. Таким образом, мы можем использовать im2col
, bsxfun
и col2im
, чтобы сделать это быстрее. im2col
берет перекрывающиеся области изображения и помещает их в отдельные столбцы. По сути, это берет скользящие окна вашего изображения, как и при любой пространственной фильтрации изображения, собирает все пиксели в скользящем окне и помещает каждое окно в виде отдельных столбцов.
Предположим, что размер вашего шаблона равен M x N
, а размер вашего изображения, в котором вы хотите выполнить поиск, равен R x C
, и предположим, что ваш шаблон изображения называется imTemplate
, а изображение, которое вы хотите найти, имеет значение imSearch
, мы можем выполнить следующую настройку. Предположим также, что оба изображения являются бинарными.
[M, N] = size(imTemplate);
[R, C] = size(imSearch);
%// Cast to double for precision
imTemplate = im2double(imTemplate);
imSearch = im2double(imSearch);
neigh = im2col(imSearch, [M, N]);
templateCol = imTemplate(:); %// Ensures we place template into single column
Теперь вы хотите исключить все пиксели, которые находятся внутри круговой границы. Таким образом, мы можем инвертировать изображение, чтобы черные пиксели стали белыми, а затем удалить все пиксели вокруг границы. Это должно дать нам внутреннюю часть круга.
imInvert = ~imTemplate;
imInvertNoBorder = imclearborder(imInvert, 8); %// Search 8-pixel neighbourhood
Мы будем использовать это, чтобы выяснить, какие пиксели мы собираемся удалить из поиска. Это можно сделать:
rowsToRemove = imInvertNoBorder(:) == 1;
Теперь, что мы можем сделать, так это, наконец, удалить те пиксели, которые находятся внутри круга, чтобы их не искали в нашей схеме корреляции.
neigh(rowsToRemove,:) = [];
Теперь мы можем вычислить NCC по всем этим столбцам. Если вы помните, NCC между двумя сигналами выглядит следующим образом:
![NCC](https://i.stack.imgur.com/NYFQj.gif)
(источник: www.jot.fm)
Таким образом, нам нужно вычесть среднее значение из каждой окрестности, а также нам нужно вычесть среднее значение из каждого из столбцов. Затем мы вычисляем формулу, как показано выше. Мы можем легко сделать это векторизованным в MATLAB следующим образом:
neighMeanSubtract = bsxfun(@minus, neigh, mean(neigh));
templateMeanSubtract = templateCol - mean(templateCol);
Мы можем вычислить числитель NCC для каждой окрестности (до суммирования) следующим образом:
numerator = bsxfun(@times, neighMeanSubtract, templateMeanSubtract);
Теперь все, что нам нужно сделать, это суммировать все столбцы, и это даст нам наш окончательный числитель:
sumNumerator = sum(numerator);
Знаменатель можно вычислить так:
denominator1 = sqrt(sum(neighMeanSubtract.*neighMeanSubtract));
denominator2 = sqrt(sum(templateMeanSubtract.*templateMeanSubtract));
sumDenominator = denominator1 .* denominator2;
Наконец, наш NCC можно вычислить следующим образом:
NCC = sumNumerator ./ sumDenominator;
Вы заметите, что это одна строка значений. Каждая строка соответствует выходу, определенному в окрестности. Таким образом, нам также нужно преобразовать это обратно в матрицу, поэтому вы можете использовать col2im
:
finalOutput = col2im(NCC, [M, N], [R, C]);
Приведенный выше оператор возьмет перекрывающиеся окрестности M x N
, определенные в NCC, и изменит их форму, чтобы она стала матрицей R x C
. Иногда вы получаете сообщение об ошибке делите на ноль, особенно если окно поиска соседей однородно. Таким образом, вы получите NaN
чисел. Предполагается, что области без изменений не имеют корреляции при обработке изображений, поэтому давайте обнулим эти местоположения:
finalOutput(isnan(finalOutput)) = 0;
Если вы хотите найти место с наибольшей корреляцией, просто выполните:
[rowNCC, colNCC] = find(finalOutput == max(finalOutput(:)));
Если вы хотите интерпретировать отрицательную корреляцию, это полностью зависит от вашего приложения. Если вы хотите убедиться, что ваш алгоритм сопоставления с шаблоном неизменен к чередованию, вам следует проверить максимальное количество абсолютных значений. Отрицательная корреляция просто означает, что совпадение между шаблоном и окрестностью просто меняется. Таким образом, лучший способ найти лучшее соседство:
maxCoeff = max(abs(finalOutput(:)));
[rowNCC, colNCC] = find(abs(finalOutput) == maxCoeff);
Для вашего удовольствия от копирования и вставки вот весь код:
function [rowNCC, colNCC] = testCorr(imTemplate, imSearch)
[M, N] = size(imTemplate);
[R, C] = size(imSearch);
%// Cast to double for precision
imTemplate = im2double(imTemplate);
imSearch = im2double(imSearch);
neigh = im2col(imSearch, [M, N]);
templateCol = imTemplate(:); %// Ensures we place template into single column
imInvert = ~imTemplate;
imInvertNoBorder = imclearborder(imInvert, 8); %// Search 8-pixel neighbourhood
rowsToRemove = imInvertNoBorder(:) == 1;
neigh(rowsToRemove,:) = [];
neighMeanSubtract = bsxfun(@minus, neigh, mean(neigh));
templateMeanSubtract = templateCol - mean(templateCol);
numerator = bsxfun(@times, neighMeanSubtract, templateMeanSubtract);
sumNumerator = sum(numerator);
denominator1 = sqrt(sum(neighMeanSubtract.*neighMeanSubtract));
denominator2 = sqrt(sum(templateMeanSubtract.*templateMeanSubtract));
sumDenominator = denominator1 .* denominator2;
NCC = sumNumerator ./ sumDenominator;
finalOutput = col2im(NCC, [M, N], [R, C]);
finalOutput(isnan(finalOutput)) = 0;
maxCoeff = max(abs(finalOutput(:)));
[rowNCC, colNCC] = find(abs(finalOutput) == maxCoeff);
end
Удачи!
person
rayryeng
schedule
12.06.2014
normxcorr2
тоже работает в реальном времени. Этот пост был в основном для новичков в MATLAB, но если вам нужно что-то более реальное, я не вижу никакого способа использовать Image Processing Toolbox, поэтому в OP этого поста собирался использовать MEX. - person rayryeng   schedule 12.06.2014colfilt
иim2col
. Вы хотите, чтобы я написал решение для вас? - person rayryeng   schedule 12.06.2014