解决这个问题的方法是找到一种方法来组合来自 A 和 B 的信息,以便过滤本身变得容易。
我想到的第一件事是沿着第三维连接 A 和 B,并传递一个过滤器掩码,该过滤器掩码将从“A 切片”中获取 8 个元素,并从“B 切片”中获取中心元素。不幸的是,Matlab 不支持这一点。
虽然 nlfilter 仅适用于 2D 图像,但它确实允许您指定任何过滤函数。因此,您可以创建一个函数,以某种方式能够查找 A 和 B 的正确值。因此,我得出了第一个解决方案。
您创建一个新数组 C,其中包含每个元素的元素索引,即第一个元素是 1,第二个元素是 2,等等。然后,您运行 nlfilter,它采用 3x3 滑动窗口并传递 C 的值窗口内的过滤功能,ffn。 ffn 是一个匿名函数,它调用疯狂过滤器,并且已经初始化,以便 A 和 B 在每次调用时都被传递。 CrazyFunction 从 C 的滑动窗口获取值,这些值只不过是 A 和 B 的索引,并从中收集 A 和 B 的值。
第二个解决方案完全相同,只是您不移动滑动窗口,而是创建一个新数组,该数组的每一列中的每个可能位置都包含滑动窗口的内容。使用重叠窗口时,列数组会比原始数组更大。同样,您只需使用列数组 C 的值(它们是 A 和 B 的索引)即可在相关位置查找 A 和 B 的值。
EDIT如果你有足够的内存,im2col和col2im可以大大加快进程
%# define A,B
A = randn(100);
B = rand(100);
%# pad A, B - you may want to think about how you want to pad
Ap = padarray(A,[1,1]);
Bp = padarray(B,[1,1]);
#% EITHER -- the more more flexible way
%# create a pseudo image that has indices instead of values
C = zeros(size(Ap));
C(:) = 1:numel(Ap);
%# convert to 'column image', where each column represents a block
C = im2col(C,[3,3]);
%# read values from A
data = Ap(C);
%# replace centers with values from B
data(5,:) = Bp(C(5,:));
%# OR -- the more efficient way
%# reshape A directly into windows and fill in B
data = im2col(Ap,[3,3]);
data(5,:) = B(:);
% median and reshape
out = reshape(median(data,1),size(A));
旧版本(使用较少的内存,可能需要填充)
%# define A,B
A = randn(100);
B = rand(100);
%# define the filter function
ffun = @(x)crazyFilter(x,A,B);
%# create a pseudo image that has indices instead of values
C = zeros(size(A));
C(:) = 1:numel(A);
%# filter
filteredImage = nlfilter(C,[3,3],ffun);
%# filter function
function out = crazyFilter(input,A,B)
%#CRAZYFILTER takes the median of a 3x3 mask defined by input, taking 8 elements from A and 1 from B
%# read data from A
data = A(input(:));
%# replace center element with value from B
data(5) = B(input(5));
%# return the median
out = median(data);