View Javadoc

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.apache.commons.math.stat.descriptive.SummaryStatistics;
33  import org.openimaj.citation.annotation.Reference;
34  import org.openimaj.citation.annotation.ReferenceType;
35  import org.openimaj.feature.DoubleFV;
36  import org.openimaj.feature.EnumFV;
37  import org.openimaj.feature.FeatureVectorProvider;
38  import org.openimaj.image.analyser.PixelAnalyser;
39  
40  /**
41   * Implementation of Hasler and Susstruck's Colorfulness metric
42   * http://infoscience.epfl.ch/record/33994/files/HaslerS03.pdf?version=1
43   * 
44   * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
45   */
46  @Reference(
47  		type = ReferenceType.Inproceedings,
48  		author = { "Hasler, David", "S\\\"{u}sstrunk, Sabine" },
49  		title = "Measuring {C}olourfulness in {N}atural {I}mages",
50  		year = "2003",
51  		booktitle = "Proc. {IS}&{T}/{SPIE} {E}lectronic {I}maging 2003: {H}uman {V}ision and {E}lectronic {I}maging {VIII}",
52  		pages = { "87", "", "95" },
53  		volume = "5007",
54  		url = "http://infoscience.epfl.ch/record/33994/files/HaslerS03.pdf?version=1",
55  		customData = {
56  				"details", "http://infoscience.epfl.ch/record/33994",
57  				"documenturl", "http://infoscience.epfl.ch/record/33994/files/HaslerS03.pdf",
58  				"doi", "10.1117/12.477378",
59  				"keywords", "IVRG; colorfulness; image quality; image attributes; colourfulness",
60  				"location", "San Jose, CA",
61  				"oai-id", "oai:infoscience.epfl.ch:33994",
62  				"oai-set", "conf; fulltext; fulltext-public",
63  				"review", "NON-REVIEWED",
64  				"status", "PUBLISHED",
65  				"unit", "LCAV IVRG"
66  		})
67  public class Colorfulness implements PixelAnalyser<Float[]>, FeatureVectorProvider<DoubleFV> {
68  	SummaryStatistics rgStats = new SummaryStatistics();
69  	SummaryStatistics ybStats = new SummaryStatistics();
70  
71  	@Override
72  	public void analysePixel(Float[] pixel) {
73  		final float r = pixel[0];
74  		final float g = pixel[1];
75  		final float b = pixel[2];
76  
77  		final float rg = r - g;
78  		final float yb = 0.5f * (r + g) - b;
79  
80  		rgStats.addValue(rg);
81  		ybStats.addValue(yb);
82  	}
83  
84  	/**
85  	 * Classes of colourfulness
86  	 * 
87  	 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
88  	 */
89  	@Reference(
90  			type = ReferenceType.Inproceedings,
91  			author = { "Hasler, David", "S\\\"{u}sstrunk, Sabine" },
92  			title = "Measuring {C}olourfulness in {N}atural {I}mages",
93  			year = "2003",
94  			booktitle = "Proc. {IS}&{T}/{SPIE} {E}lectronic {I}maging 2003: {H}uman {V}ision and {E}lectronic {I}maging {VIII}",
95  			pages = { "87", "", "95" },
96  			volume = "5007",
97  			url = "http://infoscience.epfl.ch/record/33994/files/HaslerS03.pdf?version=1",
98  			customData = {
99  					"details", "http://infoscience.epfl.ch/record/33994",
100 					"documenturl", "http://infoscience.epfl.ch/record/33994/files/HaslerS03.pdf",
101 					"doi", "10.1117/12.477378",
102 					"keywords", "IVRG; colorfulness; image quality; image attributes; colourfulness",
103 					"location", "San Jose, CA",
104 					"oai-id", "oai:infoscience.epfl.ch:33994",
105 					"oai-set", "conf; fulltext; fulltext-public",
106 					"review", "NON-REVIEWED",
107 					"status", "PUBLISHED",
108 					"unit", "LCAV IVRG"
109 			})
110 	public enum ColorfulnessAttr implements FeatureVectorProvider<EnumFV<ColorfulnessAttr>> {
111 		/**
112 		 * Not colourful
113 		 */
114 		NOT(0.0),
115 		/**
116 		 * Slightly colourful
117 		 */
118 		SLIGHTLY(15.0 / 255.0),
119 		/**
120 		 * Moderately colourful
121 		 */
122 		MODERATELY(33.0 / 255.0),
123 		/**
124 		 * Averagely colourful
125 		 */
126 		AVERAGELY(45.0 / 255.0),
127 		/**
128 		 * Quite colourful
129 		 */
130 		QUITE(59.0 / 255.0),
131 		/**
132 		 * Highly colourful
133 		 */
134 		HIGHLY(82.0 / 255.0),
135 		/**
136 		 * Extremely colourful
137 		 */
138 		EXTREMELY(109.0 / 255.0);
139 
140 		private double threshold;
141 
142 		private ColorfulnessAttr(double val) {
143 			this.threshold = val;
144 		}
145 
146 		/**
147 		 * Get the colourfulness class for a given colourfulness value.
148 		 * 
149 		 * @param val
150 		 *            the colourfulness value
151 		 * @return the colourfulness class
152 		 */
153 		public static ColorfulnessAttr getAttr(double val) {
154 			final ColorfulnessAttr[] attrs = values();
155 			for (int i = attrs.length - 1; i >= 0; i--) {
156 				if (val >= attrs[i].threshold)
157 					return attrs[i];
158 			}
159 			return null;
160 		}
161 
162 		@Override
163 		public EnumFV<ColorfulnessAttr> getFeatureVector() {
164 			return new EnumFV<ColorfulnessAttr>(this);
165 		}
166 	}
167 
168 	/**
169 	 * @return the colourfulness class from the last image analysed
170 	 */
171 	public ColorfulnessAttr getColorfulnessAttribute() {
172 		return ColorfulnessAttr.getAttr(getColorfulness());
173 	}
174 
175 	/**
176 	 * @return the colourfulness value from the last image analysed
177 	 */
178 	public double getColorfulness() {
179 		final double var_rg = rgStats.getVariance();
180 		final double var_yb = ybStats.getVariance();
181 		final double mean_rg = rgStats.getMean();
182 		final double mean_yb = ybStats.getMean();
183 
184 		final double stddev = Math.sqrt(var_rg + var_yb);
185 		final double mean = Math.sqrt(mean_rg * mean_rg + mean_yb * mean_yb);
186 
187 		return stddev + 0.3 * mean;
188 	}
189 
190 	@Override
191 	public DoubleFV getFeatureVector() {
192 		return new DoubleFV(new double[] { getColorfulness() });
193 	}
194 
195 	/*
196 	 * (non-Javadoc)
197 	 * 
198 	 * @see org.openimaj.image.analyser.PixelAnalyser#reset()
199 	 */
200 	@Override
201 	public void reset() {
202 		rgStats.clear();
203 		ybStats.clear();
204 	}
205 }