我需要找到一个像素的所有黑色邻居;为此我尝试了以下;但输出不正确.Cropped输入图像是 标记图像(我把颜色添加到此标签) 我想添加输入图像的黑色区域(椭圆周围的区域,如结构),并将标记图像中椭圆周围的白色区域更改为蓝色(需要将周围白色区域的标签更改为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
答案 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
第一个错误是从不使用循环变量i
和j
。因此它们没用(除了让我们执行相同的计算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
开始。这很好,但你仍然在m
和n
结束循环。这意味着您处理(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)
显然,你可以做的更多,但这应该是一个非常好的开始。