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.objectdetection.haar; 031 032import org.openimaj.citation.annotation.Reference; 033import org.openimaj.citation.annotation.ReferenceType; 034import org.openimaj.image.analysis.algorithm.SummedSqTiltAreaTable; 035 036/** 037 * A classification stage. The stage is made up of an ensemble of classifiers 038 * (which may themselves be trees or stumps). In order to evaluate the stage, 039 * the ensemble of classifiers is tested in order and the responses are summed. 040 * If the summed response exceeds a threshold (corresponding to a certain 041 * error-rate set during training) then the stage will pass and the 042 * {@link #successStage()} should be evaluated. If the stage fails, then the 043 * {@link #failureStage()} will be evaluated. The actual coordination of calling 044 * the {@link #successStage()} or {@link #failureStage()} is performed by the 045 * {@link StageTreeClassifier}. 046 * 047 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 048 */ 049@Reference( 050 type = ReferenceType.Inproceedings, 051 author = { "Viola, P.", "Jones, M." }, 052 title = "Rapid object detection using a boosted cascade of simple features", 053 year = "2001", 054 booktitle = "Computer Vision and Pattern Recognition, 2001. CVPR 2001. Proceedings of the 2001 IEEE Computer Society Conference on", 055 pages = { " I", "511 ", " I", "518 vol.1" }, 056 number = "", 057 volume = "1", 058 customData = { 059 "keywords", " AdaBoost; background regions; boosted simple feature cascade; classifiers; face detection; image processing; image representation; integral image; machine learning; object specific focus-of-attention mechanism; rapid object detection; real-time applications; statistical guarantees; visual object detection; feature extraction; image classification; image representation; learning (artificial intelligence); object detection;", 060 "doi", "10.1109/CVPR.2001.990517", 061 "ISSN", "1063-6919 " 062 }) 063public class Stage { 064 float threshold; 065 Classifier[] ensemble; 066 067 /** 068 * The next stage to evaluate should this one pass; if this stage passes and 069 * this is <code>null</code> then the whole {@link StageTreeClassifier} 070 * passes. 071 */ 072 Stage successStage; 073 074 /** 075 * The next stage to evaluate should this one fail; if this stage fails and 076 * this is <code>null</code> then the whole {@link StageTreeClassifier} 077 * fails. 078 */ 079 Stage failureStage; 080 081 /** 082 * Do any of the {@link ValueClassifier}s have negative values? If not, we 083 * can perform an optimisation in 084 * {@link #pass(StageTreeClassifier, SummedSqTiltAreaTable, float, int, int)} 085 * to shortcut checking the entire ensemble. 086 */ 087 private boolean hasNegativeValueFeatures; 088 089 /** 090 * Construct a new stage. 091 * 092 * @param threshold 093 * the threshold for the stage to pass 094 * @param trees 095 * the classifier trees in the stage 096 * @param successStage 097 * the next stage after this one, or null if this is the last 098 * @param failureStage 099 * the failure stage (for trees rather than cascades) 100 */ 101 public Stage(float threshold, Classifier[] trees, Stage successStage, Stage failureStage) { 102 this.threshold = threshold; 103 this.ensemble = trees; 104 this.successStage = successStage; 105 this.failureStage = failureStage; 106 107 this.hasNegativeValueFeatures = checkForNegativeValueFeatures(); 108 } 109 110 private boolean checkForNegativeValueFeatures() { 111 for (int i = 0; i < ensemble.length; i++) { 112 if (checkForNegativeValueFeatures(ensemble[i])) 113 return true; 114 } 115 return false; 116 } 117 118 private boolean checkForNegativeValueFeatures(Classifier classifier) { 119 if (classifier instanceof ValueClassifier) { 120 if (((ValueClassifier) classifier).value < 0) 121 return true; 122 } else { 123 if (checkForNegativeValueFeatures(((HaarFeatureClassifier) classifier).left)) 124 return true; 125 if (checkForNegativeValueFeatures(((HaarFeatureClassifier) classifier).right)) 126 return true; 127 } 128 129 return false; 130 } 131 132 /** 133 * Test whether a stage passes. For the stage to pass, the sum of the 134 * responses from the internal classification trees or stumps must exceed 135 * the stage's threshold. 136 * 137 * @param sat 138 * the summed area tables (integral images) 139 * @param wvNorm 140 * the normalisation based on the current window variance 141 * @param x 142 * the x-ordinate of the top-left of the window being tested 143 * @param y 144 * the y-ordinate of the top-left of the window being tested 145 * @return true if the stage passes; false otherwise 146 */ 147 public boolean pass(final SummedSqTiltAreaTable sat, final float wvNorm, 148 final int x, final int y) 149 { 150 float total = 0; 151 152 // Optimisation: if there are no negative valued features in the 153 // ensemble, then the sum can only increase & it is cheaper to perform 154 // the threshold check on each iteration 155 if (hasNegativeValueFeatures) { 156 for (int i = 0; i < ensemble.length; i++) { 157 total += ensemble[i].classify(sat, wvNorm, x, y); 158 } 159 160 return total >= threshold; 161 } else { 162 for (int i = 0; i < ensemble.length; i++) { 163 total += ensemble[i].classify(sat, wvNorm, x, y); 164 if (total >= threshold) 165 return true; 166 } 167 168 return false; 169 } 170 } 171 172 /** 173 * Update the caches for a given scale (given by 174 * {@link StageTreeClassifier#cachedScale}). The {@link Stage} itself 175 * doesn't cache anything, but it's classifiers might... 176 * 177 * @param cascade 178 * the tree of stages 179 */ 180 void updateCaches(StageTreeClassifier cascade) { 181 for (int i = 0; i < ensemble.length; i++) { 182 ensemble[i].updateCaches(cascade); 183 } 184 } 185 186 /** 187 * Get the next stage to evaluate should this one pass; if this stage passes 188 * and this is <code>null</code> then the whole {@link StageTreeClassifier} 189 * passes. 190 * 191 * @return the next stage should 192 * {@link #pass(SummedSqTiltAreaTable, float, int, int)} return 193 * true. 194 */ 195 public Stage successStage() { 196 return successStage; 197 } 198 199 /** 200 * Get the next stage to evaluate should this one fail; if this stage fails 201 * and this is <code>null</code> then the whole {@link StageTreeClassifier} 202 * fails. 203 * 204 * @return the next stage should 205 * {@link #pass(SummedSqTiltAreaTable, float, int, int)} return 206 * false. 207 */ 208 public Stage failureStage() { 209 return failureStage; 210 } 211}