产生的内核类型

时间:2018-09-29 19:15:43

标签: matlab image-processing

我试图从here了解MATLAB的非局部均值过滤算法的实现。我想了解以下部分代码生成的是哪种内核:

kernel=zeros(2*f+1,2*f+1);   
for d=1:f    
  value= 1 / (2*d+1)^2 ;    
  for i=-d:d
      for j=-d:d
          kernel(f+1-i,f+1-j)= kernel(f+1-i,f+1-j) + value ;
      end
  end
end
kernel = kernel ./ f;

我试图查看中间输出,我认为它正在产生高斯加权核,但是我不确定这是否正确。

输出:

kernel =

0.0200    0.0200    0.0200    0.0200    0.0200
0.0200    0.0756    0.0756    0.0756    0.0200
0.0200    0.0756    0.0756    0.0756    0.0200
0.0200    0.0756    0.0756    0.0756    0.0200
0.0200    0.0200    0.0200    0.0200    0.0200

所引用的纸张:Buades-NonLocal第3节

2 个答案:

答案 0 :(得分:2)

首先,请注意,最里面的两个循环是一种非矢量化的方法,用于定义一个(2d+1) x (2d+1)大小的常数矩阵,其总和为1(value只是1*(2*d+1)^2的倒数) 。这定义了a box blur kernel

因此,发生的情况是通过对大小为(2f+1) x (2f+1)3 x 3,...,5 x 5的同心盒子模糊内核求和来定义(2f+1) x (2f+1)内核。由于卷积是线性运算,因此框模糊的总和将单独应用,并且单个内核的凸组合才是有效内核。

虽然可以通过递归使用框模糊来近似高斯模糊,但是诸如上述的凸组合可能会表现出不同的行为(如Cris Luengo in a comment所示)。甚至不对称:高斯核是球对称的,而这些箱形核有角。

总而言之,我相信您的问题的答案是“否”,它可能不近似于高斯核,但仍然是模糊核。


如果必须创建上述内核,则将其矢量化:

kernel = zeros(2*f+1,2*f+1);   
for d=1:f
    kernel(f+1-d:f+1+d,f+1-d:f+1+d) = kernel(f+1-d:f+1+d,f+1-d:f+1+d) + 1/(2*d+1)^2;
end
kernel = kernel / f;

答案 1 :(得分:2)

Buades等。绝对打算使用高斯权重。如果要作为近似值,则该内核会产生非常近似的近似值。 f=3f=10f=100在1D模式中是这样的:

kernels

我添加了一个高斯内核进行比较。此外,高斯是完全各向同性的,而这个近似值离它很远(因为它是由正方形组成的)。

我发现这很奇怪,因为通过对真实高斯使用这种近似,NL-means算法的四个嵌套循环使用起来并没有更快。补丁差异的平方乘以内核,此操作的成本与内核的生成方式或包含的值无关。

我的建议是将make_kernel替换为这样的东西,从而创建真正的2D高斯内核:

function kernel = make_kernel2(f)
x = linspace(-2,2,2*f+1);
kernel = exp(-0.5*x.^2);
kernel = kernel .* kernel.'; % requires newer MATLAB, otherwise use bsxfun
kernel = kernel / sum(kernel(:));

我以前从未见过这种类似于高斯的近似方法(并且我已经看过很多)。通常,高斯卷积是通过重复使用盒核进行卷积来近似的(他们说3x足以满足相当好的近似but more are needed if the derivative is to be computed after)。这种方法的缺点是不可能重复使用积分图像,因为每个卷积都应用于不同的图像(即先前卷积的结果)。可以使用积分图像来计算带有盒核的卷积,无论盒的大小如何,都可以通过将4个值加一除法来计算一个像素的输出。

img = imread('cameraman.tif');
out = imfilter(img,ones(3,3)/9);
out = imfilter(out,ones(3,3)/9);
out = imfilter(out,ones(3,3)/9);

如果不是使用重复的盒式卷积运算,而是使用相同的积分图像来计算多个不同大小的盒式卷积运算,然后将结果相加在一起,那么就可以得到与该问题中所询问的内核的卷积。这将是对高斯的粗略近似,而不是各向同性的,但计算起来非常便宜。 (下面的演示代码没有使用完整的图像,这并不意味着要演示时序,而只是演示结果。)

img = imread('cameraman.tif');
out = imfilter(img,ones(3,3)/9) / 3;
out = out + imfilter(img,ones(4,4)/16) / 3;
out = out + imfilter(img,ones(5,5)/25) / 3;

我敢打赌,这就是内核的来源。但是,通过创建此内核,而不是单独应用各种卷积并添加结果,并没有使用此方法的所有速度优势,而仅留下了许多负面影响。