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.HashSet;
33  import java.util.Set;
34  
35  import org.openimaj.image.analysis.watershed.feature.ComponentFeature;
36  import org.openimaj.image.analysis.watershed.feature.PixelsFeature;
37  import org.openimaj.image.pixel.IntValuePixel;
38  import org.openimaj.image.pixel.Pixel;
39  
40  /**
41   * Represents a region or set of pixels (the name is based on the Microsoft
42   * paper)
43   *
44   * @author David Dupplaw (dpd@ecs.soton.ac.uk)
45   * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
46   *
47   */
48  public class Component implements Cloneable
49  {
50  	/** Whether this component represents an MSER */
51  	public boolean isMSER = false;
52  
53  	/** List of features representing this component */
54  	public ComponentFeature[] features;
55  
56  	/**
57  	 * The pivot pixel
58  	 */
59  	public IntValuePixel pivot;
60  	private int size = 0;
61  
62  	/**
63  	 * Default constructor.
64  	 *
65  	 * @param p
66  	 *            The grey level of the component
67  	 * @param featureClasses
68  	 *            the list of features to create for the component
69  	 */
70  	@SafeVarargs
71  	public Component(IntValuePixel p, Class<? extends ComponentFeature>... featureClasses)
72  	{
73  		this.pivot = p;
74  
75  		features = new ComponentFeature[featureClasses.length];
76  		for (int i = 0; i < featureClasses.length; i++) {
77  			try {
78  				features[i] = featureClasses[i].newInstance();
79  			} catch (final Exception e) {
80  				throw new AssertionError(e);
81  			}
82  		}
83  	}
84  
85  	/**
86  	 * {@inheritDoc}
87  	 *
88  	 * @see java.util.AbstractCollection#toString()
89  	 */
90  	@Override
91  	public String toString()
92  	{
93  		return "Comp@" + super.hashCode() + "(px:" + size + ",gl:" + pivot.value + ")";
94  	};
95  
96  	/**
97  	 * Add a pixel to the component
98  	 *
99  	 * @param p
100 	 *            the pixel to add
101 	 */
102 	public void accumulate(IntValuePixel p) {
103 		size++;
104 
105 		for (final ComponentFeature f : features) {
106 			f.addSample(p);
107 		}
108 	}
109 
110 	/**
111 	 * Merge another component with this one
112 	 *
113 	 * @param p
114 	 *            the component to merge into this
115 	 */
116 	public void merge(Component p) {
117 		size += p.size();
118 
119 		for (int i = 0; i < features.length; i++) {
120 			features[i].merge(p.features[i]);
121 		}
122 	}
123 
124 	/**
125 	 * The size of the component (i.e. the number of pixels)
126 	 *
127 	 * @return the size of the component
128 	 */
129 	public int size() {
130 		return size;
131 	}
132 
133 	/**
134 	 * Get the pixels in the component. If the component contains a
135 	 * {@link PixelsFeature} then the pixels will be returned from that;
136 	 * otherwise a set containing just the pivot pixel will be returned.
137 	 *
138 	 * @return the pixels in the component if possible, or just the pivot pixel
139 	 */
140 	public Set<Pixel> getPixels() {
141 		for (final ComponentFeature f : features) {
142 			if (f instanceof PixelsFeature)
143 				return ((PixelsFeature) f).pixels;
144 		}
145 
146 		final Set<Pixel> pix = new HashSet<Pixel>(1);
147 		pix.add(pivot);
148 		return pix;
149 	}
150 
151 	@Override
152 	public Component clone() {
153 		Component result;
154 		try {
155 			result = (Component) super.clone();
156 			result.features = new ComponentFeature[features.length];
157 			for (int i = 0; i < features.length; i++)
158 				result.features[i] = features[i].clone();
159 
160 			// result.pixels = pixels.clone();
161 
162 			return result;
163 		} catch (final CloneNotSupportedException e) {
164 			throw new AssertionError(e);
165 		}
166 	}
167 
168 	/**
169 	 * Get the feature at the given index
170 	 *
171 	 * @param index
172 	 *            the index
173 	 * @return the feature at the given index or null if it doesn't exist
174 	 */
175 	public ComponentFeature getFeature(int index) {
176 		if (index >= features.length)
177 			return null;
178 
179 		return features[index];
180 	}
181 
182 	/**
183 	 * Get the feature matching the given class if it exists. If more than one
184 	 * feature of the given class exists, then the first will be returned.
185 	 *
186 	 * @param <T>
187 	 *            the class of the feature
188 	 * @param featureClass
189 	 *            the class of the feature
190 	 * @return the feature with the given class; or null if no feature is found
191 	 */
192 	@SuppressWarnings("unchecked")
193 	public <T extends ComponentFeature> T getFeature(Class<T> featureClass) {
194 		for (final ComponentFeature f : features)
195 			if (f.getClass().isAssignableFrom(featureClass))
196 				return (T) f;
197 
198 		return null;
199 	}
200 }