11"""
2- ```
3- segments = felzenszwalb(img, k, [min_size])
4- index_map, num_segments = felzenszwalb(edges, num_vertices, k, [min_size])
5- ```
2+ index_map, num_segments = felzenszwalb(edges, num_vertices, k, min_size=0)
63
7- Segments an image using Felzenszwalb's graph-based algorithm. The function can be used in either of two ways -
8-
9- 1. `segments = felzenszwalb(img, k, [min_size])`
10-
11- Segments an image using Felzenszwalb's segmentation algorithm and returns the result as `SegmentedImage`. The algorithm uses
12- euclidean distance in color space as edge weights for the region adjacency graph.
13-
14- Parameters:
15- - img = input image
16- - k = Threshold for region merging step. Larger threshold will result in bigger segments.
17- - min_size = Minimum segment size
18-
19- 2. `index_map, num_segments = felzenszwalb(edges, num_vertices, k, [min_size])`
20-
21- Segments an image represented as Region Adjacency Graph(RAG) using Felzenszwalb's segmentation algorithm. Each pixel/region
22- corresponds to a node in the graph and weights on each edge measure the dissimilarity between pixels.
4+ Segment an image represented as Region Adjacency Graph(RAG) using Felzenszwalb's segmentation algorithm. Each pixel/region
5+ corresponds to a node in the graph and weights on each edge measure the dissimilarity between pixels.
236The function returns the number of segments and index mapping from nodes of the RAG to segments.
247
258Parameters:
26- - edges = Array of edges in RAG. Each edge is represented as `ImageEdge`.
27- - num_vertices = Number of vertices in RAG
28- - k = Threshold for region merging step. Larger threshold will result in bigger segments.
29- - min_size = Minimum segment size
30-
31-
9+ - `edges`: Array of edges in RAG. Each edge is represented as `ImageEdge`.
10+ - `num_vertices`: Number of vertices in RAG
11+ - `k`: Threshold for region merging step. Larger threshold will result in bigger segments.
12+ - `min_size`: Minimum segment size (in # pixels)
3213"""
33- function felzenszwalb (edges:: Array{ImageEdge} , num_vertices:: Int , k:: Real , min_size:: Int = 0 )
14+ function felzenszwalb (edges:: Array{ImageEdge} , num_vertices:: Int , k:: Float64 , min_size:: Int = 0 )
3415
3516 num_edges = length (edges)
3617 G = IntDisjointSets (num_vertices)
@@ -61,7 +42,7 @@ function felzenszwalb(edges::Array{ImageEdge}, num_vertices::Int, k::Real, min_s
6142 end
6243 end
6344
64- segments = OrderedSet ()
45+ segments = OrderedSet {Int} ()
6546 for i in 1 : num_vertices
6647 push! (segments, find_root! (G, i))
6748 end
@@ -72,35 +53,59 @@ function felzenszwalb(edges::Array{ImageEdge}, num_vertices::Int, k::Real, min_s
7253 segments2index[s] = i
7354 end
7455
75- index_map = Array {Int} (undef, num_vertices)
56+ index_map = Vector {Int} (undef, num_vertices)
7657 for i in 1 : num_vertices
7758 index_map[i] = segments2index[find_root! (G, i)]
7859 end
7960
8061 return index_map, num_sets
8162end
63+ felzenszwalb (edges:: Array{ImageEdge} , num_vertices:: Integer , k:: Real , min_size:: Integer = 0 ) =
64+ felzenszwalb (edges, convert (Int, num_vertices):: Int , convert (Float64, k):: Float64 , convert (Int, min_size):: Int )
8265
8366meantype (:: Type{T} ) where T = typeof (zero (accum_type (T))/ 2 )
8467
85- function felzenszwalb (img:: AbstractArray{T, 2} , k:: Real , min_size:: Int = 0 ) where T<: Union{Real,Color}
68+ """
69+ segments = felzenszwalb(img, k, [min_size])
70+
71+ Segment an image using Felzenszwalb's segmentation algorithm and returns the result as `SegmentedImage`.
72+ The algorithm uses euclidean distance in color space as edge weights for the region adjacency graph.
73+
74+ Parameters:
75+ - `img`: input image
76+ - `k`: Threshold for region merging step. Larger threshold will result in bigger segments.
77+ - `min_size`: Minimum segment size (in # pixels)
78+ """
79+ function felzenszwalb (img:: AbstractArray{T} , k:: Real , min_size:: Int = 0 ) where T<: Union{Real,Color}
80+
81+ sz = size (img)
82+ num_vertices = prod (sz)
8683
87- rows, cols = size (img)
88- num_vertices = rows * cols
89- num_edges = 4 * rows * cols - 3 * rows - 3 * cols + 2
90- edges = Array {ImageEdge} (undef, num_edges )
84+ R = CartesianIndices (img)
85+ L = LinearIndices (img)
86+ Ibegin, Iend = first (R), last (R)
87+ I1 = _oneunit (Ibegin )
9188
92- R = CartesianIndices (size (img))
93- I1, Iend = first (R), last (R)
94- num = 1
89+ # Compute the number of entries per pixel (other than at the image edges)
90+ num_edges = 0
91+ for I in _colon (- I1, I1)
92+ I >= zero (I1) && continue
93+ num_edges += 1
94+ end
95+ num_edges *= num_vertices # now the number for the whole image
96+ edges = Vector {ImageEdge} (undef, num_edges)
97+
98+ num = 0
9599 for I in R
96- for J in CartesianIndices (_colon (max (I1, I- I1), min (Iend, I+ I1)))
100+ imgI = img[I]
101+ for J in _colon (max (Ibegin, I- I1), min (Iend, I+ I1))
97102 if I >= J
98103 continue
99104 end
100- edges[num] = ImageEdge ((I[2 ]- 1 )* rows+ I[1 ], (J[2 ]- 1 )* rows+ J[1 ], sqrt (sum (abs2,(img[I])- meantype (T)(img[J]))))
101- num += 1
105+ edges[num+= 1 ] = ImageEdge (L[I], L[J], sqrt (abs2 (imgI- meantype (T)(img[J]))))
102106 end
103107 end
108+ deleteat! (edges, num+ 1 : num_edges) # compensate for the ones we were missing at the image edges
104109
105110 index_map, num_segments = felzenszwalb (edges, num_vertices, k, min_size)
106111
@@ -109,12 +114,10 @@ function felzenszwalb(img::AbstractArray{T, 2}, k::Real, min_size::Int = 0) wher
109114 region_means = Dict {Int, meantype(T)} ()
110115 region_pix_count = Dict {Int, Int} ()
111116
112- for j in axes (img, 2 )
113- for i in axes (img, 1 )
114- result[i, j] = index_map[(j- 1 )* rows+ i]
115- region_pix_count[result[i,j]] = get (region_pix_count, result[i, j], 0 ) + 1
116- region_means[result[i,j]] = get (region_means, result[i,j], zero (meantype (T))) + (img[i, j] - get (region_means, result[i,j], zero (meantype (T))))/ region_pix_count[result[i,j]]
117- end
117+ for I in R
118+ result[I] = index_map[L[I]]
119+ region_pix_count[result[I]] = get (region_pix_count, result[I], 0 ) + 1
120+ region_means[result[I]] = get (region_means, result[I], zero (meantype (T))) + (img[I] - get (region_means, result[I], zero (meantype (T))))/ region_pix_count[result[I]]
118121 end
119122
120123 return SegmentedImage (result, labels, region_means, region_pix_count)
0 commit comments