我有一个矩阵,值在中心,nan在边界(想象一个矩阵代表一个分水岭,它不是正方形的)。我需要用一个单元填充它来做一些分量应力计算。我试图避免使用核心Matlab功能的外部库,但我想做的是类似于padarray对称,但对于不规则的边界:
padarray(Zb,[1 1],'symmetric','both');
例如:
NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
NaN NaN NaN 2 5 39 55 44 8 NaN NaN NaN
NaN NaN NaN NaN 7 33 48 31 66 17 NaN NaN
NaN NaN NaN NaN 28 NaN 89 NaN NaN NaN NaN NaN
NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
就变成:
NaN NaN 2 2 5 39 55 44 8 8 NaN NaN
NaN NaN 2 2 5 39 55 44 8 17 17 NaN
NaN NaN 2 2 7 33 48 31 66 17 17 NaN
NaN NaN NaN 28 28 33 89 31 66 17 17 NaN
NaN NaN NaN 28 28 28 89 89 NaN NaN NaN NaN
(不知道如何处理两个相邻值的凸角,因为我需要控制边缘效果)。
这篇文章遵循今天早些时候的一个问题,在这个问题中,我能够将这些填充单元(缓冲区)的位置提取到扩展的逻辑中。然而,使用fillmissing和nearest并没有产生我所期望的效果(padarray所做的)。
Zb_ext(logical(ZbDilated)) = fillmissing(Zb_ext(logical(ZbDilated)),'nearest');
我可能能够逆转我所做的查找垫单元以查找相邻值并使用这些值来替换垫单元nan。但我想先看看有没有更简单的解决办法?
您可以使用两个2D卷积来实现这一点,其中conv2
在核心MATLAB库中,因此不需要外部任何东西,并且它应该很快。
然而,你注意到这个:
不知道如何处理两个相邻值的凸角,因为我需要控制边缘效果
我冒昧地定义了一个"合理的"凸角的输出是取平均值,因为从你的例子中,似乎没有定义如何处理这些情况,以及更复杂的情况,如cell(5,6)。
我已经给下面的代码添加了详细的注释来解释
% Example matrix
A = [
NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
NaN NaN NaN 2 5 39 55 44 8 NaN NaN NaN
NaN NaN NaN NaN 7 33 48 31 66 17 NaN NaN
NaN NaN NaN NaN 28 NaN 89 NaN NaN NaN NaN NaN
NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
];
% Track the "inner" indices, where values are defined
inner = (~isnan(A));
B = A; % Copy A so we don't change it
B(~inner) = 0; % Replace NaN with 0 so that convolutions work OK
% First dilate the inner region by one element, taking the average of
% neighbours which are up/down/left/right (no diagonals). This is required
% to avoid including interior points (which only touch diagonally) in the
% averaging. These can be considered the "cardinal neighbours"
kernel = [0 1 0 ; 1 0 1; 0 1 0]; % Cardinal directions in 3x3 stencil
s = conv2(B,kernel,'same'); % 2D convolution to get sum of neighbours
n = conv2(inner,kernel,'same'); % 2D convolution to get count of neighbours
s(inner) = 0; % Zero out the inner region
s = s./n; % Get the mean of neighbours
% Second, dilate the inner region but including the mean from all
% directions. This lets us handle convex corners in the image
s2 = conv2(B,ones(3),'same'); % Sum of neighbours (and self, doesn't matter)
n = conv2(inner,ones(3),'same'); % Count of neighbours (self=0 for dilated elems)
s2 = s2./n; % Get the mean of neighbours
% Finally piece together the 3 matrices:
out = s2; % Start with outmost dilation inc. corners
out(~isnan(s)) = s(~isnan(s)); % Override with inner dilation for cardinal neighbours
out(inner) = A(inner); % Override with original inner data
所以对于这个例子,输出将与你的例子输出相同,除了前面提到的角:
NaN NaN 2 2 5 39 55 44 8 8 NaN NaN
NaN NaN 2 2 5 39 55 44 8 12.5 17 NaN
NaN NaN 2 4.5 7 33 48 31 66 17 17 NaN
NaN NaN NaN 28 28 50 89 60 66 17 17 NaN
NaN NaN NaN 28 28 58.5 89 89 NaN NaN NaN NaN
相关(和使用):MATLAB/Octave:计算矩阵中相邻/相邻元素的和