【问题标题】:Fast way to find the neighboor of pixel快速查找像素邻居的方法
【发布时间】:2015-03-01 13:49:17
【问题描述】:

我正在为在图像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

【问题讨论】:

  • 如果您在一些嵌套循环中使用此函数,那么摆脱这些循环以加快执行速度可能更有意义。
  • 对。我在循环中使用了它,实际上,它会调用该函数大约 4000 次。是否可以减少计算时间?
  • 那些函数调用可能会破坏那里的性能。向我们展示那些嵌套循环的代码?
  • @请告诉我们你在用这些像素做什么。 conv2blockproc 可能是正确的选择。
  • @Divakar:让我们看看我的更新。 Daniel:conv2 适用于整个图像。但是,我的任务仅适用于图像中的几个像素。该像素是预先选择的。

标签: matlab image-processing optimization matrix


【解决方案1】:

这是使用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 用于将四个不同邻居的“维度”移动到第三个数组索引中。这样,使用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

【讨论】:

  • 感谢您的建议。但是,我测量了我的方法和您的方法之间的耗时。它表明我的方法更快。
  • 嗨@john2182,理论上这不太可能,我实际上无法重现。如果我在包含 100 万个点的 x 上运行您和我的代码,您的代码需要 3.758 秒,而我的代码需要 0.190 秒。
  • 确保使用tictoc 进行基准测试,并至少在几千个点上运行它——否则测量毫无意义。
  • 谢谢。我会再次测试它。因为我只测试了几个像素
  • @A.Donda,您似乎对图像处理感兴趣-您能否帮助我们打开这个专门的小组:area51.stackexchange.com/proposals/66531/computer-vision/72084 对问题进行投票赞成票少于 10 票。谢谢。
【解决方案2】:

多次调用小函数时,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

【讨论】:

  • 感谢 Ophir Gvirtzer。再次检查第二个解决方案。它给出了 x=[30;110] 的错误答案
猜你喜欢
  • 2014-02-05
  • 2020-01-29
  • 1970-01-01
  • 2014-06-10
  • 1970-01-01
  • 2016-01-14
  • 1970-01-01
  • 2013-09-06
  • 1970-01-01
相关资源
最近更新 更多