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.openimaj.citation.annotation.Reference; 033import org.openimaj.citation.annotation.ReferenceType; 034import org.openimaj.feature.DoubleFV; 035import org.openimaj.feature.FeatureVectorProvider; 036import org.openimaj.image.FImage; 037import org.openimaj.image.analyser.ImageAnalyser; 038import org.openimaj.image.processor.GridProcessor; 039import org.openimaj.math.util.FloatArrayStatsUtils; 040 041/** 042 * Implementation of the Bokeh estimation feature described by Yeh et al. 043 * 044 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 045 * 046 */ 047@Reference( 048 type = ReferenceType.Inproceedings, 049 author = { "Che-Hua Yeh", "Yuan-Chen Ho", "Brian A. Barsky", "Ming Ouhyoung" }, 050 title = "Personalized Photograph Ranking and Selection System", 051 year = "2010", 052 booktitle = "Proceedings of ACM Multimedia", 053 pages = { "211", "220" }, 054 month = "October", 055 customData = { "location", "Florence, Italy" }) 056public class YehBokehEstimator implements ImageAnalyser<FImage>, FeatureVectorProvider<DoubleFV> { 057 class Sharpness implements GridProcessor<Float, FImage> { 058 SharpPixelProportion bpp = new SharpPixelProportion(); 059 060 @Override 061 public int getHorizontalGridElements() { 062 return nBlocksX; 063 } 064 065 @Override 066 public int getVerticalGridElements() { 067 return nBlocksY; 068 } 069 070 @Override 071 public Float processGridElement(FImage patch) { 072 patch.analyseWith(bpp); 073 return (float) bpp.getBlurredPixelProportion(); 074 } 075 } 076 077 class GreyLevelVariance implements GridProcessor<Float, FImage> { 078 @Override 079 public int getHorizontalGridElements() { 080 return nBlocksX; 081 } 082 083 @Override 084 public int getVerticalGridElements() { 085 return nBlocksY; 086 } 087 088 @Override 089 public Float processGridElement(FImage patch) { 090 return FloatArrayStatsUtils.var(patch.pixels); 091 } 092 } 093 094 Sharpness sharpProcessor = new Sharpness(); 095 GreyLevelVariance varProcessor = new GreyLevelVariance(); 096 097 int nBlocksX = 5; 098 int nBlocksY = 5; 099 100 float varThreshold = 0.1f; 101 float sharpnessThreshold = 0.5f; 102 float lowerBound = 0.3f; 103 float upperBound = 0.7f; 104 105 double bokeh; 106 107 /** 108 * Construct with defaults: 5x5 blocks, variance threshold of 0.1, sharpness 109 * threshold of 0.5, lower bound of 0.3, upper bound of 0.7 110 */ 111 public YehBokehEstimator() { 112 } 113 114 /** 115 * Construct with the given parameters. 116 * 117 * @param nBlocksX 118 * number of blocks in the x-direction 119 * @param nBlocksY 120 * number of blocks in the y-direction 121 * @param varThreshold 122 * threshold for the variance 123 * @param sharpnessThreshold 124 * threshold for the sharpness 125 * @param lowerBound 126 * lower bound on Qbokeh for bokeh to be detected 127 * @param upperBound 128 * upper bound on Qbokeh for bokeh to be detected 129 */ 130 public YehBokehEstimator(int nBlocksX, int nBlocksY, float varThreshold, float sharpnessThreshold, float lowerBound, 131 float upperBound) 132 { 133 this.nBlocksX = nBlocksX; 134 this.nBlocksY = nBlocksY; 135 this.varThreshold = varThreshold; 136 this.sharpnessThreshold = sharpnessThreshold; 137 this.lowerBound = lowerBound; 138 this.upperBound = upperBound; 139 } 140 141 @Override 142 public DoubleFV getFeatureVector() { 143 return new DoubleFV(new double[] { bokeh }); 144 } 145 146 /* 147 * (non-Javadoc) 148 * 149 * @see 150 * org.openimaj.image.processor.ImageProcessor#processImage(org.openimaj 151 * .image.Image) 152 */ 153 @Override 154 public void analyseImage(FImage image) { 155 final FImage sharpness = image.process(sharpProcessor); 156 final FImage variance = image.process(varProcessor); 157 158 double Qbokeh = 0; 159 int validBlocks = 0; 160 for (int y = 0; y < sharpness.height; y++) { 161 for (int x = 0; x < sharpness.width; x++) { 162 if (variance.pixels[y][x] >= varThreshold) { 163 Qbokeh += sharpness.pixels[y][x] > 0.5 ? 1 : 0; 164 validBlocks++; 165 } 166 } 167 } 168 Qbokeh /= (validBlocks); 169 170 bokeh = (Qbokeh >= lowerBound && Qbokeh <= upperBound) ? 1 : 0; 171 } 172}