View Javadoc

1   /**
2    * Copyright (c) 2011, The University of Southampton and the individual contributors.
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without modification,
6    * are permitted provided that the following conditions are met:
7    *
8    *   * 	Redistributions of source code must retain the above copyright notice,
9    * 	this list of conditions and the following disclaimer.
10   *
11   *   *	Redistributions in binary form must reproduce the above copyright notice,
12   * 	this list of conditions and the following disclaimer in the documentation
13   * 	and/or other materials provided with the distribution.
14   *
15   *   *	Neither the name of the University of Southampton nor the names of its
16   * 	contributors may be used to endorse or promote products derived from this
17   * 	software without specific prior written permission.
18   *
19   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
23   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26   * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29   */
30  package org.openimaj.image.analysis.watershed;
31  
32  import java.util.HashMap;
33  import java.util.Map;
34  
35  import org.apache.log4j.Logger;
36  import org.openimaj.image.analysis.watershed.event.ComponentStackMergeListener;
37  import org.openimaj.util.tree.TreeNode;
38  import org.openimaj.util.tree.TreeNodeImpl;
39  
40  /**
41   * A listener that listens to the watershed algorithm progress and creates a
42   * region tree as the processing takes place.
43   *
44   * @author David Dupplaw (dpd@ecs.soton.ac.uk)
45   * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
46   *
47   */
48  public class MergeTreeBuilder implements ComponentStackMergeListener
49  {
50  	Logger logger = Logger.getLogger(MergeTreeBuilder.class);
51  
52  	/** This is the tree we build */
53  	private TreeNode<Component> tree = null;
54  
55  	/**
56  	 * Because we're creating components to store the history, the components
57  	 * that are being processed by the algorithm are not the same as those in
58  	 * our tree, so we must provide a map so that we can join up the tree
59  	 * afterwards.
60  	 */
61  	private Map<Component, TreeNode<Component>> map = null;
62  
63  	/**
64  	 * Default constructor
65  	 */
66  	public MergeTreeBuilder()
67  	{
68  		map = new HashMap<Component, TreeNode<Component>>();
69  	}
70  
71  	/**
72  	 * {@inheritDoc}
73  	 *
74  	 * @see org.openimaj.image.analysis.watershed.event.ComponentStackMergeListener#componentsMerged(org.openimaj.image.analysis.watershed.Component,
75  	 *      org.openimaj.image.analysis.watershed.Component)
76  	 */
77  	@Override
78  	public void componentsMerged(Component c1, Component c2)
79  	{
80  		// logger.debug( "Map: "+map );
81  		logger.debug("Component c1: " + c1);
82  		logger.debug("Component c2: " + c2);
83  
84  		// Create a tree node for the component if it doesn't
85  		// exist already
86  		TreeNode<Component> c1xtn = map.get(c1);
87  		if (c1xtn == null)
88  		{
89  			logger.debug("c1 not found");
90  			c1xtn = new TreeNodeImpl<Component>();
91  			final Component c1x = c1.clone();
92  			c1xtn.setValue(c1x);
93  			map.put(c1, c1xtn);
94  		}
95  
96  		// Add all the pixels from c2 into our copy of c1
97  		c1xtn.getValue().merge(c2);
98  
99  		// Create a tree node for the second component
100 		// if it doesn't exist already
101 		TreeNode<Component> c2xtn = map.get(c2);
102 		if (c2xtn == null)
103 		{
104 			logger.debug("c2 not found");
105 			c2xtn = new TreeNodeImpl<Component>();
106 			final Component c2x = c2.clone();
107 			c2xtn.setValue(c2x);
108 			map.put(c2, c2xtn);
109 		}
110 
111 		// logger.debug("Linking " + c1xtn + " and " + c2xtn);
112 
113 		// Link the tree nodes
114 		c1xtn.addChild(c2xtn);
115 		this.tree = c1xtn;
116 	}
117 
118 	/**
119 	 * {@inheritDoc}
120 	 *
121 	 * @see org.openimaj.image.analysis.watershed.event.ComponentStackMergeListener#componentPromoted(org.openimaj.image.analysis.watershed.Component)
122 	 */
123 	@Override
124 	public void componentPromoted(Component c1)
125 	{
126 		final TreeNode<Component> c1xtn_old = map.get(c1);
127 
128 		final Component c1x = c1.clone();
129 
130 		final TreeNode<Component> c1xtn = new TreeNodeImpl<Component>();
131 		c1xtn.setValue(c1x);
132 
133 		map.put(c1, c1xtn);
134 
135 		if (c1xtn_old != null)
136 			c1xtn.addChild(c1xtn_old);
137 	}
138 
139 	/**
140 	 * Return the tree that has been built.
141 	 *
142 	 * @return the tree
143 	 */
144 	public TreeNode<Component> getTree()
145 	{
146 		return tree;
147 	}
148 }