Определение:
A (i, j) = 1 - середина креста, если элементы
A (i-1, j) = 1
A (i + 1, j) = 1
A (i, j + 1) = 1
A (i, j-1) = 1.
Вместе элементы и средняя точка образуют крест в матрице A, где A - это как минимум матрица 3 на 3, а i , j ∈ ℕ \ {0} .
Предположим, что изображение выше представляет собой матрицу A размером 8 на 8 с натуральными числами 1, 2, 3 ... в качестве элементов. Из этого определения в матрице всего 3 креста. Кресты имеют середины на A (2,2), A (5, 4) и A (5, 5).
Я хочу написать функцию, которая находит количество крестиков в матрице A. У меня есть идея, но я не уверен, что она наиболее оптимальная. Вот его псевдокод:
ITERATE FROM row 2 TO row 7
ITERATE FROM column 1 TO column 8
IF current element contains 1
INCREMENT xcount by 1
IF xcount >= 3
CHECK IF counted 1:s is part of a cross
ELSE IF xcount IS NOT 0
SET xcount to 0
Идея состоит в том, чтобы перебирать каждый столбец от строки 2 до строки 7. Если я нахожу 3 последовательных 1: s в одной строке, я немедленно проверяю, принадлежит ли 1: s кресту. Это должно работать, но представьте, что у вас очень большая матрица A - насколько эффективен этот код в этой ситуации? Нельзя ли решить эту проблему с помощью векторной записи?
Мы очень ценим любой ответ. Заранее спасибо!
2 ответа
На данный момент не рядом с Matlab, но я бы сделал это. Предполагая, что A
является двоичным (имеет только 0'a и 1):
crs=[0 1 0 ; 1 1 1 ; 0 1 0]; % a minimal "cross" filter
C=conv2(A,crs./sum(crs(:)),'same'); % convolve A with it
[x y]=find(C>0.9); % find x,y positions of the crosses by looking
% for peak values of C
Так что вы в основном сворачиваете с «минимальным» (нормализованным) перекрестием (crs
) и ищите пики, используя max
. x
и y
- координаты ваших перекрестных позиций. Нет необходимости использовать циклы for, только встроенная (и довольно быстрая) двумерная свертка и функция max
.
Условие порога C>0.9
просто для иллюстрации того, что должен быть порог, взвешенный по интенсивности crs
. В этом случае я нормализовал crs
в строке колволюции (crs/sum(crs(:))
), поэтому, если A
является двоичной матрицей, как в примере, вы обнаружите, что свертка минимального нормализованного креста оставит значение пикселя, в котором крест находится на 1
, тогда как другие пиксели будут меньше 1 (поэтому я произвольно выбрал 0,9). Таким образом, вы можете заменить порог на C==1
, если он всегда двоичный.
Другой способ визуализировать положение креста - просто взглянуть на C.*(C==1)
. Это сгенерирует матрицу размером A
с 1
только там, где были кресты ...
РЕДАКТИРОВАТЬ:
Для максимальной скорости вы можете написать его как однострочник, например:
[x y]=find(conv2(A,[0 1 0 ; 1 1 1 ; 0 1 0]./5,'same')==1);
Использование битовых масок:
ux = [false(size(A,1),1) (A(:,3:end) & A(:,2:end-1) & A(:,1:end-2)) false(size(A,1),1)]
uy = [false(1,size(A,2)); (A(3:end,:) & A(2:end-1,:) & A(1:end-2,:)); false(1, size(A,2))]
u = ux & uy
[x y] = find(u)
Похожие вопросы
Связанные вопросы
Новые вопросы
matlab
MATLAB - это высокоуровневая языковая и интерактивная среда программирования для численных расчетов и визуализации, разработанная MathWorks. Не используйте оба тега [matlab] и [octave], если явно не задан вопрос о сходстве или различии между ними. При использовании этого тега, пожалуйста, укажите версию MATLAB, с которой вы работаете (например, R2017a).