用Butterworth滤波器去除正弦噪声

时间:2011-03-02 09:31:42

标签: python image-processing opencv

我正试图消除此图像中的正弦噪声:

enter image description here

这是它的DFT光谱(应用对数和任意强度缩放后):

enter image description here

我已经有一个巴特沃斯滤镜应用于此图像。它将淘汰中频峰值。加载后我正在注意将它从[0..255]缩放到[0..1.0]。这是过滤器:

enter image description here

结果不是很好:

enter image description here

我的问题:

  • 为什么图像中仍然存在大量噪音?
  • 为什么结果比原始图像更暗?过滤器显然没有触及DC项,所以我希望平均强度是相同的。
  • 为什么过滤器只取出某些峰值?它来自一本教科书,所以我倾向于认为它是正确的,但在频谱中还有其他峰值 - 它们也是噪声的一部分吗?我尝试使用同心滤镜去除它们,但它并没有带来太大的好处,并使图像变得无法识别。

我拍摄了图像(裁剪)并过滤了Gonzalez和Woods的书Digital Image Processing。在他们的例子中,通过滤波完全消除了周期性噪声,并且图像的平均强度保持不变。

我的加载图片和过滤器,DFT,过滤,IDFT的源代码如下:

import cv

def unshift_crop(comp, width, height):
    result = cv.CreateImage((width, height), cv.IPL_DEPTH_8U, 1)
    for x in range(height):
        for y in range(width):
            real, _, _, _ = cv.Get2D(comp, x, y)
            real = int(real) * ((-1)**(x+y))
            cv.Set2D(result, x, y, cv.Scalar(real))
    return result

def load_filter(fname):
    loaded = cv.LoadImage(fname, cv.CV_LOAD_IMAGE_GRAYSCALE)
    flt = cv.CreateImage(cv.GetSize(loaded), cv.IPL_DEPTH_32F, 2)
    width, height = cv.GetSize(loaded)
    for i in range(width*height):
        px, _, _, _ = cv.Get1D(loaded, i)
        #cv.Set1D(flt, i, cv.Scalar(px/255.0, 0))
        cv.Set1D(flt, i, cv.Scalar(px/255.0, px/255.0))
    return flt

if __name__ == '__main__':
    import sys
    fname, filt_name, ofname = sys.argv[1:]
    img = cv.LoadImage(fname, cv.CV_LOAD_IMAGE_GRAYSCALE)
    width, height = cv.GetSize(img)
    src = cv.CreateImage((width*2, height*2), cv.IPL_DEPTH_32F, 2)
    dst = cv.CreateImage((width*2, height*2), cv.IPL_DEPTH_32F, 2)
    cv.SetZero(src)
    for x in range(height):
        for y in range(width):
            px, _, _, _ = cv.Get2D(img, x, y)
            px = float(px) * ((-1) ** (x+y))
            cv.Set2D(src, x, y, cv.Scalar(px, 0))
    cv.DFT(src, dst, cv.CV_DXT_FORWARD)
    flt = load_filter(filt_name)
    cv.Mul(dst, flt, src)
    cv.DFT(src, dst, cv.CV_DXT_INV_SCALE)
    result = unshift_crop(dst, width, height)
    cv.SaveImage(ofname, result)

修改

原始源中存在一个错误,其中过滤器虚构组件被加载为零。这就是导致结果图像显得比实际更暗的原因。我已经解决了这个问题并评论了相关的一行。

使用@ 0x69提供的固定源和过滤器(是的,我知道它不是真正的Butterworth过滤器,但在这个阶段我很乐意尝试任何东西),这就是结果:

enter image description here

比我开始时更好,但仍然不如我希望的那么好。谁能打败这个?我怀疑放入更多的凹槽以取出剩余的峰值可能会带来一些好处。

编辑2

我已经联系了作者。这是他们的回应:

  

问题在于使用的图像   实验是浮点数,   而书中所示的那个(和   提供的原件   downloads)是8位。这是   印刷等所需

     

为了复制实验,   你必须从无噪音开始   图像,然后添加自己的噪音   它

3 个答案:

答案 0 :(得分:5)

我试过使用这样的修改过滤器: enter image description here 我和我得到的是这个 - >
enter image description here 我无法完全解释结果,但我最好的猜测是通过与主图像信号相互作用产生的正弦噪声会产生二次,三次,......谐波噪声波。 结果也很不理想,似乎还有一些噪音谐波仍在这里...... 顺便说一句,感谢有趣的问题。

修改

我第二次尝试过滤器改进。过滤器:
enter image description here 过滤结果:
enter image description here
这次似乎没有明显的正弦噪声模式可见。

答案 1 :(得分:3)

我记得在几年前的图像处理过程中玩这个图像,我得到了和你一样的结果。

我不知道教科书的作者如何得到他们在书中显示的图像,但他们必须做更多的事情然后应用Butterworth过滤器。正如你所提到的,有更多的峰值,因此它们可能会应用更多的Butterworth滤波器去除它们。

然而,图像的平均值确实对我来说保持不变。您是否尝试过计算两幅图像的平均值并进行比较?可能是显示时只是缩放会导致图像变暗。

答案 2 :(得分:0)

我认为您使它有点复杂。 只需在Matlab上执行即可。

它给您很好的结果。

%  Question: Filtration in Frequency Domain

im = imread('applo_noisy.tif');
FT = fft2(double(im));
FT1 = fftshift(FT);%finding spectrum
%imtool(abs(FT1),[]);

m = size(im,1);
n = size(im,2);

t = 0:pi/15:2*pi;
xc=(m+150)/2; % point around which we filter image
yc=(n-150)/2;

r=200;   
r1 = 40;

xcc = r*cos(t)+xc;
ycc =  r*sin(t)+yc;
xcc1 = r1*cos(t)+xc;
ycc1 =  r1*sin(t)+yc;

mask = poly2mask(double(xcc),double(ycc), m,n); % Convert region-of-interest polygon to mask
mask1 = poly2mask(double(xcc1),double(ycc1), m,n); % generating mask for filtering

% a=51;
% b=5;
% a(b) = 0; % 51 0 0 0 0

mask(mask1)=0;

FT2=FT1;
FT2(mask)=0;%cropping area or bandreject filtering

output = ifft2(ifftshift(FT2));
imtool(output,[]);