解决这个问题的方法是找到一种方法来组合A和B中的信息,以便过滤本身变得容易。
我想到的第一件事是沿着第三维连接A和B,并使用过滤器掩码传递,该过滤器掩码将从'A-slice'获取8个元素,从'B-slice'获取中心元素。 不幸的是,Matlab不支持这一点。
虽然nlfilter仅适用于2D图像,但它允许您指定任何过滤功能。 因此,您可以创建一个能够以某种方式查找A和B的正确值的函数。因此,我找到了第一个解决方案。
你创建一个新的数组C,它包含每个元素的元素索引,即第一个元素是1,第二个元素是2,然后,你运行nlfilter,它需要一个3x3的滑动窗口并传递C的值在窗口内部的过滤功能,ffn。 ffn是一个匿名函数,它调用crazyFilter,并且已经初始化,以便在每次调用时传递A和B. CrazyFunction从C的滑动窗口获取值,它们只是A和B中的索引,并从中收集A和B中的值。
第二种解决方案完全相同,只是不是移动滑动窗口,而是创建一个新数组,在每个列中,每个可能位置都有滑动窗口的内容。 对于重叠窗口,列数组比原始数组大。 同样,您只需要使用列数组C的值(它们是A和B的索引)来查找相关位置的A和B值。
编辑如果你有足够的内存,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);