From 717964401b90e47fa8e278b6940d88843d6a6209 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Thu, 2 Sep 2021 02:41:51 -0500 Subject: [PATCH] Add findall_window --- src/ImageFiltering.jl | 3 ++- src/findall_window.jl | 51 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/findall_window.jl diff --git a/src/ImageFiltering.jl b/src/ImageFiltering.jl index 27a68ca..3cc29bc 100644 --- a/src/ImageFiltering.jl +++ b/src/ImageFiltering.jl @@ -16,7 +16,7 @@ export Kernel, KernelFactors, BorderArray, Algorithm, imfilter, imfilter!, - mapwindow, mapwindow!, + mapwindow, mapwindow!, findall_window, imgradients, padarray, centered, kernelfactors, reflect, freqkernel, spacekernel, findlocalminima, findlocalmaxima, @@ -89,6 +89,7 @@ include("specialty.jl") include("mapwindow.jl") using .MapWindow include("extrema.jl") +include("findall_window.jl") function __init__() # See ComputationalResources README for explanation diff --git a/src/findall_window.jl b/src/findall_window.jl new file mode 100644 index 0000000..0fd827c --- /dev/null +++ b/src/findall_window.jl @@ -0,0 +1,51 @@ +""" + findall_window(f, img::AbstractArray{T,N}, window::Dims{N}; allow_edges::(true...,)) + +Return the list of window-centers for which `f(V, basepoint)` returns `true` for windowed-views `V` +"centered" on `basepoint`. At the edge of `img`, `basepoint` may not actually be in the center of `V`. +""" +function findall_window(f::F, img::AbstractArray{T,N}, window::Dims{N}; allow_edges::NTuple{N,Bool}=ntuple(_->true, N)) where {F,T<:Union{Gray,Number},N} + basepoints = Vector{CartesianIndex{N}}(undef, 0) + Iedge = CartesianIndex(map(!, allow_edges)) + R0 = CartesianIndices(img) + R = clippedinds(R0, Iedge) + halfwindow = CartesianIndex(map(x -> x >> 1, window)) + for i in R + Rview = _colon(i-halfwindow, i+halfwindow) ∩ R0 + if f(OffsetArray(@inbounds(view(img, Rview)), Rview.indices), i) + push!(basepoints, i) + end + end + return basepoints +end + +""" + all_window(f, V, basepoint, excludepoint=nothing) + +Returns `true` if `f(img[centerpoint], img[otherpoint])` for all indices `otherpoint`. +Optionally exclude a single point (e.g., `basepoint` itself) by setting `excludepoint`. +""" +@inline function all_window(f::F, V::AbstractArray, basepoint::CartesianIndex, excludepoint::Union{Nothing,CartesianIndex}=nothing) where F + @inbounds ref = V[basepoint] + @inbounds for (i, v) in pairs(V) + i == excludepoint || f(ref, v) || return false + end + return true +end + +""" + ismax_window(V, basepoint) + +Returns `true` if `V[basepoint] > V[otherpoint]` for all indices `otherpoint != basepoint` in `V`. +""" +@inline ismax_window(V, i) = all_window(>, V, i, i) + +""" + ismin_window(V, basepoint) + +Returns `true` if `V[basepoint] < V[otherpoint]` for all indices `otherpoint != basepoint` in `V`. +""" +@inline ismin_window(V, i) = all_window(<, V, i, i) + +findmax_window(A, window; kwargs...) = findall_window(ismax_window, A, window; kwargs...) +findmin_window(A, window; kwargs...) = findall_window(ismin_window, A, window; kwargs...)