Python Scipy Butterworth Filter

Want to understand the use of the “Butterworth Filter” in Scipy? The “Python Scipy Butterworth Filter” will be covered in this Python tutorial along with the following topics as we learn how to filter signals or images using the Python Scipy approach.

  • What is Butterworth Filter
  • Python Scipy Butterworth Filter
  • Python Scipy Butterworth Filter Bandpass
  • Python Scipy Butterworth Filter Image
  • Python Scipy Butterworth Filter Coefficient
  • Python Scipy Butterworth Vs Gaussian Filter
  • Python Scipy Butterworth Filter Order

What is Butterworth Filter

Before beginning, we need to know about some terminology used in this tutorial, like a filter, low or high pass filter, etc.

  • The word “filter” denotes the removal of undesirable elements. Water filters serve as the best illustrations of filters. Why is it utilized? Impurities are taken out of the water using it. The electric filter functions similarly to a water filter.
  • Amplifiers, inductors, capacitors, and resistors are components of the electric filter. The electric filter is used to attenuate signals that are lower or higher in frequency while allowing signals at a specific level of frequency to flow through.
  • Cut-off frequency refers to the frequency at which a filter operates. The filter’s cut-off frequency is chosen during filter design.
  • Electronic filters that allow signals with frequencies higher than a given cutoff frequency and suppress signals with frequencies lower than that cutoff frequency are referred to as high pass filters. They are also referred to as low-cut filters or bass-cut filters.
  • A low-pass filter, which permits signals with frequencies below the cut-off frequency but blocks any frequencies beyond it, is the opposite of a high-pass filter.
  • The range of wavelengths or frequencies that a filter can pass through is referred to as its passband. For instance, a radio receiver has a bandpass filter to choose the required radio signal’s frequency from among all the radio waves received by its antenna.

A signal processing filter called a Butterworth filter is made to have a frequency response that is as flat as possible in the passband. The Butterworth filter is frequently referred to as a “maximally flat magnitude filter” for this reason. Stephen Butterworth, a British physicist, and engineer, first described it in his paper “On the Theory of Filter Amplifiers” in 1930.

The Butterworth filter’s frequency response is flat in the passband (making it a bandpass filter) and rolls off to zero in the stopband. The sequence of the filter affects the rate of roll-off response. The order of the filter is determined by the number of reactive elements employed in the filter circuit.

Read: Python Scipy Curve Fit – Detailed Guide

Python Scipy Butterworth Filter

The Butterworth filter can be applied to a signal using Scipy’s butter() method. In other words, we can design a digital or analogue Nth order Butterworth filter to flatten the frequency.

The syntax is given below.

scipy.signal.butter(N, Wn, btype='low', analog=False, output='ba', fs=None)

Where parameters are:

  • N(int): It is used to specify the filter’s order.
  • Wn(array_data): It specifies the critical frequencies of high and lowpass filters.
  • btype: Used to specify which kind of filters to use like bandstop, highpass, lowpass, and bandpass.
  • analog(boolean): if it is true, then the analogue filter is used, otherwise, in the case of false, a digital filter is used.
  • output: It is used to specify the output type like zpk ( ploe-zero), sos (second-order sections), and ba (backward compatibility).

Let’s take an example by following the below steps:

Import the required libraries using the below python code.

from scipy.signal import butter
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline 

Create the time duration of the signal using the below code.

t_duration = np.linspace(0,0.5,2000,False)

Generate a signal of 20 and 40 Hz frequency using the below code.

sign = np.sin(2*np.pi*20*t_duration) + np.sin(2*np.pi*40*t_duration)

Plot the created signal using the below code.

fig, (ax1) = plt.subplots(1, 1, sharex=True)
ax1.plot(t_duration, sign)
ax1.set_title('20 and 40 Hz Sinusoid')
ax1.axis([0, 0.5, -2, 2.5])
Python Scipy Butterworth Filter example
Python Scipy Butterworth Filter example

Create a Butterworth high pass filter of 25 Hz and apply it to the above-created signal using the below code.

from scipy import signal
sos = butter(15, 20, 'hp', fs=2000, output='sos')
filtd = signal.sosfilt(sos, sign)

Plot the signal after applying the filter using the below code.

fig, (ax2) = plt.subplots(1, 1, sharex=True)
ax2.plot(t_duration, filtd)
ax2.set_title('After applying 20 Hz high-pass filter')
ax2.axis([0, 0.5, -2, 2.5])
ax2.set_xlabel('Time (seconds)')
plt.tight_layout()
plt.show()
Python Scipy Butterworth Filter
Python Scipy Butterworth Filter

This is how to use the method butter() of Python Scipy to remove the noise from a signal.

Read: Python Scipy Derivative of Array

