Skip to content

Commit

Permalink
Added method for constructing RAG from image (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
tejus-gupta authored and timholy committed Nov 13, 2018
1 parent 7cb2ab4 commit 93d8049
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 0 deletions.
59 changes: 59 additions & 0 deletions src/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -264,3 +264,62 @@ end
# Once Base has colon defined here we can replace this
_colon(I::CartesianIndex{N}, J::CartesianIndex{N}) where N =
map((i,j) -> i:j, Tuple(I), Tuple(J))


"""
G, vertex2cartesian = region_adjacency_graph(img, weight_fn, R)
Constructs a region adjacency graph (RAG) from a N-D image `img`. It returns the RAG along
with a mapping from vertex index in RAG to cartesian index in the image.
`weight_fn` is used to assign weights to the edges using pixel similarity and spatial proximity,
where higher weight means greater similarity and thus stronger association. Zero weight is assigned
to edges between any pair of nodes that are more than `R` pixels apart. `R` can be specified
as a N-dimensional `CartesianIndex`. Alternatively, `R` can be an integer, in which a
N-dimensional `CartesianIndex` with value `R` along each dimension is used. `weight_fn` should have
signature -
edge_weight = weight_fn(p1::Pair{CartesianIndex{N},T}, p2::Pair{CartesianIndex{N},T}) where {N,T}
Any graph clustering technique can be used with the constructed RAG to segment the image.
# Example
```julia
julia> using ImageSegmentation, SimpleWeightedGraphs
julia> img = fill(1.0, (10,10))
julia> img[4:6, 4:6] .= 0
julia> weight_fn(I, J) = 1-abs(I.second - J.second)
julia> G, vertex2cartesian = region_adjacency_graph(img, weight_fn, 1)
```
"""

function region_adjacency_graph(img::AbstractArray{CT,N}, weight_fn::Function, R::CartesianIndex{N}) where {CT<:Union{Colorant,Real}, N}
cartesian2vertex = LinearIndices(img)
vertex2cartesian = CartesianIndices(img)

sources = Vector{Int}()
destinations = Vector{Int}()
weights = Vector{Float64}()

indices = CartesianIndices(axes(img));
Istart, Iend = first(indices), last(indices)
for I in indices
for J in CartesianIndices(map((i,j)->i:j, Tuple(max(Istart, I-R)), Tuple(min(Iend, I+R))))
if I <= J
continue
end
push!(sources, cartesian2vertex[I])
push!(destinations, cartesian2vertex[J])
push!(weights, weight_fn(I=>img[I], J=>img[J]))
end
end

G = SimpleWeightedGraph(sources, destinations, weights)

return G, vertex2cartesian
end

region_adjacency_graph(img::AbstractArray{CT,N}, weight_fn::Function, R::Int) where {CT<:Union{Colorant,Real}, N} = region_adjacency_graph(img, weight_fn, R * CartesianIndex{N}())
23 changes: 23 additions & 0 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,27 @@
@test all(label->(expected_means[label] new_seg.segment_means[label]), new_seg.segment_labels)
@test new_seg.image_indexmap == expected

# region_adjacency_graph
img = fill(1.0, (10,10))
img[4:6, 4:6] .= 0

weight_fn(I, J) = exp(-abs(I.second - J.second)) / ((I.first[1]-J.first[1])^2 + (I.first[2]-J.first[2])^2)
G, vertex2cartesian = region_adjacency_graph(img, weight_fn, 2)

@test nv(G) == 100
@test G.weights[45,46] == 1
@test G.weights[43,44] == exp(-1)

#test that all edges weights equal weights computed using weight_fn
@test all(map(edge-> edge.weight == weight_fn(vertex2cartesian[edge.src]=>img[vertex2cartesian[edge.src]], vertex2cartesian[edge.dst]=>img[vertex2cartesian[edge.dst]]), edges(G)))

#test that all edges are between nodes less than r pixels away
@test all(map(edge-> max(abs(vertex2cartesian[edge.src][1] - vertex2cartesian[edge.dst][1]), abs(vertex2cartesian[edge.src][2] - vertex2cartesian[edge.dst][2])) <= 2 , edges(G)))

@test region_adjacency_graph(img, weight_fn, 2) == region_adjacency_graph(img, weight_fn, CartesianIndex(2,2))

G, vertex2cartesian = region_adjacency_graph(img, weight_fn, CartesianIndex(1,2))
@test G.weights[45,47] == 0
@test G.weights[45,65] != 0

end

0 comments on commit 93d8049

Please sign in to comment.