【问题标题】:Fastest way to find a cross in a matrix在矩阵中找到交叉的最快方法
【发布时间】:2015-02-21 09:06:00
【问题描述】:


定义:
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} .


假设上图是 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 - 在那种情况下这段代码的效率如何?这个问题不能用矢量符号来解决吗?

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

【问题讨论】:

  • 你并没有真正定义什么是十字架。 ones(3,4) 是否包含两个十字架?
  • 感谢您的提醒。我添加了一个定义。 one(3, 4) 包含两个十字架。

标签: matlab


【解决方案1】:

目前不在 matlab 附近,但这是我要做的。假设 A 是二进制的(只有 0'a 和 1's):

 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/sum(crs(:))) 中对 crs 进行了归一化,因此如果 A 是示例中的二进制矩阵,您会发现最小归一化交叉的卷积将留下像素的值十字在1,而其他像素将小于1(这就是我随意选择0.9的原因)。因此,您可以将阈值替换为 C==1,如果它始终是二进制文件。

另一种可视化十字架位置的方法是查看C.*(C==1)。这将生成一个大小为A 的矩阵,其中1s 仅在十字架所在的位置......

编辑:

为了获得最大速度,您可以考虑将其写为单行,例如:

[x y]=find(conv2(A,[0 1 0 ; 1 1 1 ; 0 1 0]./5,'same')==1); 

【讨论】:

  • 打败我!我会将>0.9 替换为==nnz(crs)
  • 理论上它应该是==1,如果crs被标准化,这就是过滤器是crs./sum(crs(:))的原因,我只是不确定A是否总是二进制等等。 ..
  • 哦,我没看到你在规范化crs
  • 抱歉回复晚了。我意识到我的问题没有正确表述。我已经对这个问题进行了更新。我希望这不会改变您建议的解决方案。谢谢!
  • @user1497133:关于您更新的问题,这个答案正是您想要的。对于交叉要求对角邻居为零的替代方案,需要以crs=[-1 1 -1 ; 1 1 1 ; -1 1 -1]; 开头。
【解决方案2】:

使用位掩码:

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)

【讨论】:

  • 当然,对于二进制过滤器的特殊情况,例如“cross”,逻辑条件可以正常工作,甚至可能更快+1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-27
  • 2012-05-18
  • 2021-11-25
  • 2021-11-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多