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 }