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.tools.globalfeature; 031 032import org.kohsuke.args4j.CmdLineOptionsProvider; 033import org.kohsuke.args4j.Option; 034import org.kohsuke.args4j.ProxyOptionHandler; 035import org.openimaj.feature.FeatureVector; 036import org.openimaj.image.FImage; 037import org.openimaj.image.MBFImage; 038import org.openimaj.image.connectedcomponent.proc.AffineInvariantMoments; 039import org.openimaj.image.connectedcomponent.proc.BasicShapeDescriptor; 040import org.openimaj.image.connectedcomponent.proc.BasicShapeDescriptor.BasicShapeDescriptorType; 041import org.openimaj.image.connectedcomponent.proc.BoundaryDistanceDescriptor; 042import org.openimaj.image.connectedcomponent.proc.ColourDescriptor; 043import org.openimaj.image.connectedcomponent.proc.ColourDescriptor.ColourDescriptorType; 044import org.openimaj.image.connectedcomponent.proc.HuMoments; 045import org.openimaj.image.pixel.ConnectedComponent; 046 047/** 048 * Features describing the shape of the foreground object in an image. A mask is 049 * used to separate foreground/background pixels. 050 * 051 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 052 * 053 */ 054public enum ShapeFeatures implements CmdLineOptionsProvider { 055 /** 056 * Any of the {@link GlobalFeatureType}s applied only to the foreground 057 * region. 058 */ 059 GLOBAL { 060 @Override 061 public ShapeFeaturesOp getOptions() { 062 return new ShapeFeaturesOp() { 063 @Option( 064 name = "--global-feature-type", 065 aliases = "-g", 066 handler = ProxyOptionHandler.class, 067 usage = "Global feature type", 068 required = true) 069 private GlobalFeatureType feature; 070 private GlobalFeatureExtractor featureOp; 071 072 @Override 073 public FeatureVector execute(MBFImage image, FImage mask) { 074 return featureOp.extract(image); 075 } 076 }; 077 } 078 }, 079 /** 080 * Affine invariant moments 081 * 082 * @see AffineInvariantMoments 083 */ 084 AFFINE_INVARIANT_MOMENTS { 085 @Override 086 public ShapeFeaturesOp getOptions() { 087 return new ShapeFeaturesOp() { 088 @Override 089 public FeatureVector execute(MBFImage image, FImage mask) { 090 final AffineInvariantMoments f = new AffineInvariantMoments(); 091 f.process(c(mask)); 092 return f.getFeatureVector(); 093 } 094 }; 095 } 096 }, 097 /** 098 * Basic shape features 099 * 100 * @see BasicShapeDescriptor 101 */ 102 BASIC_SHAPE_FEATURES { 103 @Override 104 public ShapeFeaturesOp getOptions() { 105 return new ShapeFeaturesOp() { 106 @Option(name = "--type", aliases = "-t", usage = "Shape feature type", required = true) 107 BasicShapeDescriptorType type; 108 109 @Override 110 public FeatureVector execute(MBFImage image, FImage mask) { 111 final BasicShapeDescriptor f = new BasicShapeDescriptor(); 112 f.process(c(mask)); 113 return type.getFeatureVector(f); 114 } 115 }; 116 } 117 }, 118 /** 119 * Distance from boundary descriptor 120 * 121 * @see BoundaryDistanceDescriptor 122 */ 123 BOUNDARY_DISTANCE_FEATURE { 124 @Override 125 public ShapeFeaturesOp getOptions() { 126 return new ShapeFeaturesOp() { 127 @Option(name = "--no-scale-normalisation", usage = "Disable scale normalisation", required = false) 128 boolean noNormaliseScale = false; 129 130 @Option(name = "--no-rotation-normalisation", usage = "Disable rotation normalisation", required = false) 131 boolean noNormaliseRotation = false; 132 133 @Override 134 public FeatureVector execute(MBFImage image, FImage mask) { 135 final BoundaryDistanceDescriptor f = new BoundaryDistanceDescriptor(!noNormaliseScale, 136 !noNormaliseRotation); 137 f.process(c(mask)); 138 return f.getFeatureVector(); 139 } 140 }; 141 } 142 }, 143 /** 144 * Hu moments 145 * 146 * @see HuMoments 147 */ 148 HU_MOMENTS { 149 @Override 150 public ShapeFeaturesOp getOptions() { 151 return new ShapeFeaturesOp() { 152 @Override 153 public FeatureVector execute(MBFImage image, FImage mask) { 154 final HuMoments f = new HuMoments(); 155 f.process(c(mask)); 156 return f.getFeatureVector(); 157 } 158 }; 159 } 160 }, 161 /** 162 * Colour statistics 163 * 164 * @see ColourDescriptor 165 */ 166 COLOR_STATISTICS { 167 @Override 168 public ShapeFeaturesOp getOptions() { 169 return new ShapeFeaturesOp() { 170 @Option(name = "--type", aliases = "-t", usage = "Colour statistics type", required = true) 171 ColourDescriptorType type; 172 173 @Override 174 public FeatureVector execute(MBFImage image, FImage mask) { 175 final ColourDescriptor f = new ColourDescriptor(image); 176 f.process(c(mask)); 177 return type.getFeatureVector(f); 178 } 179 }; 180 } 181 }; 182 183 protected ConnectedComponent c(FImage mask) { 184 return new ConnectedComponent(mask, 0.5f); 185 } 186 187 @Override 188 public abstract ShapeFeaturesOp getOptions(); 189 190 /** 191 * An object able to perform the execution associated with a ShapeFeatures 192 * type; possibly contains extra options for the operation. 193 * 194 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 195 */ 196 public interface ShapeFeaturesOp { 197 /** 198 * Calculate a feature using the shape defined by the mask and possibly 199 * the pixel values from the image. 200 * 201 * @param image 202 * the image. 203 * @param mask 204 * the mask. 205 * @return the feature. 206 */ 207 public abstract FeatureVector execute(MBFImage image, FImage mask); 208 } 209}