@@ -5,77 +5,6 @@ using Statistics: mean, var
5
5
import AxisArrays
6
6
using ImageMorphology: dilate!, erode!
7
7
8
- # Compat.@dep_vectorize_2arg Gray atan2
9
- # Compat.@dep_vectorize_2arg Gray hypot
10
-
11
- """
12
- `M = meanfinite(img, region)` calculates the mean value along the dimensions listed in `region`, ignoring any non-finite values.
13
- """
14
- meanfinite (A:: AbstractArray{T} , region) where {T<: Real } = _meanfinite (A, T, region)
15
- meanfinite (A:: AbstractArray{CT} , region) where {CT<: Colorant } = _meanfinite (A, eltype (CT), region)
16
- function _meanfinite (A:: AbstractArray , :: Type{T} , region) where T<: AbstractFloat
17
- inds = Base. reduced_indices (A, region)
18
- K = similar (Array{Int}, inds)
19
- S = similar (Array{eltype (A)}, inds)
20
- fill! (K, 0 )
21
- fill! (S, zero (eltype (A)))
22
- sumfinite! (S, K, A)
23
- S./ K
24
- end
25
- _meanfinite (A:: AbstractArray , :: Type , region) = mean (A, dims= region) # non floating-point
26
-
27
- using Base: check_reducedims, reducedim1, safe_tail
28
- using Base. Broadcast: newindex
29
-
30
- """
31
- sumfinite!(S, K, A)
32
-
33
- Compute the sum `S` and number of contributing pixels `K` for
34
- reductions of the array `A` over dimensions. `S` and `K` must have
35
- identical indices, and either match `A` or have singleton-dimensions for
36
- the dimensions that are being summed over. Only pixels with finite
37
- value are included in the tallies of `S` and `K`.
38
-
39
- Note that the pixel mean is just S./K.
40
- """
41
- function sumfinite! (S, K, A:: AbstractArray{T,N} ) where {T,N}
42
- check_reducedims (S, A)
43
- isempty (A) && return S, K
44
- axes (S) == axes (K) || throw (DimensionMismatch (" S and K must have identical axes" ))
45
-
46
- indsAt, indsSt = safe_tail (axes (A)), safe_tail (axes (S))
47
- keep, Idefault = _newindexer (indsSt)
48
- if reducedim1 (S, A)
49
- # keep the accumulators as a local variable when reducing along the first dimension
50
- i1 = first (axes1 (S))
51
- @inbounds for IA in CartesianIndices (indsAt)
52
- IS = newindex (IA, keep, Idefault)
53
- s, k = S[i1,IS], K[i1,IS]
54
- for i in axes (A, 1 )
55
- tmp = A[i, IA]
56
- if isfinite (tmp)
57
- s += tmp
58
- k += 1
59
- end
60
- end
61
- S[i1,IS], K[i1,IS] = s, k
62
- end
63
- else
64
- @inbounds for IA in CartesianIndices (indsAt)
65
- IS = newindex (IA, keep, Idefault)
66
- for i in axes (A, 1 )
67
- tmp = A[i, IA]
68
- if isfinite (tmp)
69
- S[i, IS] += tmp
70
- K[i, IS] += 1
71
- end
72
- end
73
- end
74
- end
75
- S, K
76
- end
77
- _newindexer (ax) = Base. Broadcast. shapeindexer (ax)
78
-
79
8
function Statistics. var (A:: AbstractArray{C} ; kwargs... ) where C<: AbstractGray
80
9
imgc = channelview (A)
81
10
base_colorant_type (C)(var (imgc; kwargs... ))
143
72
144
73
entropy (img:: AbstractArray{C} ; kind= :shannon ) where {C<: AbstractGray } = entropy (channelview (img), kind= kind)
145
74
146
- """
147
- `m = minfinite(A)` calculates the minimum value in `A`, ignoring any values that are not finite (Inf or NaN).
148
- """
149
- function minfinite (A:: AbstractArray{T} ) where T
150
- ret = sentinel_min (T)
151
- for a in A
152
- ret = minfinite_scalar (a, ret)
153
- end
154
- ret
155
- end
156
- function minfinite (f, A:: AbstractArray )
157
- ret = sentinel_min (typeof (f (first (A))))
158
- for a in A
159
- ret = minfinite_scalar (f (a), ret)
160
- end
161
- ret
162
- end
163
-
164
- """
165
- `m = maxfinite(A)` calculates the maximum value in `A`, ignoring any values that are not finite (Inf or NaN).
166
- """
167
- function maxfinite (A:: AbstractArray{T} ) where T
168
- ret = sentinel_max (T)
169
- for a in A
170
- ret = maxfinite_scalar (a, ret)
171
- end
172
- ret
173
- end
174
- function maxfinite (f, A:: AbstractArray )
175
- ret = sentinel_max (typeof (f (first (A))))
176
- for a in A
177
- ret = maxfinite_scalar (f (a), ret)
178
- end
179
- ret
180
- end
181
-
182
- """
183
- `m = maxabsfinite(A)` calculates the maximum absolute value in `A`, ignoring any values that are not finite (Inf or NaN).
184
- """
185
- function maxabsfinite (A:: AbstractArray{T} ) where T
186
- # ColorVectorSpace v0.9 un-defines abs/abs2
187
- # https://github.com/JuliaGraphics/ColorVectorSpace.jl/pull/131
188
- _abs (a) = mapreducec (abs, + , 0 , a)
189
- ret = sentinel_min (typeof (_abs (A[1 ])))
190
- for a in A
191
- ret = maxfinite_scalar (_abs (a), ret)
192
- end
193
- ret
194
- end
195
-
196
- minfinite_scalar (a:: T , b:: T ) where {T} = isfinite (a) ? (b < a ? b : a) : b
197
- maxfinite_scalar (a:: T , b:: T ) where {T} = isfinite (a) ? (b > a ? b : a) : b
198
- minfinite_scalar (a:: T , b:: T ) where {T<: Union{Integer,FixedPoint} } = b < a ? b : a
199
- maxfinite_scalar (a:: T , b:: T ) where {T<: Union{Integer,FixedPoint} } = b > a ? b : a
200
- minfinite_scalar (a, b) = minfinite_scalar (promote (a, b)... )
201
- maxfinite_scalar (a, b) = maxfinite_scalar (promote (a, b)... )
202
-
203
- function minfinite_scalar (c1:: C , c2:: C ) where C<: AbstractRGB
204
- C (minfinite_scalar (c1. r, c2. r),
205
- minfinite_scalar (c1. g, c2. g),
206
- minfinite_scalar (c1. b, c2. b))
207
- end
208
- function maxfinite_scalar (c1:: C , c2:: C ) where C<: AbstractRGB
209
- C (maxfinite_scalar (c1. r, c2. r),
210
- maxfinite_scalar (c1. g, c2. g),
211
- maxfinite_scalar (c1. b, c2. b))
212
- end
213
-
214
- sentinel_min (:: Type{T} ) where {T<: Union{Integer,FixedPoint} } = typemax (T)
215
- sentinel_max (:: Type{T} ) where {T<: Union{Integer,FixedPoint} } = typemin (T)
216
- sentinel_min (:: Type{T} ) where {T<: AbstractFloat } = convert (T, NaN )
217
- sentinel_max (:: Type{T} ) where {T<: AbstractFloat } = convert (T, NaN )
218
- sentinel_min (:: Type{C} ) where {C<: AbstractRGB } = _sentinel_min (C, eltype (C))
219
- _sentinel_min (:: Type{C} ,:: Type{T} ) where {C<: AbstractRGB ,T} = (s = sentinel_min (T); C (s,s,s))
220
- sentinel_max (:: Type{C} ) where {C<: AbstractRGB } = _sentinel_max (C, eltype (C))
221
- _sentinel_max (:: Type{C} ,:: Type{T} ) where {C<: AbstractRGB ,T} = (s = sentinel_max (T); C (s,s,s))
222
- sentinel_min (:: Type{C} ) where {C<: AbstractGray } = _sentinel_min (C, eltype (C))
223
- _sentinel_min (:: Type{C} ,:: Type{T} ) where {C<: AbstractGray ,T} = C (sentinel_min (T))
224
- sentinel_max (:: Type{C} ) where {C<: AbstractGray } = _sentinel_max (C, eltype (C))
225
- _sentinel_max (:: Type{C} ,:: Type{T} ) where {C<: AbstractGray ,T} = C (sentinel_max (T))
226
-
227
-
228
75
# FIXME : replace with IntegralImage
229
76
# average filter
230
77
"""
@@ -269,7 +116,7 @@ macro test_approx_eq_sigma_eps(A, B, sigma, eps)
269
116
kern = KernelFactors. IIRGaussian ($ (esc (sigma)))
270
117
Af = imfilter ($ (esc (A)), kern, NA ())
271
118
Bf = imfilter ($ (esc (B)), kern, NA ())
272
- diffscale = max (maxabsfinite ( $ (esc (A))), maxabsfinite ( $ (esc (B))))
119
+ diffscale = max (_abs ( maximum_finite (abs, $ (esc (A)))), _abs ( maximum_finite (abs, $ (esc (B) ))))
273
120
d = sad (Af, Bf)
274
121
if d > length (Af)* diffscale* ($ (esc (eps)))
275
122
error (" Arrays A and B differ" )
@@ -305,7 +152,7 @@ function test_approx_eq_sigma_eps(A::AbstractArray, B::AbstractArray,
305
152
kern = KernelFactors. IIRGaussian (sigma)
306
153
Af = imfilter (A, kern, NA ())
307
154
Bf = imfilter (B, kern, NA ())
308
- diffscale = max (maxabsfinite (A), maxabsfinite (B ))
155
+ diffscale = max (_abs ( maximum_finite (abs, A)), _abs ( maximum_finite (abs, B) ))
309
156
d = sad (Af, Bf)
310
157
diffpct = d / (length (Af) * diffscale)
311
158
if diffpct > eps
@@ -314,6 +161,11 @@ function test_approx_eq_sigma_eps(A::AbstractArray, B::AbstractArray,
314
161
diffpct
315
162
end
316
163
164
+ # This should be removed when upstream ImageBase is updated
165
+ # In ImageBase v0.1.3: `maxabsfinite` returns a RGB instead of a Number
166
+ _abs (c:: CT ) where CT<: Color = mapreducec (abs, + , zero (eltype (CT)), c)
167
+ _abs (c:: Number ) = abs (c)
168
+
317
169
"""
318
170
BlobLoG stores information about the location of peaks as discovered by `blob_LoG`.
319
171
It has fields:
0 commit comments