Python Scipy Butterworth Filter Bandpass

There are bandpass filters, which combine the capabilities of high pass filters with low pass filters to only permit frequencies inside a particular frequency range. The method butter() accepts the parameter btype to specify the following filters : highpass, lowpass, bandstop and bandpass.

Let’s see with an example by following the below steps:

Import the required libraries using the below python code.

from scipy.signal import butter
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline 

Create the time duration of the signal using the below code.

t_duration = np.linspace(0,0.5,2000,False)

Generate a signal of 20 and 40 Hz frequency using the below code.

sign = np.sin(2*np.pi*20*t_duration) + np.sin(2*np.pi*40*t_duration)

Plot the created signal using the below code.

fig, (ax1) = plt.subplots(1, 1, sharex=True)
ax1.plot(t_duration, sign)
ax1.set_title('20 and 50 Hz Sinusoid')
ax1.axis([0, 0.5, -2, 2.5])
Python Scipy Butterworth Filter Bandpass
Python Scipy Butterworth Filter Bandpass

Create a Butterworth high pass filter of 30 Hz and apply it to the above-created signal using the below code.

from scipy import signal
sos = butter(15, [10,30], 'bp', fs=2000, output='sos')
filtd = signal.sosfilt(sos, sign)

Plot the signal after applying the filter using the below code.

fig, (ax2) = plt.subplots(1, 1, sharex=True)
ax2.plot(t_duration, filtd)
ax2.set_title('After applying 30 Hz high-pass filter')
ax2.axis([0, 0.5, -2, 2.5])
ax2.set_xlabel('Time (seconds)')
plt.tight_layout()
plt.show()
Python Scipy Butterworth Filter Bandpass Example
Python Scipy Butterworth Filter Bandpass Example

This is how to use the bandpass filter to take advantage of both filters low and high to allow a specific range of frequencies.

Read: Python Scipy Gamma [10 Useful Examples]

Python Scipy Butterworth Filter Image

The photos are blurred and sharpened using the Butterworth filter. In this section, we will take the image and apply the Butterworth filter to see how it filters the images by following the below steps:

Import the required libraries or methods using the below python code.

import numpy as np
import matplotlib.pyplot as plt
import cv2

Open and read the image using the method imread() of cv2.

img = cv2.imread('/content/img.jpg',0)
plt.imshow(img)
Python Scipy Butterworth Filter Image Example
Python Scipy Butterworth Filter Image Example

Image transformation into a shifted and frequency domain using the method np.fft.fft2() and np.fft.fftshift().

F_domain = np.fft.fft2(img)
F_shift = np.fft.fftshift(F_domain)

plt.imshow(np.log1p(np.abs(F_shift)), cmap='gray')
plt.axis('off')
plt.show()

Apply Butterworth low pass filter using the below code.

M_shape,N_shape = img.shape
H = np.zeros((M_shape,N_shape), dtype=np.float32)
D0 = 10 # cut-off frequency
n = 10 # It is order for butterworth
for u in range(M_shape):
    for v in range(N_shape):
        D = np.sqrt((u-M_shape/2)**2 + (v-N_shape/2)**2)
        H[u,v] = 1 / (1 + (D/D0)**n)
        
plt.imshow(H, cmap='gray')
plt.axis('off')
plt.show()
Python Scipy Butterworth Filter Image Tutorial
Python Scipy Butterworth Filter Image Tutorial

Then again apply the filters for frequency domain images using the below code.

G_shift = F_shift * H
G = np.fft.ifftshift(G_shift)
g = np.abs(np.fft.ifft2(G))

plt.imshow(g, cmap='gray')
plt.axis('off')
plt.show()
Python Scipy Butterworth Filter Image
Python Scipy Butterworth Filter Image

This is how to blur and sharpen the images using the Butterworth filter in Python Scipy.

Read: Python Scipy Stats Poisson

Python Scipy Butterworth Filter Coefficients

Butterworth Low Pass Filter of the third order the three unknown coefficients in this filter are a0, a1, and a2. These have the coefficient values a0 = 1, a1 = 2, and a2 = 2. Therefore, the filter’s nth order will have n coefficients.

IIR stands for Infinite Impulse Response, and it is one of the distinctive characteristics of many linear-time invariant systems that may be identified by having an impulse response h(t)/h(n) that never reaches zero and instead goes on indefinitely.

IIR Lowpass Butterworth: What is it? It functions essentially in the same way as a standard digital Lowpass Butterworth Filter with an infinite impulse response. In this section, we’ll use the Python codes listed below to plot the filter’s magnitude and phase response.

Import the required methods or libraries using the below code.

import numpy as np
import matplotlib.pyplot as plt
import scipy.signal as signal

