001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.openimaj.image.connectedcomponent.proc; 031 032import org.openimaj.feature.DoubleFV; 033import org.openimaj.feature.FeatureVectorProvider; 034import org.openimaj.image.pixel.ConnectedComponent; 035import org.openimaj.image.processor.connectedcomponent.ConnectedComponentProcessor; 036 037/** 038 * Basic descriptors of the shape of a connected component. 039 * 040 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 041 * 042 */ 043public class BasicShapeDescriptor implements ConnectedComponentProcessor, FeatureVectorProvider<DoubleFV> { 044 /** 045 * An enum of all the different basic shape descriptors. 046 */ 047 public enum BasicShapeDescriptorType { 048 /** 049 * The area of the component 050 * 051 * @see ConnectedComponent#calculateArea() 052 */ 053 AREA { 054 @Override 055 public DoubleFV getFeatureVector(BasicShapeDescriptor desc) { 056 return new DoubleFV(new double[] { desc.area }); 057 } 058 }, 059 /** 060 * The centroid of the component 061 * 062 * @see ConnectedComponent#calculateCentroid() 063 */ 064 CENTROID { 065 @Override 066 public DoubleFV getFeatureVector(BasicShapeDescriptor desc) { 067 return new DoubleFV(new double[] { desc.cx, desc.cy }); 068 } 069 }, 070 /** 071 * The primary orientation of the component 072 * 073 * @see ConnectedComponent#calculateDirection() 074 */ 075 DIRECTION { 076 @Override 077 public DoubleFV getFeatureVector(BasicShapeDescriptor desc) { 078 return new DoubleFV(new double[] { desc.direction }); 079 } 080 }, 081 /** 082 * The elongatedness of the component. Elongatedness is defined as the 083 * ratio of the height to width of the oriented bounding box of the 084 * component. 085 * 086 * @see ConnectedComponent#calculateOrientatedBoundingBoxAspectRatio() 087 */ 088 ELONGATEDNESS { 089 @Override 090 public DoubleFV getFeatureVector(BasicShapeDescriptor desc) { 091 return new DoubleFV(new double[] { desc.elongatedness }); 092 } 093 }, 094 /** 095 * The compactness of the component. Compactness is defined as the ratio 096 * of the squared edge length of the component to its area. 097 */ 098 COMPACTNESS { 099 @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}