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.feature.global; 31 32 import org.openimaj.feature.DoubleFV; 33 import org.openimaj.feature.FeatureVectorProvider; 34 import org.openimaj.image.FImage; 35 import org.openimaj.image.MBFImage; 36 import org.openimaj.image.analyser.ImageAnalyser; 37 import org.openimaj.image.colour.Transforms; 38 import org.openimaj.image.mask.AbstractMaskedObject; 39 40 /** 41 * A two-valued summary representing mean hue (in radians) and variance of hue 42 * respectively. Additionally, can produce a classification for black & white 43 * versus colour versus sepia images based on hand-coded (and not well tested) 44 * parameters. 45 * 46 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 47 * 48 */ 49 public class HueStats extends AbstractMaskedObject<FImage> 50 implements 51 ImageAnalyser<MBFImage>, 52 FeatureVectorProvider<DoubleFV> 53 { 54 double mean_x = 0; 55 double m2_x = 0; 56 double mean_y = 0; 57 double m2_y = 0; 58 int n = 0; 59 60 /** 61 * Construct with no mask set 62 */ 63 public HueStats() { 64 super(); 65 } 66 67 /** 68 * Construct with a mask. 69 * 70 * @param mask 71 * the mask. 72 */ 73 public HueStats(FImage mask) { 74 super(mask); 75 } 76 77 @Override 78 public void analyseImage(MBFImage image) { 79 // reset vars in case we're reused 80 mean_x = 0; 81 m2_x = 0; 82 mean_y = 0; 83 m2_y = 0; 84 n = 0; 85 86 final FImage hue = Transforms.calculateHue(image); 87 88 for (int j = 0; j < hue.height; j++) { 89 for (int i = 0; i < hue.width; i++) { 90 if (mask != null && mask.pixels[j][i] == 0) 91 continue; 92 93 final double angle = hue.pixels[j][i]; 94 95 final double x = Math.cos(2 * Math.PI * angle); 96 final double y = Math.sin(2 * Math.PI * angle); 97 98 n++; 99 final double delta_x = x - mean_x; 100 final double delta_y = y - mean_y; 101 mean_x += delta_x / n; 102 mean_y += delta_y / n; 103 104 m2_x += delta_x * (x - mean_x); 105 m2_y += delta_y * (y - mean_y); 106 } 107 } 108 } 109 110 /** 111 * Get the mean hue value. 112 * 113 * @return the mean hue value over all pixels. 114 */ 115 public double getMeanHue() { 116 return Math.atan2(mean_y, mean_x); 117 } 118 119 /** 120 * Get the variance in hue value. 121 * 122 * @return the variance of hue over all pixels. 123 */ 124 public double getHueVariance() { 125 final double var_x = m2_x / n; 126 final double var_y = m2_y / n; 127 128 return var_y * var_x; 129 } 130 131 /** 132 * Tonal attributes for images based on the mean hue and variance. 133 * 134 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 135 * 136 */ 137 public enum ToneAttr { 138 /** 139 * Sepia toned image. 140 */ 141 SEPIA, 142 /** 143 * Black and white image. 144 */ 145 BLACK_AND_WHITE, 146 /** 147 * Colour image 148 */ 149 COLOR; 150 151 /** 152 * Estimate the tone from the given mean and variance of the hue. This 153 * is hand-crafted and not well tested. A variance bigger than 5e-4 is 154 * taken to imply a colour image. If the variance is less than 5e-4 and 155 * the mean hue is between -0.1 and 0.1 radians, then it is assumed the 156 * image is back and white. If the variance is less than 5e-4 and the 157 * mean hue is between -0.6 and 0.8 radians, then it is assumed the 158 * image is sepia toned. 159 * 160 * @param mean 161 * the mean hue 162 * @param var 163 * the variance in hue 164 * @return the estimated tone 165 */ 166 public static ToneAttr getAttr(double mean, double var) { 167 if (var < 5e-4) { 168 if (mean > -0.1 && mean < 0.1) 169 return BLACK_AND_WHITE; 170 if (mean > 0.6 && mean < 0.8) 171 return SEPIA; 172 } 173 return COLOR; 174 } 175 } 176 177 /** 178 * Estimate the tone of the image. 179 * 180 * @see ToneAttr#getAttr(double, double) 181 * 182 * @return the estimated tone 183 */ 184 public ToneAttr getTone() { 185 return ToneAttr.getAttr(getMeanHue(), getHueVariance()); 186 } 187 188 @Override 189 public DoubleFV getFeatureVector() { 190 return new DoubleFV(new double[] { getMeanHue(), getHueVariance() }); 191 } 192 }