Author avatar

Vivek Kumar

Multi-dimensional Image Processing Using SciPy

Vivek Kumar

  • May 9, 2019
  • 10 Min read
  • 69 Views
  • May 9, 2019
  • 10 Min read
  • 69 Views
Data
SciPy

Introduction

In this guide, you will learn about various image processing and analysis methods provided by SciPy. So far, we have introduced you with SciPy's Linear Algebra, Stats, and Optimization Sub-packages. In this guide, we are going to focus on another SciPy subpackage named ndimage.

By the end of this guide, you will be able to implement various filter methods available inside SciPy.

The Baseline

Throughout this guide, we will be using the following libraries:

1
2
3
4
5
6
# Importing necessary libraries
import numpy as np
import scipy as sp
from scipy import ndimage
from scipy import misc
import matplotlib.pyplot as plt
python

Filter Functions

In this section, we're going to discuss the implementation of given filter categories:

  1. Smoothing filters
  2. Filters based on order statistics
  3. Derivatives

1. Smoothing Filters

SciPy provides four smoothing filter methods namely:

  • gaussian_filter1d: Implements a one-dimensional Gaussian filter. Here, the parameter sigma controls the standard-deviation of the Gaussian filter. An order of 0 would perform convolution with a Gaussian kernel, whereas, an order of 1, 2, or 3 would convolve with first, second, and third derivatives of a Gaussian.

  • gaussian_filter: This method implements a multidimensional Gaussian filter. Here, parameter sigma accepts a sequence of standard-deviation along each axis. In case if a sequence is not passed rather a single number then the standard deviation is assumed to be equal in all directions.

  • uniform_filter1d: This method calculates a one-dimensional uniform filter of the given size along the given axis.

  • uniform_filter: This method implements a multi-dimensional filter. This method also follows a similar concept as gaussian_filter method where the size of the uniform filter is given for each axis in the form of a sequence of numbers via the size parameter. However, if no sequence is passed, but a single number is passed instead, then the sizes along all the axis are considered equal.

Here, we show the implementation of these filters:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# ====================
# 1. gaussian_filter1d
# ====================
ndimage.gaussian_filter1d(np.arange(5, dtype=np.float64), sigma=1)

# Output:
# array([0.42704095, 1.06782203, 2.        , 2.93217797, 3.57295905])

ndimage.gaussian_filter1d(np.arange(5, dtype=np.float64), sigma=3)

# Output:
# array([1.67938648, 1.80184558, 2.        , 2.19815442, 2.32061352])

np.random.seed(42)
x = np.random.randn(101).cumsum()
y3 = ndimage.gaussian_filter1d(x, sigma=3)
y6 = ndimage.gaussian_filter1d(x, sigma=6)

plt.figure(figsize=(8, 5))
plt.plot(x, 'k', label='original data')
plt.plot(y3, '--', label='filtered, sigma=3')
plt.plot(y6, ':', label='filtered, sigma=6')
plt.legend()
plt.grid()
plt.show()
python

gauss1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# ==================
# 2. gaussian_filter
# ==================

mat = np.arange(100, step=4).reshape((5,5))
mat

# Output:
# array([[ 0,  4,  8, 12, 16],
#        [20, 24, 28, 32, 36],
#        [40, 44, 48, 52, 56],
#        [60, 64, 68, 72, 76],
#        [80, 84, 88, 92, 96]])


ndimage.gaussian_filter(mat, sigma=1)

# Output:
# array([[ 9, 12, 16, 19, 22],
#        [22, 25, 29, 32, 35],
#        [41, 44, 48, 51, 54],
#        [59, 62, 66, 69, 72],
#        [72, 75, 79, 82, 85]])

ndimage.gaussian_filter(mat, sigma=2)

# Output:
# array([[26, 27, 30, 32, 33],
#        [33, 34, 37, 39, 40],
#        [44, 45, 48, 50, 51],
#        [54, 55, 58, 60, 61],
#        [61, 62, 65, 67, 68]])

fig = plt.figure(figsize=(12, 8))
ax1 = fig.add_subplot(121)  # First subplot
ax2 = fig.add_subplot(122)  # Second subplot
ascent = misc.ascent()
result = ndimage.gaussian_filter(ascent, sigma=5)
ax1.imshow(ascent)
ax2.imshow(result)
plt.show()
python

Gauss2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# ===================
# 3. uniform_filter1d
# ===================
ndimage.uniform_filter1d(np.arange(10), size=3)

# Output:
# array([0, 1, 2, 3, 4, 5, 6, 7, 8, 8])

np.random.seed(42)
x = np.random.randn(101).cumsum()
y3 = ndimage.uniform_filter1d(x, size=3)
y10 = ndimage.uniform_filter1d(x, size=10)

plt.figure(figsize=(8, 5))
plt.plot(x, 'k', label='original data')
plt.plot(y3, '--', label='filtered, size=3')
plt.plot(y10, ':', label='filtered, size=10')
plt.legend()
plt.grid()
plt.show()
python

Uni

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# =================
# 4. uniform_filter
# =================
mat = np.arange(100, step=4).reshape((5,5))
mat

# Output:
# array([[ 0,  4,  8, 12, 16],
#        [20, 24, 28, 32, 36],
#        [40, 44, 48, 52, 56],
#        [60, 64, 68, 72, 76],
#        [80, 84, 88, 92, 96]])

