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

时间:2014-11-03 20:31:52

标签: matlab image-processing matrix filtering

所以我对创建自定义非线性滤波器感兴趣。我的掩码是一个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矩阵中的每个元素重复该过程。我该怎么做呢?谢谢!

2 个答案:

答案 0 :(得分: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));
看起来像是满口!让我们慢慢来看看。我使用了padarray并在原始矩阵Z周围创建了1像素的零边框,并将其存储在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

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

答案 1 :(得分:3)

对于最小/最大过滤,ordfilt2可能效率最高(可能imdilate / imerode,但这是另一个故事。)

首先,创建一个掩码,指出要考虑的四个直接邻居:

>> mask = false(3); mask([2 4 6 8]) = true
mask =

     0     1     0
     1     0     1
     0     1     0

使用该面具过滤:

>> Zmax = ordfilt2(Z,4,mask); % last value (4th non-zero) is max
>> out = Z - Zmax
out =

    26   -43   -61    28
   -43   -62    49   -66
    28   -34   -49   -11
   -28   -30   -53    11

无论如何,要管理负数,请记住使用有能力的数据类型。

顺便说一句,请参阅this answer关于使用ordfilt2imdilate进行高峰查找,这是一项类似的任务。