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.connectedcomponent.proc;
31
32 import org.openimaj.feature.DoubleFV;
33 import org.openimaj.feature.FeatureVectorProvider;
34 import org.openimaj.image.pixel.ConnectedComponent;
35 import org.openimaj.image.processor.connectedcomponent.ConnectedComponentProcessor;
36
37 /**
38 * Basic descriptors of the shape of a connected component.
39 *
40 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
41 *
42 */
43 public class BasicShapeDescriptor implements ConnectedComponentProcessor, FeatureVectorProvider<DoubleFV> {
44 /**
45 * An enum of all the different basic shape descriptors.
46 */
47 public enum BasicShapeDescriptorType {
48 /**
49 * The area of the component
50 *
51 * @see ConnectedComponent#calculateArea()
52 */
53 AREA {
54 @Override
55 public DoubleFV getFeatureVector(BasicShapeDescriptor desc) {
56 return new DoubleFV(new double[] { desc.area });
57 }
58 },
59 /**
60 * The centroid of the component
61 *
62 * @see ConnectedComponent#calculateCentroid()
63 */
64 CENTROID {
65 @Override
66 public DoubleFV getFeatureVector(BasicShapeDescriptor desc) {
67 return new DoubleFV(new double[] { desc.cx, desc.cy });
68 }
69 },
70 /**
71 * The primary orientation of the component
72 *
73 * @see ConnectedComponent#calculateDirection()
74 */
75 DIRECTION {
76 @Override
77 public DoubleFV getFeatureVector(BasicShapeDescriptor desc) {
78 return new DoubleFV(new double[] { desc.direction });
79 }
80 },
81 /**
82 * The elongatedness of the component. Elongatedness is defined as the
83 * ratio of the height to width of the oriented bounding box of the
84 * component.
85 *
86 * @see ConnectedComponent#calculateOrientatedBoundingBoxAspectRatio()
87 */
88 ELONGATEDNESS {
89 @Override
90 public DoubleFV getFeatureVector(BasicShapeDescriptor desc) {
91 return new DoubleFV(new double[] { desc.elongatedness });
92 }
93 },
94 /**
95 * The compactness of the component. Compactness is defined as the ratio
96 * of the squared edge length of the component to its area.
97 */
98 COMPACTNESS {
99 @Override
100 public DoubleFV getFeatureVector(BasicShapeDescriptor desc) {
101 return new DoubleFV(new double[] { desc.compactness });
102 }
103 },
104 /**
105 * The ratio of the area of the component to the area of its convex hull
106 *
107 * @see ConnectedComponent#calculatePercentageConvexHullFit()
108 */
109 CHFIT {
110 @Override
111 public DoubleFV getFeatureVector(BasicShapeDescriptor desc) {
112 return new DoubleFV(new double[] { desc.chfit });
113 }
114 },
115 /**
116 * The estimated number of corners of the component
117 *
118 * @see ConnectedComponent#estimateNumberOfVertices(int, int)
119 */
120 CORNERS {
121 @Override
122 public DoubleFV getFeatureVector(BasicShapeDescriptor desc) {
123 return new DoubleFV(new double[] { desc.cornerEst });
124 }
125 };
126
127 /**
128 * Create a @link{FeatureVector} representation of the specified
129 * description
130 *
131 * @param desc
132 * the descriptor
133 * @return the feature vector representation
134 */
135 public abstract DoubleFV getFeatureVector(BasicShapeDescriptor desc);
136 }
137
138 /**
139 * The area of the component
140 *
141 * @see ConnectedComponent#calculateArea()
142 */
143 public double area;
144
145 /**
146 * The x coordinate of the component centroid
147 *
148 * @see ConnectedComponent#calculateCentroid()
149 */
150 public double cx; // centroid x
151
152 /**
153 * The y coordinate of the component centroid
154 *
155 * @see ConnectedComponent#calculateCentroid()
156 */
157 public double cy; // y
158
159 /**
160 * The primary orientation of the component
161 *
162 * @see ConnectedComponent#calculateDirection()
163 */
164 public double direction;
165
166 /**
167 * The elongatedness of the component. Elongatedness is defined as the ratio
168 * of the height to width of the oriented bounding box of the component.
169 *
170 * @see ConnectedComponent#calculateOrientatedBoundingBoxAspectRatio()
171 */
172 public double elongatedness;
173
174 /**
175 * The compactness of the component. Compactness is defined as the ratio of
176 * the squared edge length of the component to its area.
177 */
178 public double compactness;
179
180 /**
181 * The ratio of the area of the component to the area of its convex hull
182 *
183 * @see ConnectedComponent#calculatePercentageConvexHullFit()
184 */
185 public double chfit;
186
187 /**
188 * The estimated number of corners of the component
189 *
190 * @see ConnectedComponent#estimateNumberOfVertices(int, int)
191 */
192 public double cornerEst;
193
194 @Override
195 public void process(ConnectedComponent cc) {
196 area = cc.calculateArea();
197
198 final double[] c = cc.calculateCentroid();
199 cx = c[0];
200 cy = c[1];
201
202 direction = cc.calculateDirection();
203
204 elongatedness = cc.calculateOrientatedBoundingBoxAspectRatio();
205
206 final float edge_length = cc.getOuterBoundary().size();
207 compactness = (edge_length * edge_length) / new ConnectedComponent(cc.toPolygon()).calculateArea();
208
209 if (area > 4)
210 chfit = new ConnectedComponent(cc.toPolygon()).calculatePercentageConvexHullFit(); // chfit
211 // won't
212 // work
213 // for
214 // really
215 // small
216 // regions
217 else
218 chfit = 1;
219
220 if (area > 100)
221 cornerEst = cc.estimateNumberOfVertices(3, 10);
222 else
223 cornerEst = area;
224 }
225
226 /**
227 * Get all the values of the descriptor as an array in the order area,
228 * centroid_x, centroid_y, direction, elongatedness, compactness
229 * convex_hull_fit, corner_count
230 *
231 * @return an array of descriptor values
232 */
233 public double[] getFeatureVectorArray() {
234 return new double[] { area, cx, cy, direction, elongatedness, compactness, chfit, cornerEst };
235 }
236
237 @Override
238 public DoubleFV getFeatureVector() {
239 return new DoubleFV(getFeatureVectorArray());
240 }
241 }