【问题标题】:how to find neighours of a pixel and its co-ordinate如何找到像素的邻居及其坐标
【发布时间】:2016-03-26 22:48:38
【问题描述】:

我需要找到一个像素的所有黑色邻居;为此,我尝试了以下操作;但输出不正确。裁剪的输入图像是 标记的图像(我给这个标签添加了颜色) 我想添加输入图像的黑色区域(椭圆形结构周围的区域)并将标记图像中椭圆周围的白色区域更改为蓝色(需要将周围白色区域的标签更改为 1)

  clc
    clear all;close all
    img=[0   255 0 0 0;
         0   1   1 255 0;
         255 0   0 255 0;];
    [m n]=size(img)
    img= padarray(img, [2 2], 0)
    fi_neighbors=zeros(1,8);
    for i=1:m
        for j=1:n
    for r=3:m
        for c=3:n

           neighbors(1) = img(r-1,c-1); % Upper left.  
    neighbors(2) = img(r-1,c); % Upper middle.  
    neighbors(3) = img(r-1,c+1); % Upper right.  
    neighbors(4) = img(r,c-1); % left.  
    neighbors(5) = img(r,c+1); % right. 
    neighbors(6) = img(r+1,c+1); % Lowerleft.  
    neighbors(7) = img(r+1,c); % lower middle.  
    neighbors(8) = img(r+1,c-1); % Lower left.  
        end

    end
    fi_neighbors=[neighbors;fi_neighbors]
        end
    end

【问题讨论】:

  • 怎么不正确? aka,它目前输出什么?
  • 预期输出是多少?这段代码简单地找出图像中每个像素的所有 8 个像素邻域强度,并拼接成一个巨型数组。
  • 在 2 个内部循环中覆盖结果的事实可能很麻烦。您计算一些元素,然后放入neighbors(1:8)。您每次都在循环中执行此操作。除此之外。有用于最近邻计算的 Matlab 函数。最好的选择取决于你想做什么。除此之外。如果代码看起来也像 Matlab 中的问题一样,您应该考虑重新格式化。这可以通过标记所有内容并在菜单中选择重新格式化或其他内容来完成。
  • 第一张图片中没有黑色或白色像素。第二张图像中没有黑色像素。请更正您的问题。
  • @beaker 更新问题

标签: matlab image-processing


【解决方案1】:

您的代码中有几个错误,因此我将尝试一一解决。这是您的原始代码,重新格式化了一下:

img = [0 0 0 0 0;
       0 1 1 0 0;
       0 0 0 0 0;];
[m n] = size(img)
img = padarray(img, [2 2], 0)
fi_neighbors = zeros(1,8);

for i = 1:m
   for j = 1:n
      for r = 3:m
         for c = 3:n
            neighbors(1) = img(r-1,c-1); % Upper left.  
            neighbors(2) = img(r-1,c);   % Upper middle.  
            neighbors(3) = img(r-1,c+1); % Upper right.  
            neighbors(4) = img(r,c-1);   % left.  
            neighbors(5) = img(r,c+1);   % right. 
            neighbors(6) = img(r+1,c+1); % Lower right.  <-- corrected
            neighbors(7) = img(r+1,c);   % lower middle.  
            neighbors(8) = img(r+1,c-1); % Lower left.  
         end
      end
      fi_neighbors = [neighbors;fi_neighbors]
   end
end

第一个错误是循环变量ij 从未使用过。因此它们是无用的(除了让我们执行相同的计算m x n 次)。让我们把它们拿出来。

img = [0 0 0 0 0;
       0 1 1 0 0;
       0 0 0 0 0;];
[m n] = size(img)
img = padarray(img, [2 2], 0)
fi_neighbors = zeros(1,8);

for r = 3:m
   for c = 3:n
      neighbors(1) = img(r-1,c-1); % Upper left.  
      neighbors(2) = img(r-1,c);   % Upper middle.  
      neighbors(3) = img(r-1,c+1); % Upper right.  
      neighbors(4) = img(r,c-1);   % left.  
      neighbors(5) = img(r,c+1);   % right. 
      neighbors(6) = img(r+1,c+1); % Lower right.  
      neighbors(7) = img(r+1,c);   % lower middle.  
      neighbors(8) = img(r+1,c-1); % Lower left.              
   end
