graph_based_image_segmentation/graph/image_graph.rs
1use crate::graph::{ImageEdge, ImageNode, ImageNodeColor};
2use std::cell::Cell;
3
4/// Represents an image graph, consisting of one node per pixel which are 4-connected.
5#[derive(Debug, Clone, Default)]
6pub struct ImageGraph {
7 /// Number of components.
8 k: Cell<usize>,
9 /// All nodes in this graph.
10 nodes: Nodes,
11 /// All edges in this graph.
12 edges: Edges,
13}
14
15#[derive(Debug, Clone, Default)]
16pub struct Nodes {
17 nodes: Vec<Cell<ImageNode>>,
18 node_colors: Vec<Cell<ImageNodeColor>>,
19}
20
21#[derive(Debug, Clone, Default)]
22pub struct Edges {
23 edges: Vec<Cell<ImageEdge>>,
24}
25
26impl ImageGraph {
27 /// Constructs an image graph with the given exact number of nodes.
28 ///
29 /// # Arguments
30 ///
31 /// * `n` - The number of nodes to allocate.
32 pub fn new_with_nodes(n: usize) -> Self {
33 Self {
34 k: Cell::new(n),
35 nodes: Nodes::allocated(n),
36 ..Self::default()
37 }
38 }
39
40 /// Resets the image graph with the given exact number of nodes.
41 ///
42 /// # Arguments
43 ///
44 /// * `n` - The number of nodes to allocate.
45 pub fn reset(&mut self, n: usize) {
46 self.k.replace(n);
47 self.nodes = Nodes::allocated(n);
48 self.edges.clear();
49 }
50
51 /// Get the number of nodes.
52 ///
53 /// # Return
54 ///
55 /// The number of nodes.
56 pub fn num_nodes(&self) -> usize {
57 self.nodes.len()
58 }
59
60 /// Get the number of edges.
61 ///
62 /// # Return
63 ///
64 /// The number of edges.
65 pub fn num_edges(&self) -> usize {
66 self.edges.len()
67 }
68
69 /// Get the number of connected components.
70 ///
71 /// # Return
72 ///
73 /// The number connected components.
74 pub fn num_components(&self) -> usize {
75 self.k.get()
76 }
77
78 /// Merge two pixels (that is merge two nodes).
79 ///
80 /// # Arguments
81 ///
82 /// * `s_n` - The first node.
83 /// * `s_m` - The second node.
84 /// * `e` - The corresponding edge.
85 ///
86 /// # Remarks
87 ///
88 /// Depending on the used "Distance", some lines may be commented out
89 /// to speed up the algorithm.
90 pub fn merge(&self, s_n: &Cell<ImageNode>, s_m: &Cell<ImageNode>, e: &ImageEdge) {
91 let mut lhs = s_n.get();
92 let mut rhs = s_m.get();
93 debug_assert_ne!(lhs.id, rhs.id);
94
95 rhs.label = lhs.id;
96
97 // Update count.
98 lhs.n += rhs.n;
99
100 // Update maximum weight.
101 lhs.max_w = lhs.max_w.max(rhs.max_w).max(e.w);
102
103 // Update the nodes.
104 s_n.set(lhs);
105 s_m.set(rhs);
106
107 // Update component count.
108 let new_k = self.k.get() - 1;
109 self.k.replace(new_k);
110 }
111
112 /// Get a reference to the n-th node.
113 ///
114 /// # Arguments
115 ///
116 /// * `n` - The index of the node.
117 ///
118 /// # Return
119 ///
120 /// The node at index `n`.
121 pub fn node_at(&self, n: usize) -> &Cell<ImageNode> {
122 self.nodes.at(n)
123 }
124
125 /// Get a reference to the n-th node.
126 ///
127 /// # Arguments
128 ///
129 /// * `n` - The index of the node.
130 ///
131 /// # Return
132 ///
133 /// The node at index `n`.
134 #[inline(always)]
135 pub fn node_color_at(&self, n: usize) -> &Cell<ImageNodeColor> {
136 self.nodes.color_at(n)
137 }
138
139 /// Get the ID of the n-th node.
140 ///
141 /// # Arguments
142 ///
143 /// * `n` - The index of the node.
144 ///
145 /// # Return
146 ///
147 /// The ID of the node at index `n`.
148 #[inline(always)]
149 pub fn node_id_at(&self, n: usize) -> usize {
150 let id = self.nodes.at(n).get().id;
151 debug_assert_eq!(id, n); // TODO: Remove this method call.
152 id
153 }
154
155 /// Gets a reference to the n-th edge.
156 ///
157 /// # Arguments
158 ///
159 /// * `n` - The index of the edge.
160 ///
161 /// # Return
162 ///
163 /// The edge at index `n`.
164 pub fn edge_at(&self, n: usize) -> &Cell<ImageEdge> {
165 self.edges.at(n)
166 }
167
168 /// When two nodes get merged, the first node is assigned the id of the second
169 /// node as label. By traversing this labeling, the current component of each
170 /// node (that is, pixel) can easily be identified and the label can be updated
171 /// for efficiency.
172 ///
173 /// # Arguments
174 ///
175 /// * `index` - The index of the node to find the component for.
176 ///
177 /// # Returns
178 ///
179 /// The node representing the found component.
180 pub fn find_node_component_at(&self, index: usize) -> usize {
181 self.nodes.find_component_at(index)
182 }
183
184 /// Add new edges.
185 ///
186 /// # Arguments
187 ///
188 /// * `edges` - The edges to add.
189 pub fn add_edges<I>(&mut self, edges: I)
190 where
191 I: Iterator<Item = ImageEdge>,
192 {
193 self.edges.add_many(edges)
194 }
195
196 /// Removes all edges.
197 pub fn clear_edges(&mut self) {
198 self.edges.clear();
199 }
200
201 /// Sorts the edges by weight.
202 pub fn sort_edges(&mut self) {
203 self.edges.sort_by_weight()
204 }
205}
206
207impl Nodes {
208 pub fn allocated(n: usize) -> Self {
209 let mut nodes = vec![Default::default(); n];
210 let mut colors = vec![Default::default(); n];
211 /*for _ in 0..n {
212 nodes.push(Cell::new(ImageNode::default()));
213 colors.push(Cell::new(ImageNodeColor::default()));
214 }*/
215 Self {
216 nodes,
217 node_colors: colors,
218 }
219 }
220
221 /// Set the node of the given index.
222 ///
223 /// # Arguments
224 ///
225 /// * `n` - The index of the node.
226 /// * `node` - The node to set.
227 #[allow(dead_code)]
228 pub fn set(&mut self, n: usize, node: ImageNode) {
229 assert!(n < self.nodes.len());
230 self.nodes[n].replace(node);
231 }
232
233 /// Add a new node.
234 ///
235 /// # Arguments
236 ///
237 /// * `node` - The node to add.
238 #[allow(dead_code)]
239 pub fn add(&mut self, node: ImageNode) {
240 self.nodes.push(Cell::new(node))
241 }
242
243 /// Get a reference to the n-th node.
244 ///
245 /// # Arguments
246 ///
247 /// * `n` - The index of the node.
248 ///
249 /// # Return
250 ///
251 /// The node at index `n`.
252 pub fn at(&self, n: usize) -> &Cell<ImageNode> {
253 assert!(n < self.nodes.len());
254 &self.nodes[n]
255 }
256
257 /// Get a reference to the n-th node color.
258 ///
259 /// # Arguments
260 ///
261 /// * `n` - The index of the node color.
262 ///
263 /// # Return
264 ///
265 /// The node at index `n`.
266 #[inline(always)]
267 pub fn color_at(&self, n: usize) -> &Cell<ImageNodeColor> {
268 assert!(n < self.node_colors.len());
269 &self.node_colors[n]
270 }
271
272 /// When two nodes get merged, the first node is assigned the id of the second
273 /// node as label. By traversing this labeling, the current component of each
274 /// node (that is, pixel) can easily be identified and the label can be updated
275 /// for efficiency.
276 ///
277 /// # Arguments
278 ///
279 /// * `index` - The index of the node to find the component for.
280 ///
281 /// # Returns
282 ///
283 /// The node representing the found component.
284 pub fn find_component_at(&self, index: usize) -> usize {
285 let mut n = self.nodes[index].get();
286 debug_assert_eq!(n.id, index);
287 if n.label == n.id {
288 return index;
289 }
290
291 // Get component of node n.
292 let mut l = n.label;
293 let mut id = n.id;
294
295 while l != id {
296 let token = self.nodes[l].get();
297 l = token.label;
298 id = token.id;
299 }
300
301 // If the found component is identical to the originally provided index, we must not borrow again.
302 debug_assert_ne!(l, index);
303
304 let s = self.nodes[l].get();
305 debug_assert_eq!(s.label, s.id);
306
307 // Save latest component.
308 n.label = s.id;
309 self.nodes[index].set(n);
310 l
311 }
312
313 /// Returns the number of nodes.
314 pub fn len(&self) -> usize {
315 self.nodes.len()
316 }
317}
318
319impl Edges {
320 /// Add a new edge.
321 ///
322 /// # Arguments
323 ///
324 /// * `edge` - The edge to add.
325 pub fn add(&mut self, edge: ImageEdge) {
326 self.edges.push(Cell::new(edge))
327 }
328
329 /// Add new edges.
330 ///
331 /// # Arguments
332 ///
333 /// * `edges` - The edges to add.
334 pub fn add_many<I>(&mut self, edges: I)
335 where
336 I: Iterator<Item = ImageEdge>,
337 {
338 for edge in edges.into_iter() {
339 self.add(edge);
340 }
341 }
342
343 /// Gets a reference to the n-th edge.
344 ///
345 /// # Arguments
346 ///
347 /// * `n` - The index of the edge.
348 ///
349 /// # Return
350 ///
351 /// The edge at index `n`.
352 pub fn at(&self, n: usize) -> &Cell<ImageEdge> {
353 assert!(n < self.edges.len());
354 &self.edges[n]
355 }
356
357 /// Sorts the edges by weight.
358 pub fn sort_by_weight(&mut self) {
359 self.edges.sort_by(|a, b| {
360 let a = a.get();
361 let b = b.get();
362
363 // Main sorting is by edge weight ascending.
364 // In order to improve cache coherency during processing, we then sort by index.
365 let ord_w = a.w.partial_cmp(&b.w).unwrap();
366 let ord_n = a.n.partial_cmp(&b.n).unwrap();
367 let ord_m = a.m.partial_cmp(&b.m).unwrap();
368 ord_w.then(ord_n).then(ord_m)
369 });
370 }
371
372 /// Removes all edges.
373 pub fn clear(&mut self) {
374 self.edges.clear()
375 }
376
377 /// Returns the number of edges.
378 pub fn len(&self) -> usize {
379 self.edges.len()
380 }
381}