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.feature.global; 031 032import org.apache.commons.math.stat.descriptive.SummaryStatistics; 033import org.openimaj.citation.annotation.Reference; 034import org.openimaj.citation.annotation.ReferenceType; 035import org.openimaj.feature.DoubleFV; 036import org.openimaj.feature.EnumFV; 037import org.openimaj.feature.FeatureVectorProvider; 038import org.openimaj.image.analyser.PixelAnalyser; 039 040/** 041 * Implementation of Hasler and Susstruck's Colorfulness metric 042 * http://infoscience.epfl.ch/record/33994/files/HaslerS03.pdf?version=1 043 * 044 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 045 */ 046@Reference( 047 type = ReferenceType.Inproceedings, 048 author = { "Hasler, David", "S\\\"{u}sstrunk, Sabine" }, 049 title = "Measuring {C}olourfulness in {N}atural {I}mages", 050 year = "2003", 051 booktitle = "Proc. {IS}&{T}/{SPIE} {E}lectronic {I}maging 2003: {H}uman {V}ision and {E}lectronic {I}maging {VIII}", 052 pages = { "87", "", "95" }, 053 volume = "5007", 054 url = "http://infoscience.epfl.ch/record/33994/files/HaslerS03.pdf?version=1", 055 customData = { 056 "details", "http://infoscience.epfl.ch/record/33994", 057 "documenturl", "http://infoscience.epfl.ch/record/33994/files/HaslerS03.pdf", 058 "doi", "10.1117/12.477378", 059 "keywords", "IVRG; colorfulness; image quality; image attributes; colourfulness", 060 "location", "San Jose, CA", 061 "oai-id", "oai:infoscience.epfl.ch:33994", 062 "oai-set", "conf; fulltext; fulltext-public", 063 "review", "NON-REVIEWED", 064 "status", "PUBLISHED", 065 "unit", "LCAV IVRG" 066 }) 067public class Colorfulness implements PixelAnalyser<Float[]>, FeatureVectorProvider<DoubleFV> { 068 SummaryStatistics rgStats = new SummaryStatistics(); 069 SummaryStatistics ybStats = new SummaryStatistics(); 070 071 @Override 072 public void analysePixel(Float[] pixel) { 073 final float r = pixel[0]; 074 final float g = pixel[1]; 075 final float b = pixel[2]; 076 077 final float rg = r - g; 078 final float yb = 0.5f * (r + g) - b; 079 080 rgStats.addValue(rg); 081 ybStats.addValue(yb); 082 } 083 084 /** 085 * Classes of colourfulness 086 * 087 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 088 */ 089 @Reference( 090 type = ReferenceType.Inproceedings, 091 author = { "Hasler, David", "S\\\"{u}sstrunk, Sabine" }, 092 title = "Measuring {C}olourfulness in {N}atural {I}mages", 093 year = "2003", 094 booktitle = "Proc. {IS}&{T}/{SPIE} {E}lectronic {I}maging 2003: {H}uman {V}ision and {E}lectronic {I}maging {VIII}", 095 pages = { "87", "", "95" }, 096 volume = "5007", 097 url = "http://infoscience.epfl.ch/record/33994/files/HaslerS03.pdf?version=1", 098 customData = { 099 "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}