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 }