1
1
"""
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)
6
3
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.
23
6
The function returns the number of segments and index mapping from nodes of the RAG to segments.
24
7
25
8
Parameters:
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)
32
13
"""
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 )
34
15
35
16
num_edges = length (edges)
36
17
G = IntDisjointSets (num_vertices)
@@ -61,7 +42,7 @@ function felzenszwalb(edges::Array{ImageEdge}, num_vertices::Int, k::Real, min_s
61
42
end
62
43
end
63
44
64
- segments = OrderedSet ()
45
+ segments = OrderedSet {Int} ()
65
46
for i in 1 : num_vertices
66
47
push! (segments, find_root! (G, i))
67
48
end
@@ -72,35 +53,59 @@ function felzenszwalb(edges::Array{ImageEdge}, num_vertices::Int, k::Real, min_s
72
53
segments2index[s] = i
73
54
end
74
55
75
- index_map = Array {Int} (undef, num_vertices)
56
+ index_map = Vector {Int} (undef, num_vertices)
76
57
for i in 1 : num_vertices
77
58
index_map[i] = segments2index[find_root! (G, i)]
78
59
end
79
60
80
61
return index_map, num_sets
81
62
end
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 )
82
65
83
66
meantype (:: Type{T} ) where T = typeof (zero (accum_type (T))/ 2 )
84
67
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)
86
83
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 )
91
88
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
95
99
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))
97
102
if I >= J
98
103
continue
99
104
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]))))
102
106
end
103
107
end
108
+ deleteat! (edges, num+ 1 : num_edges) # compensate for the ones we were missing at the image edges
104
109
105
110
index_map, num_segments = felzenszwalb (edges, num_vertices, k, min_size)
106
111
@@ -109,12 +114,10 @@ function felzenszwalb(img::AbstractArray{T, 2}, k::Real, min_size::Int = 0) wher
109
114
region_means = Dict {Int, meantype(T)} ()
110
115
region_pix_count = Dict {Int, Int} ()
111
116
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]]
118
121
end
119
122
120
123
return SegmentedImage (result, labels, region_means, region_pix_count)
0 commit comments