假设我有一维高斯函数。 它的长度是600.
我想将其插值为600 X 600的2D高斯。
这是我写的代码(OTFx是高斯函数,OTF - 2d插值函数):
[x, y] = meshgrid([-300:299], [-300:299]);
r = sqrt((x .^ 2) + (y .^ 2));
OTF = interp1([-300:299], OTFx, r(:), 'spline');
OTF = reshape(OTF, [600, 600]);
问题是我最后得到了Overshoot: alt text http://i39.tinypic.com/259et0g.png
我该如何预防呢? 是否有更好的单调递减函数插值算法?
答案 0 :(得分:5)
编辑:根据您的澄清,很明显发生了什么。您试图插入超出可用数据范围的函数 - 即您将从插值到外推。样条曲线将导致您观察到的过冲。解决方案只是确保您的1D函数在区间[min(r),max(r)]中具有值。请注意,在原始数据中,max(r)约为424,而插值函数的定义范围为[-300,299]
% Simulated overshoot, see left figure:
x1d = [-300:299];
[x,y]=meshgrid(x1d,x1d);
r = sqrt(x.^2+y.^2);
gsn1d = exp(-x1d.^2/500);
lowpass = @(x)(x1d > -x & x1d < x);
gsn1dcutoff = ifft(fftshift(lowpass(10).*fftshift(fft(gsn1d))));
plot(gsn1dcutoff)
OTF2d = reshape(interp1(x1d,gsn1dcutoff,r(:),'spline'),[length(x1d),length(x1d)]);
mesh(OTF2d)
% Quick and dirty fix, see right figure:
x1dExtended = linspace(min(x1d*sqrt(2)),max(x1d*sqrt(2)),ceil(length(x1d)*sqrt(2)));
gsn1dE = exp(-x1dExtended.^2/500);
% ^^^ note that this has 600*sqrt(2) points and is defined on the diagonal of your square. Now we can low-pass filter in the freq. domain to add ripple in space domain:
lowpass = @(x)(x1dExtended > -x & x1dExtended < x);
gsn1dcutoff = -real(ifft(fftshift(lowpass(10).*fftshift(fft(gsn1dE)))));
plot(gsn1dcutoff)
OTF2d = reshape(interp1(x1dExtended,gsn1dcutoff,r(:),'spline'),[length(x1d),length(x1d)]);
mesh(OTF2d)
alt text http://img54.imageshack.us/img54/8255/clipboard01vz.png
答案 1 :(得分:2)
Leo的诊断是正确的。我想建议一个更简单的(我希望)补救措施:做你想做的事情(基本上围绕其对称轴旋转高斯)并在600x600方格中得到合理的答案你需要一个高斯600 * sqrt (2)= 849像素长。如果你能做到这一点,那么所有进一步的thttp://stackoverflow.com/questions/2443046/interpolating-1d-gaussian-into-2d-gaussianrickery都没有必要。
编辑:换句话说:如果围绕其中心旋转600像素宽的内容,则会得到直径为600像素的圆圈。您想要覆盖600x600 square 。为此你需要一个直径为849像素的圆,因为这是正方形的对角线。
答案 2 :(得分:0)
在高斯的特定情况下,您可以通过使用它可分离的事实来计算高斯:
OTF2(x,y) = exp( - x^2 - y^2) = exp( - x^2) * exp( - y^2) = OTFx(x) * OTFx(y)
所以你仍然只需要将OTFx存储在内存中。