如何创建自定义非线性滤波器?

Dar*_*rik 3 matlab filtering image-processing matrix

所以我对创建自定义非线性滤波器感兴趣.我的掩码是一个3乘3的矩阵,我想要做的是取我的中心点并查看与其直接相邻的值(不包括对角线元素).我想通过每个相邻值减去中间元素,然后找到这些值中的最小值.基本上我正在查看高程数据,我想找到中间点的最小delta-Z.

例:

Z = [64 21 31 59 38 30 92 26 81 47 43 60 53 23 18 71];

所以我想Z(3,3)现在只是看着= 43.我会拿43并减去92,60,18和47; 分别产生-49,-17,25和-4.然后我希望它只输出-49.对Z矩阵中的每个元素重复该过程.我该怎么做呢?谢谢!

ray*_*ica 5

@chappjc的答案是完全可以接受的.但是,如果您想采用colfilt灵感方法,可以转换像素邻域,im2col以便将3 x 3个重叠的邻域放入列中.这里发生的是像素邻域以列主格式构建,因此每个像素邻域的列被堆叠成单个列.您将获取所有这些堆叠的列并将它们放入2D矩阵中.在我们的例子中,行数将是9,而我们将拥有与有效像素邻域一样多的列.这是您使用时的结果im2col.如何获得像素邻域也是列主要格式.从图像的左上角开始,沿着行向下收集3 x 3像素的邻域.一旦我们到达矩阵的底部,我们就会移动到下一列,然后再次向下行.这种工作方式的行为im2col对于此算法的工作至关重要.

一旦你这样做,分别提取它的第二,第四,第六和第八行,以获得邻域中的西,北,南和东元素(基本方向).您将减去第五行,它将是每个相应基数方向的邻域中心,然后取最小值.但是,在执行此操作之前,您需要使用1像素边框填充数组,以便可以处理边框像素Z.假设该像素边界为零.

换句话说,尝试做这样的事情:

Zpad = padarray(Z, [1 1]);
A = im2col(Zpad, [3 3]);
cardinal_directions = A(2:2:8,:);
out = reshape(min(bsxfun(@minus, A(5,:), cardinal_directions), [], 1), size(Z));
Run Code Online (Sandbox Code Playgroud)

看起来像一口!让我们慢慢来看看.我使用padarray并创建了一个1像素的零边框,它围绕原始矩阵Z并存储在其中Zpad.然后im2col,我使用将填充结果的每个3 x 3像素邻域转换为每个9个元素的列.然后,我通过对输出的第二,第四,第六和第八行进行采样来提取每个像素邻域的基本方向im2col.一旦我提取了这些基本方向,我就提取第五行,这是每个像素邻域的中心,并使用相应的像素邻域进行减法.然后,我在所有列上使用min和操作所有行的最小值(指定操作的维度1).

我用它bsxfun来促进每个邻域中的中心像素与它们各自的基本方向相减.此输出将是单个向量,因此我需要reshape将向量返回到矩阵中.这个行向量的元素以列主格式排列,这就是为什么我需要将数组重新整形为适当的矩阵.

这就是我的例子:

out =

    26   -43   -61    28
   -43   -62    49   -66
    28   -34   -49   -11
   -28   -30   -53    11
Run Code Online (Sandbox Code Playgroud)

如果你想仔细检查这是否正确,请看一下Z(2,2).我们看到中心元素是30,而基本元素是21,38,47和92.取30和每个元素减去给出9,-8,-17和-62.所有这些中的最小值是-62,这是看到的out(2,2).同样,你的例子的Z(3,3)收益率为-49 at out(3,3),这正是你所期望的.你将不得不照顾沿着边界发生的事情out.我对此矩阵进行了零填充,因此沿着边界有条目,您将获取邻域的中心并减去零.你没有正确地定义你想要沿着边界做什么,所以我假设如果你走出边界的边界方向Z在这种情况下是零.