diff --git a/NEWS.md b/NEWS.md new file mode 100644 index 0000000..1751067 --- /dev/null +++ b/NEWS.md @@ -0,0 +1,10 @@ +# NEWS + +Release 1.6: + +- New `flood` and `flood_fill!` algorithms allow segmenting just the portion of the image connected to a seed point. +- `seeded_region_growing` now allows seeds to be supplied with pair syntax, e.g., + `[CartesianIndex(300,97) => 1, CartesianIndex(145,218) => 2]`. +- Kernel/window dimensions supplied in vector format are deprecated. Instead of supplying the neighborhood size as `[3,3]`, use `(3, 3)` (`seeded_region_growing` and `unseeded_region_growing`). +- `felzenswalb` now supports multidimensional images. +- Output types use `floattype` in more places. In some cases this has resulted in `RGB{Float32}` rather than `RGB{Float64}` outputs. diff --git a/Project.toml b/Project.toml index b0947e4..a74201a 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "ImageSegmentation" uuid = "80713f31-8817-5129-9cf8-209ff8fb23e1" -version = "1.5.1" +version = "1.6.0" [deps] Clustering = "aaaa29a8-35af-508c-8bc3-b662a17a0fe5" diff --git a/src/core.jl b/src/core.jl index 8b6f425..1db388f 100644 --- a/src/core.jl +++ b/src/core.jl @@ -7,7 +7,9 @@ accum_type(::Type{C}) where {C<:Colorant} = base_colorant_type(C){accum_type(e accum_type(val) = isa(val, Type) ? throw_accum_type(val) : convert(accum_type(typeof(val)), val) throw_accum_type(T) = error("type $T not supported in `accum_type`") -_abs2(c::MathTypes) = c ⋅ c +# TODO: +# _abs2(c::MathTypes) = c ⋅ c +_abs2(c::MathTypes) = mapreducec(v->float(v)^2, +, 0, c) _abs2(x) = abs2(x) default_diff_fn(c1::CT1,c2::CT2) where {CT1<:Union{Colorant,Real}, CT2<:Union{Colorant,Real}} = sqrt(_abs2(c1-accum_type(c2))) diff --git a/src/fast_scanning.jl b/src/fast_scanning.jl index 0331ca1..aefc990 100644 --- a/src/fast_scanning.jl +++ b/src/fast_scanning.jl @@ -20,6 +20,44 @@ getscalar(A::AbstractArray{T,N}, i::CartesianIndex{N}, block_length::CartesianIn getscalar(a::Real, i...) = a +""" + seg_img = fast_scanning(img, threshold, [diff_fn]) + +Segments the N-D image using a fast scanning algorithm and returns a +[`SegmentedImage`](@ref) containing information about the segments. + +# Arguments: +* `img` : N-D image to be segmented (arbitrary axes are allowed) +* `threshold` : Upper bound of the difference measure (δ) for considering + pixel into same segment; an `AbstractArray` can be passed + having same number of dimensions as that of `img` for adaptive + thresholding +* `diff_fn` : (Optional) Function that returns a difference measure (δ) + between the mean color of a region and color of a point + +# Examples: + +```jldoctest; setup = :(using ImageCore, ImageMorphology, ImageSegmentation) +julia> img = zeros(Float64, (3,3)); + +julia> img[2,:] .= 0.5; + +julia> img[:,2] .= 0.6; + +julia> seg = fast_scanning(img, 0.2); + +julia> labels_map(seg) +3×3 $(Matrix{Int}): + 1 4 5 + 4 4 4 + 3 4 6 +``` + +# Citation: + +Jian-Jiun Ding, Cheng-Jin Kuo, Wen-Chih Hong, +"An efficient image segmentation technique by fast scanning and adaptive merging" +""" fast_scanning(img::AbstractArray{CT,N}, block::NTuple{N,Int} = ntuple(i->4,Val(N))) where {CT<:ImageCore.NumberLike,N} = fast_scanning(img, adaptive_thres(img, block)) diff --git a/test/flood_fill.jl b/test/flood_fill.jl index fcde4c7..e930c59 100644 --- a/test/flood_fill.jl +++ b/test/flood_fill.jl @@ -56,7 +56,7 @@ using Test # Colors path = download("https://github.com/JuliaImages/juliaimages.github.io/raw/source/docs/src/pkgs/segmentation/assets/flower.jpg") img = load(path) - seg = flood(img, CartesianIndex(87,280); thresh=0.3) + seg = flood(img, CartesianIndex(87,280); thresh=0.3*sqrt(3)) # TODO: eliminate the sqrt(3) when we transition to `abs2(c) = c ⋅ c` @test 0.2*length(seg) <= sum(seg) <= 0.25*length(seg) c = mean(img[seg]) # N0f8 makes for easier approximate testing