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.contour;
31  
32  import java.io.PrintWriter;
33  import java.io.StringWriter;
34  import java.util.ArrayList;
35  import java.util.Iterator;
36  import java.util.List;
37  
38  import org.openimaj.image.pixel.Pixel;
39  import org.openimaj.math.geometry.shape.Polygon;
40  import org.openimaj.math.geometry.shape.Rectangle;
41  
42  /**
43   * A contour or hierarchical set of contours within an image.
44   * 
45   * @author Sina Samangooei (ss@ecs.soton.ac.uk)
46   */
47  public class Contour extends Polygon {
48  	/**
49  	 * The type of contour
50  	 */
51  	public ContourType type;
52  	/**
53  	 * sub contours
54  	 */
55  	public List<Contour> children = new ArrayList<Contour>();
56  	/**
57  	 * The parent contour, might be null
58  	 */
59  	public Contour parent;
60  
61  	/**
62  	 * where the contour starts
63  	 */
64  	public Pixel start;
65  	Rectangle rect = null;
66  
67  	/**
68  	 * Construct a contour with the given type and start at the origin
69  	 * 
70  	 * @param type
71  	 *            the type
72  	 */
73  	public Contour(ContourType type) {
74  		this.type = type;
75  		this.start = new Pixel(0, 0);
76  	}
77  
78  	/**
79  	 * Construct a contour with the given type and start pixel
80  	 * 
81  	 * @param type
82  	 *            the type
83  	 * @param x
84  	 *            the x-ordinate of the start pixel
85  	 * @param y
86  	 *            the y-ordinate of the start pixel
87  	 */
88  	public Contour(ContourType type, int x, int y) {
89  		this.type = type;
90  		this.start = new Pixel(x, y);
91  	}
92  
93  	/**
94  	 * Construct a contour with the given type and start pixel
95  	 * 
96  	 * @param type
97  	 *            the type
98  	 * @param p
99  	 *            the coordinate of the start pixel
100 	 */
101 	public Contour(ContourType type, Pixel p) {
102 		this.type = type;
103 		this.start = p;
104 	}
105 
106 	/**
107 	 * Construct a contour with the given starting coordinate and a
108 	 * <code>null</code> type.
109 	 * 
110 	 * @param x
111 	 *            the x-ordinate of the start pixel
112 	 * @param y
113 	 *            the y-ordinate of the start pixel
114 	 */
115 	public Contour(int x, int y) {
116 		this.type = null;
117 		this.start = new Pixel(x, y);
118 	}
119 
120 	protected void setParent(Contour bp) {
121 		this.parent = bp;
122 		bp.children.add(this);
123 	}
124 
125 	@Override
126 	public String toString() {
127 		final StringWriter contour = new StringWriter();
128 		final PrintWriter pw = new PrintWriter(contour);
129 		pw.println(String.format("[%s] start: %s %s", this.type, this.start, this.points));
130 		for (final Contour child : this.children) {
131 			pw.print(child);
132 		}
133 		pw.flush();
134 		return contour.toString();
135 	}
136 
137 	/**
138 	 * Complete this contour by computing it's bounding box
139 	 */
140 	public void finish() {
141 		this.rect = this.calculateRegularBoundingBox();
142 	}
143 
144 	private class ContourIterator implements Iterator<Contour> {
145 		final List<Contour> toProcess = new ArrayList<Contour>();
146 
147 		ContourIterator() {
148 			toProcess.add(Contour.this);
149 		}
150 
151 		@Override
152 		public boolean hasNext() {
153 			return !toProcess.isEmpty();
154 		}
155 
156 		@Override
157 		public Contour next() {
158 			final Contour next = toProcess.remove(toProcess.size() - 1);
159 			toProcess.addAll(next.children);
160 			return next;
161 		}
162 
163 		@Override
164 		public void remove() {
165 			throw new UnsupportedOperationException("Removal not supported");
166 		}
167 	}
168 
169 	/**
170 	 * Get an iterator over the complete set of contours (including the root
171 	 * itself)
172 	 * 
173 	 * @return the iterator
174 	 */
175 	public Iterator<Contour> contourIterator() {
176 		return new ContourIterator();
177 	}
178 
179 	/**
180 	 * Get an {@link Iterable} over all the contours belonging to this root
181 	 * (including the root itself)
182 	 * 
183 	 * @return the iterable
184 	 */
185 	public Iterable<Contour> contourIterable() {
186 		return new Iterable<Contour>() {
187 			@Override
188 			public Iterator<Contour> iterator() {
189 				return contourIterator();
190 			}
191 		};
192 	}
193 
194 	@Override
195 	public boolean isHole() {
196 		return type != null && type.equals(ContourType.HOLE);
197 	}
198 }