定义:
如果元素为,则(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}
假设上面的图像是8乘8的矩阵A,自然数为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 - 这种代码在这种情况下的效率如何?使用矢量符号无法解决这个问题吗?
非常感谢任何答案。提前谢谢!
答案 0 :(得分:3)
此刻不在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循环,只需内置(并且非常快)2d卷积和max
函数。
阈值条件C>0.9
,只是为了说明需要一个由crs
强度加权的阈值。在这种情况下,我在colvolution行(crs
)中对crs/sum(crs(:))
进行了标准化,因此,如果A
是一个二进制矩阵,如示例所示,您会发现最小标准化十字的卷积将离开交叉点为1
的像素值,而其他像素值小于1(这就是我任意选择0.9的原因)。因此,您可以将阈值替换为C==1
,如果它始终是二进制的。
另一种可视化十字架位置的方法就是看C.*(C==1)
。这将生成一个大小为A
且只有1
s的矩阵,只有在十字架的位置......
对于最大速度,您可以考虑将其写为单行,例如:
[x y]=find(conv2(A,[0 1 0 ; 1 1 1 ; 0 1 0]./5,'same')==1);
答案 1 :(得分: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)