【发布时间】:2017-07-01 18:20:03
【问题描述】:
我有一个矩阵,其中值 -1 是随机分布的(请参见图像中的黄色单元格)。矩阵的其余部分用 0 填充(蓝色单元格)。
我现在需要用 1 从左侧、右侧、顶部或底部填充与 -1 相邻的单元格。如果多个单元格的 -1 彼此相邻,则不应覆盖这些 -1。
我尝试过使用两个嵌套的 for 循环,但使用索引会变得非常棘手。我将不胜感激。
【问题讨论】:
我有一个矩阵,其中值 -1 是随机分布的(请参见图像中的黄色单元格)。矩阵的其余部分用 0 填充(蓝色单元格)。
我现在需要用 1 从左侧、右侧、顶部或底部填充与 -1 相邻的单元格。如果多个单元格的 -1 彼此相邻,则不应覆盖这些 -1。
我尝试过使用两个嵌套的 for 循环,但使用索引会变得非常棘手。我将不胜感激。
【问题讨论】:
我从Vahe Tshitoyan's answer借用了示例矩阵生成:
A = zeros(10,10);
A(randi(100,1,20))=-1;
colormap(parula(3)); % set colormap: blue, yellow, bluish green
image(-A*2+1); % -A*2+1 is just a trick to get the desired colors
axis square
你可以
conv2) 将 1 写入包围等于 -1 的单元格。-1 覆盖到原始单元格中。也就是说,
mask = [0 1 0; 1 0 1; 0 1 0]; % define neighbouthood mask
B = double(conv2(-A, mask, 'same') > 0); % step 1
B(A==-1) = -1; % step 2
figure
colormap(parula(3));
image(-B*2+1+3*(B==1)); % similar trick to that used before
axis square
示例原始矩阵(A)和结果矩阵(B):
【讨论】:
您可以使用circshift 函数。
% generating the matrix
A = zeros(10,10);
A(randi(100,1,20))=-1;
figure(1);imagesc(A, [-1 1]);
% neighbours + no circular boundary condition
downshifted = circshift(A, 1, 1);downshifted(1,:)=0;
upshifted = circshift(A, -1, 1);upshifted(end,:)=0;
leftshifted = circshift(A, -1, 2);leftshifted(:,end)=0;
rightshifted = circshift(A, 1, 2);rightshifted(:,1)=0;
% combining neighbours and removing where A~=0
neighbours = (downshifted|upshifted|leftshifted|rightshifted)&~A;
% final matrix
B = A+neighbours;
figure(2);imagesc(B, [-1 1]);
需要注意的一点是circshift 的圆形边界条件。这就是我手动设置downshifted(1,:)=0; 等的原因。当然,除非你真的想要圆形边界条件。这就是我得到的
还有这个,我认为这样做更有效。
对于每个给定的像素,四个最近邻的线性索引由偏移量给出
offsets = [-n, -1, +1, +n];
其中n 是行数。因此,您可以使用类似
minusOneInd = find(A==-1); % the linear indices of -1s
indices = unique(bsxfun(@plus, minusOneInd, offsets)); % all neighbours
但是,由于边缘和索引用完,这会导致一些麻烦。解决此问题的一种方法是用 0 填充初始矩阵,然后在操作完成后移除填充。假设A 是您的初始矩阵,则可以编写如下所示的完整代码。
Ap = padarray(A,[1 1]); % to get rid of the edge effects
n = size(Ap, 1);
offsets = [-n, +1, -1, +n]; % index offsets of four neighbours
minusOneInd = find(Ap==-1); % finding the indices of -1s
indices = unique(bsxfun(@plus, minusOneInd, offsets)); % neighbours
% now, remove out of range indices and indices where A is -1
indices(indices<1|indices>numel(Ap)|ismember(indices, minusOneInd))=[];
Ap(ind2sub(size(Ap),indices)) = 1; % assigning the ones
B = Ap(2:end-1,2:end-1); % this is what we want
【讨论】:
@Vahe Tshitoyan 使用 circshift 的答案似乎不错,而我使用的是 for 循环:
M = zeros(10);
M(randi(100, [1,20])) = -1;
siz = size(M);
[I, J] = ind2sub(siz, find(M == -1)); % row, column indice of those -1
for i = 1:numel(I)
if I(i)>1 && M(I(i)-1, J(i))~=-1, M(I(i)-1, J(i)) = 1; end % above
if I(i)<siz(1) && M(I(i)+1, J(i))~=-1, M(I(i)+1, J(i)) = 1; end % below
if J(i)>1 && M(I(i), J(i)-1)~=-1, M(I(i), J(i)-1) = 1; end % left
if J(i)<siz(2) && M(I(i), J(i)+1)~=-1, M(I(i), J(i)+1) = 1; end % right
end
【讨论】: