enter image description here


Определение:
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 - насколько эффективен этот код в этой ситуации? Нельзя ли решить эту проблему с помощью векторной записи?

Мы очень ценим любой ответ. Заранее спасибо!

4
RazGo 21 Фев 2015 в 00:21

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); 
3
bla 21 Фев 2015 в 01:06

Использование битовых масок:

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)
1
Iban Cereijo 21 Фев 2015 в 00:04