-
Notifications
You must be signed in to change notification settings - Fork 21
Open
Description
i was hoping a simple little rewrite of this section of code to use broadcasting would magically make erode
fast for a boolean Zarr array, but alas, no:
diff --git a/src/extreme_filter.jl b/src/extreme_filter.jl
index 1d63ace..35af06c 100644
--- a/src/extreme_filter.jl
+++ b/src/extreme_filter.jl
@@ -527,10 +527,11 @@ function _extreme_filter_bool!(f, out, A::AbstractArray{Bool}, Ω)
R_inner = (first(R) + δ):(last(R) - δ)
select = _fast_select(f)
- @inbounds for p in R_inner
- out[p] = select(A, p, Ω)
- end
+ @info 1
+ out[R_inner] .= select.(Ref(A), R_inner, Ref(Ω))
+ @info 2
for p in EdgeIterator(R, R_inner)
+ @info p
out[p] = select(A, p, Ω)
end
return out
my test harness prints "1" and then hangs for the call to erode!
with the ZArray:
using ImageMorphology, Zarr
a = rand(Bool, 256,256,256);
z = ZArray(a);
oa = similar(a);
oz = similar(z);
se = strel_diamond((3, 3, 3));
erode!(oa, a, se);
erode!(oz, z, se);
i'm guessing it's because the logic in select
has too many branches, or perhaps because it indexes the Zarray on two different lines (544 and 550).
is there any hope to an elegant solution here? if so, i'll keep banging my head on it.
in the meantime, i've got this hack:
using ImageMorphology
for (fun, filt) in (("erode!", typemax), ("dilate!", typemin))
fun_sym = Symbol(fun)
@eval ImageMorphology.$fun_sym(out, img; dims=coords_spatial(img), r=nothing, chunk) =
ImageMorphology.$fun_sym(out, img, strel_box(img, dims; r), chunk=chunk)
@eval @doc """
$($fun)(out, img, se; chunk)
$($fun) `img` in chunks. Doing so can be much faster than the generic
element-wise algorithm if `img` is backed by, for example, a Zarr array.
`chunk` should be a tuple with an element for each dimension. The chunk
can nominally be of any size but generally should be larger than `se` and
the underlying chunk size of `img`.
# Examples
$($fun)(out, img, se; chunk=(64,64,64))
""" ImageMorphology.$fun_sym
@eval function ImageMorphology.$fun_sym(out, img, se; chunk)
pad = extrema.(axes(se))
PAD1 = CartesianIndex(ntuple(i->pad[i][1], length(pad)))
PAD2 = CartesianIndex(ntuple(i->pad[i][2], length(pad)))
ZERO = CartesianIndex(ntuple(_->0, ndims(img)))
ONE = CartesianIndex(ntuple(_->1, ndims(img)))
SIZEIMG = CartesianIndex(size(img))
CHUNK = CartesianIndex(chunk)
chunk_pad = [c+length(range(p...))-1 for (c,p) in zip(chunk,pad)]
img_chunk = Array{eltype(img)}(undef, chunk_pad...)
out_chunk = similar(img_chunk)
for I in CartesianIndices((:).(ntuple(_->1, ndims(img)), chunk, size(img)))
img_chunk .= $filt(eltype(img))
R = min(SIZEIMG, I+CHUNK-ONE)
IMG1 = max(ONE, I+PAD1)
IMG2 = min(SIZEIMG, R+PAD2)
img_chunk[ONE:IMG2-IMG1+ONE] .= img[IMG1:IMG2]
ImageMorphology.$fun_sym(out_chunk, img_chunk, se)
OUT1 = ONE-PAD1 + min(ZERO, I+PAD1-ONE)
OUT2 = OUT1+R-I
out[I:R] .= out_chunk[OUT1:OUT2]
end
end
end
thanks in advance for any help!
Metadata
Metadata
Assignees
Labels
No labels