end
fi_neighbors = [neighbors;fi_neighbors]

排除这些循环后,我们可以看到您在完成所有计算后才更新fi_neighbors 数组一次。这就是为什么您之前得到相同的结果m x n 次。我们需要将它移到循环中,在每组计算后更新结果(这次我省略了设置,只列出了循环):

for r = 3:m
   for c = 3:n
      neighbors(1) = img(r-1,c-1); % Upper left.  
      neighbors(2) = img(r-1,c);   % Upper middle.  
      neighbors(3) = img(r-1,c+1); % Upper right.  
      neighbors(4) = img(r,c-1);   % left.  
      neighbors(5) = img(r,c+1);   % right. 
      neighbors(6) = img(r+1,c+1); % Lower right.  
      neighbors(7) = img(r+1,c);   % lower middle.  
      neighbors(8) = img(r+1,c-1); % Lower left.              
      fi_neighbors = [neighbors;fi_neighbors]   %// moved inside loops
   end
end

接下来是我们循环的范围。您在数组的每一侧填充了 2 个零,因此您从行/列3 开始。这很好,但你仍然在mn 结束循环。这意味着您处理(m-2) x (n-2) 像素。你需要扩大范围。但实际上,您填充的内容超出了您的需要。每边一个像素的填充就足够了,所以让我们同时做两个,更改填充并更正范围:

img = [0 0 0 0 0;
       0 1 1 0 0;
       0 0 0 0 0;];
[m n] = size(img)
img = padarray(img, [1 1], 0)
fi_neighbors = zeros(1,8);

for r = 2:m+1
   for c = 2:n+1
      neighbors(1) = img(r-1,c-1); % Upper left.  
      neighbors(2) = img(r-1,c);   % Upper middle.  
      neighbors(3) = img(r-1,c+1); % Upper right.  
      neighbors(4) = img(r,c-1);   % left.  
      neighbors(5) = img(r,c+1);   % right. 
      neighbors(6) = img(r+1,c+1); % Lower right.  
      neighbors(7) = img(r+1,c);   % lower middle.  
      neighbors(8) = img(r+1,c-1); % Lower left.              
      fi_neighbors = [neighbors;fi_neighbors]
   end
end

现在您应该有一个可以为您提供正确输出的工作程序:

fi_neighbors =

   0   0   0   0   0   0   0   0   <-- img(m,n) neighbors
   1   0   0   0   0   0   0   0
   1   1   0   0   0   0   0   0
   0   1   1   0   0   0   0   0
   0   0   1   0   0   0   0   0
   0   0   0   0   0   0   0   0
   0   0   0   1   0   0   0   0
   0   0   0   1   0   0   0   0
   0   0   0   0   1   0   0   0
   0   0   0   0   1   0   0   0
   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   1
   0   0   0   0   0   0   1   1
   0   0   0   0   0   1   1   0
   0   0   0   0   0   1   0   0   <-- img(1,1) neighbors
   0   0   0   0   0   0   0   0

这可行,但请查看我添加到输出中的注释。结果的第一行包含像素img(m,n) 的邻居:图像中的最后一个 像素。倒数第二行包含 img(1,1) 的邻居,而 last 行只是因为您对 zeros(1,8) 的初始化而挂在那里。所有这些对我来说似乎都不自然,所以我将翻转结果数组,使img(1,1) 成为第一行。此外,在每次循环迭代中增长一个数组也很慢。我们要预先分配数组,然后将数据放在适当的位置。

由于我们引用原始图像中的像素,但在填充图像上进行计算,添加计数器变量比进行所有行/列索引计算要容易得多,所以我添加了 pix 为一个计数器:

img = [0 0 0 0 0;
       0 1 1 0 0;
       0 0 0 0 0;];
[m n] = size(img);
img = padarray(img, [1 1], 0)
fi_neighbors = zeros(m*n,8);   % preallocate result array

