我试图从这里中理解非局部均值滤波算法的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-非本地第3节
发布于 2018-09-30 06:08:39
Buades等人绝对打算使用高斯权值。这个核,如果它是一个近似,则产生一个非常粗略的近似。这就是f=3,f=10和f=100在1D中的样子。

为了比较,我增加了一个高斯核。此外,高斯是完全各向同性的,而这个近似离它很远(因为它是由正方形构成的)。
我觉得这很奇怪,因为使用NL-均值算法的四个嵌套循环在真正的高斯上使用这个近似不能使速度更快。补丁差的平方乘以内核,此操作的成本与内核的生成方式或包含的值无关。
我的建议是用这样的东西代替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足够一个相当好的近似,但是,如果要计算之后的导数,还需要更多的)。这种方法的缺点是不可能重复使用积分图像,因为每个卷积都应用于不同的图像(即先前卷积的结果)。带盒核的卷积可以用积分图像计算,其中一个像素的输出可以通过加法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;我打赌这就是这个内核的来源。但是,通过创建这个内核,而不是单独应用各种卷积并添加结果,这种方法的所有速度优势都没有被使用,只留下了它的许多负面方面。
发布于 2018-09-29 19:48:52
首先,请注意,最里面的两个循环是一种非向量化的方法,可以定义一个(2d+1) x (2d+1)-sized常数矩阵,该矩阵之和为1 (value只是1*(2*d+1)^2的倒数)。这定义了一个盒子模糊的内核。
因此,(2f+1) x (2f+1)内核的定义是通过对大小为3 x 3、5 x 5、.、(2f+1) x (2f+1)的同心盒模糊核进行总结。由于卷积是一种线性运算,因此箱形模糊和将单独应用,单个核的凸组合是有效的核。
虽然框模糊可以通过递归使用来近似高斯模糊,但像上面这样的凸组合可能表现得不同(正如Cris Luengo在评论中所指出的)。甚至对称也是不对称的:高斯核是球对称的,而这些盒子核有角。
总之,我相信你的问题的答案是“不”,它可能不是一个高斯核,但它仍然是一个模糊的内核。
如果我必须创建上面的内核,我会将其矢量化:
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;https://stackoverflow.com/questions/52571689
复制相似问题