Skip to content

Commit

Permalink
Merge pull request #30 from JuliaImages/teh/updates_docs
Browse files Browse the repository at this point in the history
Updates in documentation, and fixes in mean eltype computation
  • Loading branch information
timholy authored Oct 4, 2018
2 parents 884af7c + db7ce9a commit 7cb2ab4
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 48 deletions.
2 changes: 1 addition & 1 deletion src/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ segment_mean(r::FuzzyCMeansResult) = Dict([(i, segment_mean(r,i)) for i in segme

# Dispatch on show
function show(io::IO, seg::SegmentedImage)
print(io, "Segmented Image with:\n\t labels map: ", summary(labels_map(seg)), "\n\t number of labels: ", length(segment_labels(seg)))
print(io, "Segmented Image with:\n labels map: ", summary(labels_map(seg)), "\n number of labels: ", length(segment_labels(seg)))
end

"""
Expand Down
13 changes: 9 additions & 4 deletions src/fast_scanning.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,15 @@ Segments the N-D image using a fast scanning algorithm and returns a
# Examples:
```jldoctest
```jldoctest; setup = :(using Images, ImageSegmentation)
julia> img = zeros(Float64, (3,3));
julia> img[2,:] = 0.5;
julia> img[:,2] = 0.6;
julia> img[2,:] .= 0.5;
julia> img[:,2] .= 0.6;
julia> seg = fast_scanning(img, 0.2);
julia> labels_map(seg)
3×3 Array{Int64,2}:
1 4 5
Expand All @@ -69,8 +73,9 @@ function fast_scanning(img::AbstractArray{CT,N}, threshold::Union{AbstractArray,
neighbourhood(x) = ntuple(i-> x-half_region[i], Val(N))

# Required data structures
TM = meantype(CT)
result = fill(-1, axes(img)) # Array to store labels
region_means = Dict{Int, Images.accum(CT)}() # A map conatining (label, mean) pairs
region_means = Dict{Int, TM}() # A map conatining (label, mean) pairs
region_pix_count = Dict{Int, Int}() # A map conatining (label, count) pairs
temp_labels = IntDisjointSets(0) # Disjoint set to map labels to their equivalence class
v_neigh = MVector{N,Int}(undef) # MVector to store valid neighbours
Expand Down
3 changes: 1 addition & 2 deletions src/felzenszwalb.jl
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ function felzenszwalb(edges::Array{ImageEdge}, num_vertices::Int, k::Real, min_s
return index_map, num_sets
end

meantype(::Type{T}) where T = Images.accum(T)
meantype(::Type{T}) where T<:Integer = Float64
meantype(::Type{T}) where T = typeof(zero(Images.accum(T))/2)

function felzenszwalb(img::AbstractArray{T, 2}, k::Real, min_size::Int = 0) where T<:Union{Real,Color}

Expand Down
5 changes: 3 additions & 2 deletions src/meanshift.jl
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,10 @@ function meanshift(img::Array{CT, 2}, spatial_radius::Real, range_radius::Real;

clusters = dbscan(modes, 1.414)
num_segments = length(clusters)
TM = meantype(CT)
result = similar(img, Int)
labels = Array(1:num_segments)
region_means = Dict{Int, Images.accum(CT)}()
region_means = Dict{Int, TM}()
region_pix_count = Dict{Int, Int}()

cluster_idx = 0
Expand All @@ -81,7 +82,7 @@ function meanshift(img::Array{CT, 2}, spatial_radius::Real, range_radius::Real;
for index in [cluster.core_indices; cluster.boundary_indices]
i, j = (index-1)%rows + 1, floor(Int, (index-1)/rows) + 1
result[i, j] = cluster_idx
region_means[cluster_idx] = get(region_means, cluster_idx, zero(Images.accum(CT))) + img[i, j]
region_means[cluster_idx] = get(region_means, cluster_idx, zero(TM)) + img[i, j]
end
region_means[cluster_idx] /= region_pix_count[cluster_idx]
end
Expand Down
32 changes: 20 additions & 12 deletions src/region_growing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,21 @@ and returns a [`SegmentedImage`](@ref) containing information about the segments
# Examples
```jldoctest
```jldoctest; setup = :(using Images, ImageSegmentation)
julia> img = zeros(Gray{N0f8},4,4);
julia> img[2:4,2:4] = 1;
julia> img[2:4,2:4] .= 1;
julia> seeds = [(CartesianIndex(3,1),1),(CartesianIndex(2,2),2)];
julia> seg = seeded_region_growing(img, seeds);
julia> labels_map(seg)
4×4 Array{Int64,2}:
1 1 1 1
1 2 2 2
1 2 2 2
1 2 2 2
```
# Citation:
Expand All @@ -50,7 +53,7 @@ Albert Mehnert, Paul Jackaway (1997), "An improved seeded region growing algorit
Pattern Recognition Letters 18 (1997), 1065-1071
"""
function seeded_region_growing(img::AbstractArray{CT,N}, seeds::AbstractVector{Tuple{CartesianIndex{N},Int}},
kernel_dim::Union{Vector{Int}, NTuple{N, Int}} = ntuple(i->3,N), diff_fn::Function = default_diff_fn) where {CT<:Colorant, N}
kernel_dim::Union{Vector{Int}, NTuple{N, Int}} = ntuple(i->3,N), diff_fn::Function = default_diff_fn) where {CT<:Union{Colorant,Real}, N}
length(kernel_dim) == N || error("Dimension count of image and kernel_dim do not match")
for dim in kernel_dim
dim > 0 || error("Dimensions of the kernel must be positive")
Expand All @@ -62,7 +65,7 @@ function seeded_region_growing(img::AbstractArray{CT,N}, seeds::AbstractVector{T
end

function seeded_region_growing(img::AbstractArray{CT,N}, seeds::AbstractVector{Tuple{CartesianIndex{N},Int}},
neighbourhood::Function, diff_fn::Function = default_diff_fn) where {CT<:Colorant, N}
neighbourhood::Function, diff_fn::Function = default_diff_fn) where {CT<:Union{Colorant,Real}, N}

_QUEUE_SZ = 10

Expand All @@ -71,22 +74,24 @@ function seeded_region_growing(img::AbstractArray{CT,N}, seeds::AbstractVector{T
seed[2] > 0 || error("Seed labels need to be positive integers!")
end

TM = meantype(CT)

# Required data structures
result = fill(-1, axes(img)) # Array to store labels
nhq = Queue{CartesianIndex{N}}(_QUEUE_SZ) # Neighbours holding queue
pq = PriorityQueue{Queue{CartesianIndex{N}}, Float64}() # Priority Queue to hold the queues of same δ value
qdict = Dict{Float64, Queue{CartesianIndex{N}}}() # A map to get a reference to queue using the δ value
labelsq = Queue{Int}(_QUEUE_SZ) # Queue to hold labels
holdingq = Queue{CartesianIndex{N}}(_QUEUE_SZ) # Queue to hold points corresponding to the labels in `labelsq`
region_means = Dict{Int, Images.accum(CT)}() # A map containing (label, mean) pairs
region_means = Dict{Int, TM}() # A map containing (label, mean) pairs
region_pix_count = Dict{Int, Int}() # A map containing (label, pixel_count) pairs
labels = Vector{Int}() # A vector containing list of labels

# Labelling initial seeds and initialising `region_means` and `region_pix_count`
for seed in seeds
result[seed[1]] = seed[2]
region_pix_count[seed[2]] = get(region_pix_count, seed[2], 0) + 1
region_means[seed[2]] = get(region_means, seed[2], zero(Images.accum(CT))) + (img[seed[1]] - get(region_means, seed[2], zero(Images.accum(CT))))/(region_pix_count[seed[2]])
region_means[seed[2]] = get(region_means, seed[2], zero(TM)) + (img[seed[1]] - get(region_means, seed[2], zero(TM)))/(region_pix_count[seed[2]])
if ! (seed[2] in labels)
push!(labels, seed[2])
end
Expand Down Expand Up @@ -230,17 +235,19 @@ and returns a [`SegmentedImage`](@ref) containing information about the segments
# Examples
```jldoctest
```jldoctest; setup = :(using Images, ImageSegmentation)
julia> img = zeros(Gray{N0f8},4,4);
julia> img[2:4,2:4] = 1;
julia> img[2:4,2:4] .= 1;
julia> seg = unseeded_region_growing(img, 0.2);
julia> labels_map(seg)
4×4 Array{Int64,2}:
1 1 1 1
1 2 2 2
1 2 2 2
1 2 2 2
```
"""
Expand All @@ -257,11 +264,12 @@ function unseeded_region_growing(img::AbstractArray{CT,N}, threshold::Real,
end

function unseeded_region_growing(img::AbstractArray{CT,N}, threshold::Real, neighbourhood::Function, diff_fn = default_diff_fn) where {CT<:Colorant,N}
TM = meantype(CT)

# Required data structures
result = fill(-1, axes(img)) # Array to store labels
neighbours = PriorityQueue{CartesianIndex{N},Float64}() # Priority Queue containing boundary pixels with δ as the priority
region_means = Dict{Int, Images.accum(CT)}() # A map containing (label, mean) pairs
region_means = Dict{Int, TM}() # A map containing (label, mean) pairs
region_pix_count = Dict{Int, Int}() # A map containing (label, pixel_count) pairs
labels = Vector{Int}() # Vector containing assigned labels

Expand Down Expand Up @@ -321,7 +329,7 @@ function unseeded_region_growing(img::AbstractArray{CT,N}, threshold::Real, neig

#Update region_means
region_pix_count[minlabel] = get(region_pix_count, minlabel, 0) + 1
region_means[minlabel] = get(region_means, minlabel, zero(Images.accum(CT))) + (pixelval - get(region_means, minlabel, zero(Images.accum(CT))))/(region_pix_count[minlabel])
region_means[minlabel] = get(region_means, minlabel, zero(TM)) + (pixelval - get(region_means, minlabel, zero(TM)))/(region_pix_count[minlabel])

# Enqueue neighbours of `point`
for p in neighbourhood(point)
Expand Down
18 changes: 13 additions & 5 deletions src/region_merging.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,16 @@ Returns true if `img` is homogeneous.
# Examples
```jldoctest
# img is an array with elements of type `Float64`
```jldoctest; setup = :(using Images, ImageSegmentation)
julia> img = 0.1*rand(6, 6);
julia> img[4:end, 4:end] .+= 10;
julia> function homogeneous(img)
min, max = extrema(img)
max - min < 0.2
end
homogeneous (generic function with 1 method)
julia> t = region_tree(img, homogeneous);
```
Expand Down Expand Up @@ -97,20 +101,24 @@ Returns true if `img` is homogeneous.
# Examples
```jldoctest
# img is an array with elements of type `Float64`
```jldoctest; setup = :(using Images, ImageSegmentation)
julia> img = 0.1*rand(6, 6);
julia> img[4:end, 4:end] .+= 10;
julia> function homogeneous(img)
min, max = extrema(img)
max - min < 0.2
end
homogeneous (generic function with 1 method)
julia> seg = region_splitting(img, homogeneous);
```
"""
function region_splitting(img::AbstractArray{T,N}, homogeneous::Function) where T<:Union{Colorant, Real} where N
rtree = region_tree(img, homogeneous)
seg = SegmentedImage(similar(img, Int), Vector{Int}(), Dict{Int, Images.accum(T)}(), Dict{Int, Int}())
seg = SegmentedImage(similar(img, Int), Vector{Int}(), Dict{Int, meantype(T)}(), Dict{Int, Int}())
lc = 1
lc = fill_recursive!(seg, seg.image_indexmap, lc, rtree)
seg
Expand Down
5 changes: 3 additions & 2 deletions src/watershed.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,15 @@ function watershed(img::AbstractArray{T, N}, markers::AbstractArray{S,N}) where
end
end

TM = meantype(T)
num_segments = Int(maximum(segments))
labels = Array(1:num_segments)
region_means = Dict{Int, Images.accum(T)}()
region_means = Dict{Int, TM}()
region_pix_count = Dict{Int, Int}()

for i in R
region_pix_count[segments[i]] = get(region_pix_count, segments[i], 0) + 1
region_means[segments[i]] = get(region_means, segments[i], zero(Images.accum(T))) + (img[i] - get(region_means, segments[i], zero(Images.accum(T))))/region_pix_count[segments[i]]
region_means[segments[i]] = get(region_means, segments[i], zero(TM)) + (img[i] - get(region_means, segments[i], zero(TM)))/region_pix_count[segments[i]]
end
return SegmentedImage(segments, labels, region_means, region_pix_count)
end
Expand Down
19 changes: 11 additions & 8 deletions test/felzenszwalb.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@
@test all(label->(label==result.image_indexmap[2,2]), result.image_indexmap[2:3, 2:3])
@test all(label->(label==result.image_indexmap[5,5]), result.image_indexmap[5:6, 5:6])

@test result.segment_means[result.image_indexmap[1,1]] == zero(Images.accum(T))
@test result.segment_means[result.image_indexmap[2,2]] == Images.accum(T)(img[2,2])
@test result.segment_means[result.image_indexmap[2,8]] == Images.accum(T)(img[2,8])
@test result.segment_means[result.image_indexmap[5,5]] == Images.accum(T)(img[5,5])
TM = ImageSegmentation.meantype(T)
@test result.segment_means[result.image_indexmap[1,1]] == zero(TM)
@test result.segment_means[result.image_indexmap[2,2]] == TM(img[2,2])
@test result.segment_means[result.image_indexmap[2,8]] == TM(img[2,8])
@test result.segment_means[result.image_indexmap[5,5]] == TM(img[5,5])

@test result.segment_pixel_count[result.image_indexmap[1,1]] == 91
@test result.segment_pixel_count[result.image_indexmap[2,2]] == 4
Expand All @@ -30,6 +31,7 @@
img[2, 8] = RGB(0.5,0.5,0.5)
img[5:6, 5:6] .= RGB(0.8,0.8,0.8)
T = RGB{Float64}
TM = ImageSegmentation.meantype(T)

result = felzenszwalb(img, 1, 2)

Expand All @@ -41,8 +43,8 @@
@test all(label->(label==result.image_indexmap[5,5]), result.image_indexmap[5:6, 5:6])

@test result.segment_means[result.image_indexmap[1,1]] RGB{Float64}(0.5/92, 0.5/92, 0.5/92)
@test result.segment_means[result.image_indexmap[2,2]] == Images.accum(T)(img[2,2])
@test result.segment_means[result.image_indexmap[5,5]] == Images.accum(T)(img[5,5])
@test result.segment_means[result.image_indexmap[2,2]] == TM(img[2,2])
@test result.segment_means[result.image_indexmap[5,5]] == TM(img[5,5])

@test result.segment_pixel_count[result.image_indexmap[1,1]] == 92
@test result.segment_pixel_count[result.image_indexmap[2,2]] == 4
Expand All @@ -54,6 +56,7 @@
img[2, 8] = true
img[5:6, 5:6] .= true
T = Bool
TM = ImageSegmentation.meantype(T)

result = felzenszwalb(img, 1, 2)

Expand All @@ -65,8 +68,8 @@
@test all(label->(label==result.image_indexmap[5,5]), result.image_indexmap[5:6, 5:6])

@test result.segment_means[result.image_indexmap[1,1]] 1/92
@test result.segment_means[result.image_indexmap[2,2]] == Images.accum(T)(img[2,2])
@test result.segment_means[result.image_indexmap[5,5]] == Images.accum(T)(img[5,5])
@test result.segment_means[result.image_indexmap[2,2]] == TM(img[2,2])
@test result.segment_means[result.image_indexmap[5,5]] == TM(img[5,5])

@test result.segment_pixel_count[result.image_indexmap[1,1]] == 92
@test result.segment_pixel_count[result.image_indexmap[2,2]] == 4
Expand Down
9 changes: 5 additions & 4 deletions test/meanshift.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
img[2, 8] = 0.5
img[5:6, 5:6] .= 0.8
T = Gray{N0f8}
TM = ImageSegmentation.meantype(T)

result = meanshift(img, 8, 7/255)

Expand All @@ -14,10 +15,10 @@
@test all(label->(label==result.image_indexmap[2,2]), result.image_indexmap[2:3, 2:3])
@test all(label->(label==result.image_indexmap[5,5]), result.image_indexmap[5:6, 5:6])

@test result.segment_means[result.image_indexmap[1,1]] == zero(Images.accum(T))
@test result.segment_means[result.image_indexmap[2,2]] == Images.accum(T)(img[2,2])
@test result.segment_means[result.image_indexmap[2,8]] == Images.accum(T)(img[2,8])
@test result.segment_means[result.image_indexmap[5,5]] == Images.accum(T)(img[5,5])
@test result.segment_means[result.image_indexmap[1,1]] == zero(TM)
@test result.segment_means[result.image_indexmap[2,2]] == TM(img[2,2])
@test result.segment_means[result.image_indexmap[2,8]] == TM(img[2,8])
@test result.segment_means[result.image_indexmap[5,5]] == TM(img[5,5])

@test result.segment_pixel_count[result.image_indexmap[1,1]] == 91
@test result.segment_pixel_count[result.image_indexmap[2,2]] == 4
Expand Down
Loading

0 comments on commit 7cb2ab4

Please sign in to comment.