forked from alejandroklever/detedge
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdetedge.py
122 lines (85 loc) · 3.29 KB
/
detedge.py
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
from typing import Tuple, Callable, Union
import numpy as np
##############
# Type Hints #
##############
Mask = np.ndarray
Spectrum = np.ndarray
Range = Tuple[float, float]
FFilter = Callable[[np.ndarray, Union[float, Range]], np.ndarray]
def lpf(img: np.ndarray, r: float) -> Mask:
"""
Band Pass Filter compute a binary mask where
mask[i, j] = 1 if
- (i - x0) ^ 2 + (j - y0) ^ 2 <= r ^ 2
where x0 and y0 are thr coords of the center of the image
:param img: image as 2-D numpy.ndarray
:param r: radio for clean the high frequencies
:return: the binary mask
"""
rows, cols = img.shape
center = (rows // 2, cols // 2)
mask = np.zeros((rows, cols), np.uint8)
x, y = np.ogrid[:rows, :cols]
mask_area = (x - center[0]) ** 2 + (y - center[1]) ** 2 <= r ** 2
mask[mask_area] = 1
return mask
def hpf(img: np.ndarray, r: float) -> Mask:
"""
Band Pass Filter compute a binary mask where
mask[i, j] = 0 if
- (i - x0) ^ 2 + (j - y0) ^ 2 <= r ^ 2
where x0 and y0 are thr coords of the center of the image
:param img: image as 2-D numpy.ndarray
:param r: radio for clean the high frequencies
:return: the binary mask
"""
rows, cols = img.shape
center = (rows // 2, cols // 2)
mask = np.ones((rows, cols), np.uint8)
x, y = np.ogrid[:rows, :cols]
mask_area = (x - center[0]) ** 2 + (y - center[1]) ** 2 <= r ** 2
mask[mask_area] = 0
return mask
def bpf(img: np.ndarray, r: Tuple[float, float]) -> Mask:
"""
Band Pass Filter compute a binary mask where
mask[i, j] = 1 if
- r2 ^ 2 >= (i - x0) ^ 2 + (j - y0) ^ 2 >= r ^ 2
where x0 and y0 are thr coords of the center of the image
:param img: image as 2-D numpy.ndarray
:param r: 2-items tuple (inner_radio, outer_radio)
:return: a 2-D binary mask as numpy.ndarray
"""
r1, r2 = r
rows, cols = img.shape
center = (rows // 2, cols // 2)
mask = np.zeros((rows, cols), np.uint8)
x, y = np.ogrid[:rows, :cols]
mask_area = np.logical_and(
((x - center[0]) ** 2 + (y - center[1]) ** 2 >= r1 ** 2),
((x - center[0]) ** 2 + (y - center[1]) ** 2 <= r2 ** 2)
)
print(mask_area.shape)
mask[mask_area] = 1
return mask
def detect_edges(img: np.ndarray, ffilter: FFilter, r: Union[float, Range]) -> Tuple[np.ndarray, Tuple[Spectrum, Mask]]:
"""
Compute fft in the given image and filter the frequencies using the mask
returned by ffilter function in the given radio or radio_range
:param img: image as 2-D numpy.ndarray
:param ffilter: one of the functions lpf, hpf, bpf
:param r: if ffilter is lpf or hpf is a float representing the radio
if ffilter is bpf is 2-items tuple with (inner_radio, outer_radio)
:return: image as numpy.array with the applied filter
"""
mask: np.ndarray = ffilter(img, r)
fft: np.ndarray = np.fft.fft2(np.float32(img))
fft_shift: np.ndarray = np.fft.fftshift(fft)
magnitude_spectrum: np.ndarray = 20 * np.log(np.abs(fft_shift))
# apply a mask and inverse DFT
fft_shift *= mask
fshift_mask_mag = 2000 * np.log(np.abs(fft_shift))
ifft_shift = np.fft.ifftshift(fft_shift)
img_back = np.abs(np.fft.ifft2(ifft_shift))
return img_back, (magnitude_spectrum, fshift_mask_mag)