[SciPy-User] Gaussian Filter

Sturla Molden sturla at molden.no
Fri Sep 4 23:01:29 EDT 2009


Brian Thorne skrev:
 > Similar question, but now a bit harder. I have this code (pieced 
together from a few files) that does a gaussian filter on a single image 
in both OpenCV and in SciPy.
 > It is now at a point where I cannot tell them apart with a visual 
inspection, but a imshow(image1 - image2) begs to differ. Is it going to 
be possible to get the exact same output?
 >
 >
 > from opencv import cv
 > from opencv import adaptors
 > from __future__ import division
 > import numpy as np
 > from numpy import array, uint8
 > from scipy import signal, ndimage
 >
 > @scipyFromOpenCV
 > def gaussianBlur(np_image):
 >     """Blur an image with scipy"""
 >     sigma = opencvFilt2sigma(43.0)
 >    
 >     result = ndimage.filters.gaussian_filter(np_image,
 >                             sigma=(sigma, sigma, 0),
 >                             order=0,
 >                             mode='reflect'
 >                             )
 >     return result
 >
 > def gaussianBlur(image, filterSize=43, sigma=opencvFilt2sigma(43)):
 >     """Blur an image with a particular strength filter.
 >     Default is 43, 139 gives a very strong blur, but takes a while
 >     """
 >    
 >     # Carry out the filter operation
 >     cv.cvSmooth(image, image, cv.CV_GAUSSIAN, filterSize, 0, sigma)
 >     return image


For Gaussian filtering (and Gaussian blur in particular) one can also 
use a fast IIR approximation. It will not be faster if you use small 
truncated kernels like 3 x 3 pixels, but is quite efficient and run-time 
does not depend on sigma. (I think I've posted this code before, though.)

Regards,
Sturla Molden



from numpy import array, zeros, ones, flipud, fliplr
from scipy.signal import lfilter
from math import sqrt

def __gausscoeff(s):

    # Young, I.T. and van Vliet, L.J. (1995). Recursive implementation
    # of the Gaussian filter, Signal Processing, 44: 139-151.

    if s < .5: raise ValueError, \
        'Sigma for Gaussian filter must be >0.5 samples'
    q = 0.98711*s - 0.96330 if s > 0.5 else 3.97156 \
        - 4.14554*sqrt(1.0 - 0.26891*s)
    b = zeros(4)
    b[0] = 1.5785 + 2.44413*q + 1.4281*q**2 + 0.422205*q**3
    b[1] = 2.44413*q + 2.85619*q**2 + 1.26661*q**3
    b[2] = -(1.4281*q**2 + 1.26661*q**3)
    b[3] = 0.422205*q**3
    B = 1.0 - ((b[1] + b[2] + b[3])/b[0])

    # convert to a format compatible with lfilter's
    # difference equation

    B = array([B])
    A = ones(4)
    A[1:] = -b[1:]/b[0]
    return B,A

def gaussian1D(signal, sigma, padding=0):
    n = signal.shape[0]
    tmp = zeros(n + padding)
    if tmp.shape[0] < 4: raise ValueError, \
        'Signal and padding too short'
    tmp[:n] = signal
    B,A = __gausscoeff(sigma)
    tmp = lfilter(B, A, tmp)
    tmp = tmp[::-1]
    tmp = lfilter(B, A, tmp)
    tmp = tmp[::-1]
    return tmp[:n]

def gaussian2D(image, sigma, padding=0):
    n,m = image.shape[0],image.shape[1]
    tmp = zeros((n + padding, m + padding))
    if tmp.shape[0] < 4: raise ValueError, \
        'Image and padding too small'
    if tmp.shape[1] < 4: raise ValueError, \
        'Image and padding too small'
    B,A = __gausscoeff(sigma)
    tmp[:n,:m] = image
    tmp = lfilter(B, A, tmp, axis=0)
    tmp = flipud(tmp)
    tmp = lfilter(B, A, tmp, axis=0)
    tmp = flipud(tmp)
    tmp = lfilter(B, A, tmp, axis=1)
    tmp = fliplr(tmp)
    tmp = lfilter(B, A, tmp, axis=1)
    tmp = fliplr(tmp)
    return tmp[:n,:m]






More information about the SciPy-User mailing list