ndimage.uniform_filter(mat, size=3)

# Output:
# array([[ 7, 10, 14, 18, 20],
#        [21, 24, 28, 32, 34],
#        [41, 44, 48, 52, 54],
#        [61, 64, 68, 72, 74],
#        [74, 77, 81, 85, 87]])


fig = plt.figure(figsize=(12, 8))
ax1 = fig.add_subplot(121)  # First subplot
ax2 = fig.add_subplot(122)  # Second subplot
ascent = misc.ascent()
result = ndimage.uniform_filter(ascent, size=7)
ax1.imshow(ascent)
ax2.imshow(result)
plt.show()
python

Uni2

2. Filters Based on Order Statistics

There are seven filters provided by SciPy based on order statistics:

  • minimum_filter1d: This method calculates a one-dimensional minimum filter of a given size on a given axis.

  • maximum_filter1d: This method calculates a one-dimensional maximum filter of a given size on a given axis.

  • minimum_filter: This method calculates a multi-dimensional minimum filter.

  • maximum_filter: This method calculates a multi-dimensional maximum filter.

  • rank_filter: This method calculates a multi-dimensional rank filter.

  • percentile_filter: This method calculates a multi-dimensional percentile filter.

  • median_filter: This method calculates a multi-dimensional median filter.

Here's an implementation of these filters in python:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# ===================
# 1. minimum_filter1d
# ===================

np.random.seed(42)
x = np.random.randn(101).cumsum()
y3 = ndimage.minimum_filter1d(x, size=3)
y10 = ndimage.minimum_filter1d(x, size=10)
plt.figure(figsize=(8, 5))
plt.plot(x, 'k', label='original data')
plt.plot(y3, '--', label='filtered, size=3')
plt.plot(y10, ':', label='filtered, size=10')
plt.legend()
plt.grid()
plt.show()
python

Min1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# ===================
# 2. maximum_filter1d
# ===================

np.random.seed(42)
x = np.random.randn(101).cumsum()
y3 = ndimage.maximum_filter1d(x, size=3)
y10 = ndimage.maximum_filter1d(x, size=10)
plt.figure(figsize=(8, 5))
plt.plot(x, 'k', label='original data')
plt.plot(y3, '--', label='filtered, size=3')
plt.plot(y10, ':', label='filtered, size=10')
plt.legend()
plt.grid()
plt.show()
python

Max1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# ============================================
# minimum_filter, maximum_filter, rank_filter
# percentile_filter, median_filter
# ============================================

fig = plt.figure(figsize=(15, 15))
ax1 = fig.add_subplot(321)  # First subplot
ax1.set_title('Original', fontsize=16, weight='bold')
ax2 = fig.add_subplot(322)  # Minimum Filter
ax2.set_title('Minimum Filter', fontsize=16, weight='bold')
ax3 = fig.add_subplot(323)  # Maximum Filter
ax3.set_title('Maximum Filter', fontsize=16, weight='bold')
ax4 = fig.add_subplot(324)  # Rank Filter
ax4.set_title('Rank Filter', fontsize=16, weight='bold')
ax5 = fig.add_subplot(325)  # Percentile Filter
ax5.set_title('Percentile Filter', fontsize=16, weight='bold')
ax6 = fig.add_subplot(326)  # Median Filter
ax6.set_title('Median Filter', fontsize=16, weight='bold')

ascent = misc.ascent()
min_filt = ndimage.minimum_filter(ascent, size=7)
max_filt = ndimage.maximum_filter(ascent, size=7)
rank_filt = ndimage.rank_filter(ascent, rank=30, size=7)
per_filt = ndimage.percentile_filter(ascent, percentile=20, size=7)
med_filt = ndimage.median_filter(ascent, size=7)

ax1.imshow(ascent)
ax2.imshow(min_filt)
ax3.imshow(max_filt)
ax4.imshow(rank_filt)
ax5.imshow(per_filt)
ax6.imshow(med_filt)

plt.show()
python

All

3. Derivatives

Derivative filters are commonly used in edge detection processes. Prewitt and Sobel are two such derivative filters whose direct methods are available in SciPy. Here we describe their implementation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# ===============
# Prewitt filter
# ===============
fig = plt.figure(figsize=(8, 5))
ax1 = fig.add_subplot(121)  # Original
ax1.set_title('Original', fontsize=16, weight='bold')
ax2 = fig.add_subplot(122)  # Prewitt
ax2.set_title('Prewitt Filter', fontsize=16, weight='bold')

ascent = misc.ascent()
result = ndimage.prewitt(ascent)

ax1.imshow(ascent)
ax2.imshow(result)
plt.show()
python

Prewitt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# ===============
# Sobel filter
# ===============
fig = plt.figure(figsize=(8, 5))
ax1 = fig.add_subplot(121)  # Original
ax1.set_title('Original', fontsize=16, weight='bold')
ax2 = fig.add_subplot(122)  # Sobel
ax2.set_title('Sobel Filter', fontsize=16, weight='bold')

ascent = misc.ascent()
result = ndimage.sobel(ascent)

ax1.imshow(ascent)
ax2.imshow(result)
plt.show()
python

Sobel

Conclusion

In this guide, you have learned about various filter functions which are available in SciPy ndimage sub-package.

To revisit on additional concepts on SciPy, you can refer the following guides:

0