Define the order of the filter, sampling frequency, cut-off frequency, and sampling parameters using the below code.

N_order = 2 
Freq_samp = 7000 
freq_cut = 3300 
Td = 1/Freq_samp

Cutting-off frequency computation using the below code.

w_d = 2*np.pi*freq_cut
print(w_d) 

Wrapping the analogue frequency using the below code.

w_c = (2/Td)*np.tan(w_d*Td/2)
print('Order of the filter=', N_order)
print('Cut-off frequency (in rad/s)=', w_c)

Using the signal.butter() method to create the filter and the signal.bilinear() function to carry out the bilinear transformation.


b, a = signal.butter(N, wc, 'low', analog='True')

z, p = signal.bilinear(b, a, fs=Fs)


Now print the coefficients using the below code.

print('Numerator-Coefficients:', z_)
print('Denominator-Coefficients:', p_)
Python Scipy Butterworth Filter Coefficients
Python Scipy Butterworth Filter Coefficients

This is how to get the coefficients of the Butterworth filter based on the order of filter using the method bilinear() of Python Scipy.

Read: Python Scipy Kdtree

Python Scipy Butterworth Vs Gaussian Filter

Higher frequencies in the image are highlighted by high pass filters. The original image is then combined with the high pass image to create a sharper image.

It could be interesting to play around with the Butterworth or Gaussian high pass filters’ width and frequency threshold. It would be fascinating to compare the sharpening done in the frequency domain to the sharpening done in the spatial domain.

High pass filters highlight the image’s high frequencies. Butterworth filters are sharper than Gaussian filters, which is how they differ from one another.

Python Scipy Butterworth Filter Order

The Python Scipy has a method buttord() in a module scipy.signal that gives the order of the lowest order Butterworth filter, whether digital or analogue, that has at least gstop dB of attenuation in the stopband and no more than gpass dB of passband loss.

The syntax is given below.

scipy.signal.buttord(wp, ws, gpass, gstop, analog=False, fs=None)

Where parameters are:

  • wp,ws(float): Edge frequencies for stopband and passband. These are in the same units as fs for digital filters. The samples are normalized from 0 to 1, where 1 is the Nyquist frequency since fs by default is 2 half-cycles/sample. (Therefore, wp and ws are in half-cycles per sample.)
  • gpass(float): Passband’s maximum loss at its maximum (dB).
  • gstop(float): The stopband’s minimal attenuation (dB).
  • analog(boolean): Return an analogue filter if True; else, return a digital filter.
  • fs(float): the system’s sampling rate in digital systems.

The method buttord() returns ord(The least expensive Butterworth filter that satisfies specifications) and wn(The natural frequency of Butterworth) of type int and ndarray or float respectively.

Let’s know with an example by following the below steps:

Import the required libraries or methods using the below python code.

from scipy.signal import buttord, butter, freqs
import numpy as np
import matplotlib.pyplot as plt

Create an analogue bandpass filter with a passband of 2 dB or less from 15 to 45 rad/s and at least -30 dB rejection from 10 to 50 rad/s.

N_ord, butt_freq = buttord([15, 45], [10, 50], 2, 30, True)
b_numerator, a_denominator = butter(N_ord, butt_freq, 'band', True)
angular_frq, freq_res = freqs(b_numerator, a_denominator, np.logspace(1, 2, 450))

Graph the frequency response while highlighting the grey passband and stopband restrictions.

plt.semilogx(angular_frq, 25 * np.log10(abs(freq_res)))
plt.title('Fitting a Butterworth bandpass filter to restrictions.')
plt.xlabel('Radians per second, frequency')
plt.ylabel('dB of amplitude')
plt.grid(which='both', axis='both')
plt.fill([1,  10,  10,   1], [-30, -30, 99, 99], '0.8', lw=0) # stop
plt.fill([15, 15,  45,  45], [-99, -2, -2, -99], '0.8', lw=0) # pass
plt.fill([50, 50, 1e9, 1e9], [99, -30, -30, 99], '0.8', lw=0) # stop
plt.axis([10, 100, -50, 2])
plt.show()
Python Scipy Butterworth Filter Order
Python Scipy Butterworth Filter Order

This is how to use the method buttord() of Python Scipy for choosing the Butterworth filter order.

You may also like to read the following Python Scipy tutorials.

So, in this tutorial, we have learned about the “Python Scipy Butterworth Filter” and covered the following topics.

  • What is Butterworth Filter
  • Python Scipy Butterworth Filter
  • Python Scipy Butterworth Filter Bandpass
  • Python Scipy Butterworth Filter Image
  • Python Scipy Butterworth Filter Coefficient
  • Python Scipy Butterworth Vs Gaussian Filter
  • Python Scipy Butterworth Filter Order