Skip to content

Commit f1f5eac

Browse files
committed
Add ModeFilter class for python
Add documentation for python
1 parent ad07844 commit f1f5eac

File tree

1 file changed

+86
-1
lines changed

1 file changed

+86
-1
lines changed

python/modefilter/__init__.py

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,54 @@
1+
"""Python API for the mode and empirical null filter - GPU ONLY
2+
3+
The empirical null filter normalises an image using the empirical null mean
4+
filter (also known as the mode filter) and the empirical null std filter.
5+
The mode filter is an edge-preserving smoothing filter by taking the local mode
6+
of the empirical density. The empirical null std filter takes the local standard
7+
deviation of the empirical density.
8+
9+
This code uses CuPy to interact with the cuda implementation of the empirical
10+
null filter. It requires the CUDA code to be compiled into a .ptx file
11+
beforehand. See PTX_FILE_PATH in this code and Makefile in the repo.
12+
13+
To use, instantiate from EmpiricalNullFilter() or ModeFilter() and modify their
14+
options if needed. Then call filter(image) to filter the image.
15+
16+
The GPU is used in the following filters:
17+
- counting the number of finite elements in the kernel using the custom cuda
18+
module (see _get_prerequisite_images() and d_count)
19+
- std filter using the custom cuda module (see _get_prerequisite_images())
20+
- median filter of the image using cupyx.scipy.ndimage (see
21+
_get_prerequisite_images())
22+
- quartile filter of the image using cupyx.scipy.ndimage (see
23+
_get_prerequisite_images())
24+
- empirical null filter of the image using the custom module (see
25+
_call_cuda_kernel())
26+
27+
Example:
28+
29+
import cupy
30+
import matplotlib.pyplot as plt
31+
import numpy as np
32+
import numpy.random
33+
import skimage.data
34+
35+
import modefilter
36+
37+
image = skimage.data.coffee()[:, :, 0]
38+
39+
plt.figure()
40+
plt.imshow(image)
41+
plt.show()
42+
43+
filter = modefilter.ModeFilter(30)
44+
filter.set_n_initial(100)
45+
filtered = filter.filter(image)
46+
47+
plt.figure()
48+
plt.imshow(filtered)
49+
plt.show()
50+
"""
51+
152
import ctypes
253
from importlib.resources import files
354
import math
@@ -23,6 +74,24 @@ class EmpiricalNullFilter:
2374
- call filter.filter(image) which returns the filtered image
2475
- call filter.get_null_mean() or filter.get_null_std() to get the
2576
the null mean or null std image
77+
78+
Attributes:
79+
_radius (float): radius of the kernel
80+
_n_initial (int): number of initial points for the Newton method
81+
_n_step (int): number of steps for the Newton method
82+
_bandwidth_parameter_a (float): bandwidth parameter A for density
83+
estimate
84+
_bandwidth_parameter_b (float): bandwidth parameter B for density
85+
estimate
86+
_block_dim_x (int): x block dimension for GPU
87+
_block_dim_y (int): y block dimension for GPU
88+
_std_for_zero (float): value to replace zero value pixels when doing
89+
std filtering
90+
_null_mean (numpy.ndarray): the resulting empirical null mean or mode
91+
filter after calling filter()
92+
_null_std (numpy.ndarray): the resulting empirical null std after
93+
calling filter()
94+
_kernel (_Kernel): the kernel used in filtering
2695
"""
2796

2897
def __init__(self, radius):
@@ -47,7 +116,7 @@ def set_n_initial(self, n_initial):
47116
self._n_initial = n_initial
48117

49118
def set_n_step(self, n_step):
50-
"""Set the number of stepsfor the Newton method
119+
"""Set the number of steps for the Newton method
51120
52121
Args:
53122
n_step (int): Number of steps for Newton method
@@ -405,6 +474,22 @@ def _get_d_kernel_pointer(self):
405474
return cupy.asarray(self._kernel.get_pointer(), cupy.int32)
406475

407476

477+
class ModeFilter(EmpiricalNullFilter):
478+
"""Mode filter using GPU
479+
480+
Get the mode filtered image
481+
482+
How to use:
483+
- construct the filter filter = Modefilter(radius)
484+
- set optional parameters, for example, filter.set_n_initial(100)
485+
- call filter.filter(image) which returns the mode image
486+
"""
487+
488+
def filter(self, image):
489+
super().filter(image)
490+
return self.get_null_mean()
491+
492+
408493
class _Kernel:
409494
"""A circular kernel which captures the local pixels
410495

0 commit comments

Comments
 (0)