pix = 0;   % pixel counter
for r = 2:m+1
   for c = 2:n+1
      pix = pix + 1;   % find neighbors for next pixel
      neighbors(1) = img(r-1,c-1); % Upper left.  
      neighbors(2) = img(r-1,c);   % Upper middle.  
      neighbors(3) = img(r-1,c+1); % Upper right.  
      neighbors(4) = img(r,c-1);   % left.  
      neighbors(5) = img(r,c+1);   % right. 
      neighbors(6) = img(r+1,c+1); % Lower right.  
      neighbors(7) = img(r+1,c);   % lower middle.  
      neighbors(8) = img(r+1,c-1); % Lower left.
      fi_neighbors(pix,:) = neighbors;   % update the correct row
   end
end

结果:

fi_neighbors =

   0   0   0   0   0   1   0   0
   0   0   0   0   0   1   1   0
   0   0   0   0   0   0   1   1
   0   0   0   0   0   0   0   1
   0   0   0   0   0   0   0   0
   0   0   0   0   1   0   0   0
   0   0   0   0   1   0   0   0
   0   0   0   1   0   0   0   0
   0   0   0   1   0   0   0   0
   0   0   0   0   0   0   0   0
   0   0   1   0   0   0   0   0
   0   1   1   0   0   0   0   0
   1   1   0   0   0   0   0   0
   1   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0

现在,img(1,1) 的邻居在第 1 行,img(m,n) 的邻居在 m*n 行。

最后,您可以进行一些快速优化。它们都需要更改结果的顺序。如果您愿意以不同的顺序显示像素和邻居(我会尽量清楚地显示),那么我们可以首先更改循环的顺序以利用 MATLAB 的列优先顺序。

代替:

for r = 2:m+1
   for c = 2:n+1
      ...
   end
end

我们将使用:

for c = 2:n+1    % be sure to swap m and n as well!
   for r = 2:m+1
      ...
   end
end

对于大型矩阵,这应该有助于将我们正在使用的当前列保留在缓存中。这将改变像素的顺序,因此第二个像素不是img(1,2),而是img(2,1),然后是img(3,1),再到img(m,1),然后是img(1,2)

第二个更改将您所有的邻居计算压缩为 2 行(可能是 3 行),但它会更改顺序,如下所示:

pix = 0;   % pixel counter
for c = 2:n+1
   for r = 2:m+1
      pix = pix + 1;   % find neighbors for next pixel

      neighbors = img(r-1:r+1,c-1:c+1);
      neighbors = neighbors(:).';

      fi_neighbors(pix,:) = neighbors;   % update the correct row
   end
end

这会将img 的子矩阵围绕当前像素,然后使用冒号符号将其转换为列向量,最后将其转置为行向量。以下是neighbors 内生成的邻居位置:

neighbors(1) % Upper left.
neighbors(2) % left.
neighbors(3) % Lower left.
neighbors(4) % Upper middle.
neighbors(5) % *** current pixel ***
neighbors(6) % Lower middle.
neighbors(7) % Upper right.
neighbors(8) % right.
neighbors(9) % Lower right.

但是现在neighbors 中有 9 个元素,包括当前像素!如果您真的不想列出当前像素,我们可以解决这个问题,但无论哪种方式,我们都需要将fi_neighbors 的大小更改为(m*n,9)。如果需要,我们可以在最后从结果中删除第 5 列。

这是最终代码:

img = [0 0 0 0 0;
       0 1 1 0 0;
       0 0 0 0 0;];
[m n] = size(img);
img = padarray(img, [1 1], 0);
fi_neighbors = zeros(m*n,9);   % preallocate result array

pix = 0;   % pixel counter
for c = 2:n+1
   for r = 2:m+1
      pix = pix + 1;   % find neighbors for next pixel
      neighbors = img(r-1:r+1,c-1:c+1);
      neighbors = neighbors(:).';
      fi_neighbors(pix,:) = neighbors;   % update the correct row
   end
end

fi_neighbors(:,5) = []; % OPTIONAL - remove current pixel from each row

显然,您还可以做更多事情,但这应该是一个很好的开始。

【讨论】:

  • 您的样本矩阵仅包含 01。你从哪里得到255?请编辑您的问题以反映您的要求。
猜你喜欢
  • 2014-02-26
  • 1970-01-01
  • 2017-09-17
  • 1970-01-01
  • 2020-09-09
  • 2020-03-05
  • 1970-01-01
  • 2021-04-23
  • 2017-03-16
相关资源
最近更新 更多