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 }