如何找到一个像素的邻居及其坐标

时间:2016-03-02 16:29:34

标签: matlab image-processing

我需要找到一个像素的所有黑色邻居;为此我尝试了以下;但输出不正确.Cropped输入图像是 enter image description here 标记图像(我把颜色添加到此标签) enter image description here 我想添加输入图像的黑色区域(椭圆周围的区域,如结构),并将标记图像中椭圆周围的白色区域更改为蓝色(需要将周围白色区域的标签更改为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

1 个答案:

答案 0 :(得分:2)

您的代码中存在多个错误,因此我会尝试逐个使用它们。这是您的原始代码,重新格式化了一下:

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)的邻居:图像中的 last 像素。倒数第二行包含img(1,1)的邻居,而 last 行只是因为初始化到zeros(1,8)而挂在那里。所有这一切对我来说都是不自然的,所以我要翻转结果数组,以便img(1,1)是第一行。此外,在每次循环迭代中生成数组的速度很慢。我们想要预先分配数组,然后将数据放在适当的位置。

由于我们引用了原始图像中的像素,但计算了填充图像,因此添加计数器变量比执行所有行/列索引计算要容易得多,所以我&# 39; ve添加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),然后是{{ 1}}。

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

img(1,2)

这会在当前像素周围采用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. 中有9个元素,包括当前像素!如果你真的不想列出当前的像素,我们可以解决这个问题,但无论哪种方式,我们都需要将neighbors的大小更改为fi_neighbors。如果需要,我们可以在结尾处从结果中删除第5列。

这是最终的代码:

(m*n,9)

显然,你可以做的更多,但这应该是一个非常好的开始。