@@ -20,6 +20,18 @@ ctypedef fused dtype_t:
20
20
cnp.float64_t
21
21
22
22
23
+ # Definition of flag values used for `flags` in _local_maxima & _fill_plateau
24
+ cdef:
25
+ # First or last index in a dimension
26
+ unsigned char BORDER_INDEX = 3
27
+ # Potentially part of a maximum
28
+ unsigned char MAYBE_MAXIMUM = 2
29
+ # Index was queued (flood-fill) and might still be part of maximum
30
+ unsigned char QUEUED_MAYBE_MAXIMUM = 1
31
+ # None of the above is true
32
+ unsigned char NOT_MAXIMUM = 0
33
+
34
+
23
35
def _local_maxima (dtype_t[::1] image not None ,
24
36
unsigned char[::1] flags ,
25
37
Py_ssize_t[::1] neighbor_offsets not None ):
@@ -46,12 +58,6 @@ def _local_maxima(dtype_t[::1] image not None,
46
58
Py_ssize_t i, i_max, i_ahead
47
59
unsigned char prefilter
48
60
49
- # Current flag meanings:
50
- # 3 - first or last index in a dimension
51
- # 2 - potentially part of a maximum
52
- # 1 - not used in first loop
53
- # 0 - not evaluated or none of the above is true
54
-
55
61
# Prefilter candidates only if neighbors in last dimension are part of
56
62
# the structuring element
57
63
prefilter = - 1 in neighbor_offsets and 1 in neighbor_offsets
@@ -61,32 +67,35 @@ def _local_maxima(dtype_t[::1] image not None,
61
67
62
68
if prefilter:
63
69
while i < i_max:
64
- if image[i - 1 ] < image[i] and flags[i] != 3 :
70
+ if image[i - 1 ] < image[i] and flags[i] != BORDER_INDEX :
65
71
# Potential maximum (in last dimension) is found, find
66
72
# other edge of current plateau or "edge of dimension"
67
73
i_ahead = i + 1
68
- while image[i] == image[i_ahead] and flags[i_ahead] != 3 :
74
+ while (
75
+ image[i] == image[i_ahead] and
76
+ flags[i_ahead] != BORDER_INDEX
77
+ ):
69
78
i_ahead += 1
70
79
if image[i] > image[i_ahead]:
71
80
# Found local maximum (in one dimension), mark all
72
81
# parts of the plateau as potential maximum
73
- flags[i:i_ahead] = 2
82
+ flags[i:i_ahead] = MAYBE_MAXIMUM
74
83
i = i_ahead
75
84
else :
76
85
i += 1
77
86
78
87
else : # Skip prefiltering and flag entire array as potential maximum
79
88
while i < i_max:
80
- if flags[i] != 3 :
81
- flags[i] = 2
89
+ if flags[i] != BORDER_INDEX :
90
+ flags[i] = MAYBE_MAXIMUM
82
91
i += 1
83
92
84
93
# Initialize a buffer used to queue positions while evaluating each
85
94
# potential maximum (flagged with 2)
86
95
queue_init(& queue, 64 )
87
96
try :
88
97
for i in range (image.shape[0 ]):
89
- if flags[i] == 2 :
98
+ if flags[i] == MAYBE_MAXIMUM :
90
99
# Index is potentially part of a maximum:
91
100
# Find all samples part of the plateau and fill with 0
92
101
# or 1 depending on whether it's a true maximum
@@ -124,13 +133,7 @@ cdef inline void _fill_plateau(
124
133
h = image[start_index]
125
134
true_maximum = 1 # Boolean flag
126
135
127
- # Current / new flag meanings:
128
- # 3 - first or last value in a dimension
129
- # 2 - not used here
130
- # 1 - index was queued and might still be part of maximum
131
- # 0 - none of the above is true
132
- # Therefore mark current index as true maximum as an initial guess
133
- flags[start_index] = 1
136
+ flags[start_index] = QUEUED_MAYBE_MAXIMUM
134
137
135
138
# And queue start position after clearing the buffer
136
139
queue_clear(queue_ptr)
@@ -144,21 +147,21 @@ cdef inline void _fill_plateau(
144
147
145
148
if image[neighbor] == h:
146
149
# Value is part of plateau
147
- if flags[neighbor] == 3 :
150
+ if flags[neighbor] == BORDER_INDEX :
148
151
# Plateau touches border and can't be maximum
149
- true_maximum = 0
150
- elif flags[neighbor] != 1 :
152
+ true_maximum = NOT_MAXIMUM
153
+ elif flags[neighbor] != QUEUED_MAYBE_MAXIMUM :
151
154
# Index wasn't queued already, do so now
152
155
queue_push(queue_ptr, & neighbor)
153
- flags[neighbor] = 1
156
+ flags[neighbor] = QUEUED_MAYBE_MAXIMUM
154
157
155
158
elif image[neighbor] > h:
156
159
# Current plateau can't be maximum because it borders a
157
160
# larger one
158
- true_maximum = 0
161
+ true_maximum = NOT_MAXIMUM
159
162
160
163
if not true_maximum:
161
164
queue_restore(queue_ptr)
162
165
# Initial guess was wrong -> replace 1 with 0 for plateau
163
166
while queue_pop(queue_ptr, & neighbor):
164
- flags[neighbor] = 0
167
+ flags[neighbor] = NOT_MAXIMUM
0 commit comments