快速找到像素邻居的方法

Fast way to find the neighboor of pixel

我正在为在图像 D 中找到给定像素 x 的邻居的任务编程,可以公式为:

公式显示像素y满足到像素x的距离为1,则它们是像素x的邻居。这是我的matlab代码。但是,仍然需要很长时间才能找到。你能建议一个更快的方法吗?非常感谢

%-- Find the neighborhood of one pixel
% x is pixel coordinate
% nrow, ncol is size of image 
function N = find_neighbor(x,nrow,ncol)

    i = x(1);
    j = x(2);
    I1 = i+1;
    if (I1 > nrow)
        I1 = nrow;
    end
    I2 = i-1;
    if (I2 < 1)
        I2 = 1;
    end
    J1 = j+1;
    if (J1 > ncol)
        J1 = ncol;
    end
    J2 = j-1;
    if (J2 < 1)
        J2 = 1;
    end
    N = [I1, I2, i, i; j, j, J1, J2]; 

例如:ncol=128; nrow=128; x =[30;110]则输出

N =31    29    30    30; 110   110   111   109]

用于循环调用函数

x=[30 31 32 33; 110 123 122 124]
for i=1:length(x)    
N = find_neighbor(x(:,i),nrow,ncol);
end

这是使用 bsxfun 的矢量化方法:

% define four neighbors as coordinate differences
d = [-1 0 ; 1 0 ; 0 -1 ; 0 1]';
% add to pixel coordinates
N = bsxfun(@plus, x, permute(d, [1 3 2]));
% make one long list for the neighbors of all pixels together
N = reshape(N, 2, []);
% identify out-of-bounds coordinates
ind = (N(1, :) < 1) | (N(1, :) > nrow) | (N(2, :) < 1) | (N(2, :) > ncol);
% and remove those "neighbors"
N(:, ind) = [];

permute 用于将四个不同邻居的 "dimension" 移动到第三个数组索引中。这样,使用 bsxfun,我们得到每对原始像素坐标与每对相对邻域坐标的组合。越界检查假设nrow属于第一个坐标,ncol属于第二个坐标。

ncol=128;
nrow=128;
x = [30 31 32 33; 110 123 122 124];

结果是

N =

    29    30    31    32    31    32    33    34    30    31    32    33    30    31    32    33
   110   123   122   124   110   123   122   124   109   122   121   123   111   124   123   125

不同像素的不同邻居最终可能是同一个像素,因此列表中可能存在重复项。如果您只想要每个结果像素一次,请使用

% remove duplicates?
N = unique(N', 'rows')';

得到

N =

    29    30    30    30    31    31    31    32    32    32    33    33    33    34
   110   109   111   123   110   122   124   121   123   124   122   123   125   124

多次调用小函数时,Matlab 的性能非常糟糕。 Matlab 的方法是尽可能地进行矢量化。您的代码的矢量化版本:

  function N = find_neighbor(x,nrow,ncol)
  N = [min(x(1,:)+1,nrow), max(x(1,:)-1,1), x(1,:), x(1,:); x(2,:),   x(2,:),min(x(2,:)+1,ncol), max(x(2,:)-1,1)];
  end

和用法

x=[30 31 32 33; 110 123 122 124]   
N = find_neighbor(x,nrow,ncol);

顺便说一句,对于边界上的像素,您的解决方案总是给出 4 个邻居。这是错误的。例如,(1,1) 的邻居应该只有 (2,1) 和 (1,2),而您添加两个额外的 (1,1)。 解决这个问题的方法很简单——删除图像外的所有邻居

  function N = find_neighbor(x,nrow,ncol)
  N = [x(1,:)+1, x(1,:)-1, x(1,:), x(1,:); x(2,:), x(2,:),x(2,:)+1, x(2,:)-1];
  N(:,N(1,:)<1 | N(1,:)> nrow | N(2,:)<1 | N(2,:)>ncol)=[];
  end