在矩阵中找到十字架的最快方法

时间:2015-02-20 21:21:06

标签: matlab

enter image description here


定义:
如果元素为,则(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 - 这种代码在这种情况下的效率如何?使用矢量符号无法解决这个问题吗?

非常感谢任何答案。提前谢谢!

2 个答案:

答案 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查找峰值。 xy是您的交叉位置的坐标。不需要使用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)