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}