1227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/* 2227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Copyright 2013 The Android Open Source Project 3227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 4227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Licensed under the Apache License, Version 2.0 (the "License"); 5227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * you may not use this file except in compliance with the License. 6227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * You may obtain a copy of the License at 7227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 8227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * http://www.apache.org/licenses/LICENSE-2.0 9227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 10227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Unless required by applicable law or agreed to in writing, software 11227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * distributed under the License is distributed on an "AS IS" BASIS, 12227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * See the License for the specific language governing permissions and 14227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * limitations under the License. 15227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 16227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks// Takes sharpness score, rates the image good if above 10, bad otherwise 17227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 18227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspackage androidx.media.filterfw.samples.simplecamera; 19227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.graphics.Bitmap; 21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.os.AsyncTask; 22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.util.Log; 23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.widget.ImageView; 24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.Filter; 25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.FrameImage2D; 26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.FrameType; 27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.FrameValue; 28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.MffContext; 29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.OutputPort; 30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.Signature; 31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspublic class ImageGoodnessFilter extends Filter { 33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static final String TAG = "ImageGoodnessFilter"; 35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static boolean mLogVerbose = Log.isLoggable(TAG, Log.VERBOSE); 36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final static String GREAT = "Great Picture!"; 38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final static String GOOD = "Good Picture!"; 39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final static String OK = "Ok Picture"; 40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final static String BAD = "Bad Picture"; 41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final static String AWFUL = "Awful Picture"; 42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final static float SMALL_SCORE_INC = 0.25f; 43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final static float BIG_SCORE_INC = 0.5f; 44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final static float LOW_VARIANCE = 0.1f; 45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final static float MEDIUM_VARIANCE = 10; 46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final static float HIGH_VARIANCE = 100; 47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float sharpnessMean = 0; 48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float sharpnessVar = 0; 49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float underExposureMean = 0; 50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float underExposureVar = 0; 51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float overExposureMean = 0; 52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float overExposureVar = 0; 53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float contrastMean = 0; 54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float contrastVar = 0; 55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float colorfulnessMean = 0; 56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float colorfulnessVar = 0; 57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float brightnessMean = 0; 58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float brightnessVar = 0; 59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float motionMean = 0; 61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float scoreMean = 0; 62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static final float DECAY = 0.03f; 63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param context 65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param name 66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public ImageGoodnessFilter(MffContext context, String name) { 68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks super(context, name); 69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public Signature getSignature() { 73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameType floatT = FrameType.single(float.class); 74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameType imageIn = FrameType.image2D(FrameType.ELEMENT_RGBA8888, FrameType.READ_GPU); 75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new Signature() 77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .addInputPort("sharpness", Signature.PORT_REQUIRED, floatT) 78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .addInputPort("overExposure", Signature.PORT_REQUIRED, floatT) 79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .addInputPort("underExposure", Signature.PORT_REQUIRED, floatT) 80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .addInputPort("colorfulness", Signature.PORT_REQUIRED, floatT) 81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .addInputPort("contrastRating", Signature.PORT_REQUIRED, floatT) 82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .addInputPort("motionValues", Signature.PORT_REQUIRED, FrameType.array(float.class)) 83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .addInputPort("brightness", Signature.PORT_REQUIRED, floatT) 84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .addInputPort("capturing", Signature.PORT_REQUIRED, FrameType.single(boolean.class)) 85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .addInputPort("image", Signature.PORT_REQUIRED, imageIn) 86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .addOutputPort("goodOrBadPic", Signature.PORT_REQUIRED, 87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameType.single(String.class)) 88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .addOutputPort("score", Signature.PORT_OPTIONAL, floatT) 89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .disallowOtherPorts(); 90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @see androidx.media.filterfw.Filter#onProcess() 94227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 95227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 96227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks protected void onProcess() { 97227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameValue sharpnessFrameValue = 98227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks getConnectedInputPort("sharpness").pullFrame().asFrameValue(); 99227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float sharpness = ((Float)sharpnessFrameValue.getValue()).floatValue(); 100227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 101227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameValue overExposureFrameValue = 102227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks getConnectedInputPort("overExposure").pullFrame().asFrameValue(); 103227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float overExposure = ((Float)overExposureFrameValue.getValue()).floatValue(); 104227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 105227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameValue underExposureFrameValue = 106227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks getConnectedInputPort("underExposure").pullFrame().asFrameValue(); 107227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float underExposure = ((Float)underExposureFrameValue.getValue()).floatValue(); 108227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 109227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameValue colorfulnessFrameValue = 110227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks getConnectedInputPort("colorfulness").pullFrame().asFrameValue(); 111227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float colorfulness = ((Float)colorfulnessFrameValue.getValue()).floatValue(); 112227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 113227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameValue contrastRatingFrameValue = 114227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks getConnectedInputPort("contrastRating").pullFrame().asFrameValue(); 115227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float contrastRating = ((Float)contrastRatingFrameValue.getValue()).floatValue(); 116227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 117227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameValue brightnessFrameValue = 118227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks getConnectedInputPort("brightness").pullFrame().asFrameValue(); 119227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float brightness = ((Float)brightnessFrameValue.getValue()).floatValue(); 120227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 121227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameValue motionValuesFrameValue = 122227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks getConnectedInputPort("motionValues").pullFrame().asFrameValue(); 123227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float[] motionValues = (float[]) motionValuesFrameValue.getValue(); 124227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 125227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 126227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float vectorAccel = (float) Math.sqrt(Math.pow(motionValues[0], 2) + 127227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Math.pow(motionValues[1], 2) + Math.pow(motionValues[2], 2)); 128227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks String outStr; 129227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 130227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameValue capturingFrameValue = 131227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks getConnectedInputPort("capturing").pullFrame().asFrameValue(); 132227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks boolean capturing = (Boolean) capturingFrameValue.getValue(); 133227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 134227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameImage2D inputImage = getConnectedInputPort("image").pullFrame().asFrameImage2D(); 135227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 136227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 137227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // TODO: get rid of magic numbers 138227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float score = 0.0f; 139227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks score = computePictureScore(vectorAccel, sharpness, underExposure, overExposure, 140227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks contrastRating, colorfulness, brightness); 141227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (scoreMean == 0) scoreMean = score; 142227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks else scoreMean = scoreMean * (1 - DECAY) + score * DECAY; 143227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 144227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (motionMean == 0) motionMean = vectorAccel; 145227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks else motionMean = motionMean * (1 - DECAY) + vectorAccel * DECAY; 146227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 147227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float classifierScore = classifierComputeScore(vectorAccel, sharpness, underExposure, 148227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks colorfulness, contrastRating, score); 149227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 150227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks// Log.v(TAG, "ClassifierScore:: " + classifierScore); 151227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks final float GREAT_SCORE = 3.5f; 152227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks final float GOOD_SCORE = 2.5f; 153227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks final float OK_SCORE = 1.5f; 154227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks final float BAD_SCORE = 0.5f; 155227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 156227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (score >= GREAT_SCORE) { 157227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks outStr = GREAT; 158227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (score >= GOOD_SCORE) { 159227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks outStr = GOOD; 160227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (score >= OK_SCORE) { 161227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks outStr = OK; 162227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (score >= BAD_SCORE) { 163227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks outStr = BAD; 164227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 165227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks outStr = AWFUL; 166227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 167227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 168227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if(capturing) { 169227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (outStr.equals(GREAT)) { 170227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // take a picture 171227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Bitmap bitmap = inputImage.toBitmap(); 172227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 173227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks new AsyncOperation().execute(bitmap); 174227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks final float RESET_FEATURES = 0.01f; 175227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks sharpnessMean = RESET_FEATURES; 176227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks underExposureMean = RESET_FEATURES; 177227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks overExposureMean = RESET_FEATURES; 178227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks contrastMean = RESET_FEATURES; 179227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks colorfulnessMean = RESET_FEATURES; 180227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks brightnessMean = RESET_FEATURES; 181227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 182227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 183227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 184227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks OutputPort outPort = getConnectedOutputPort("goodOrBadPic"); 185227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameValue stringFrame = outPort.fetchAvailableFrame(null).asFrameValue(); 186227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks stringFrame.setValue(outStr); 187227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks outPort.pushFrame(stringFrame); 188227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 189227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks OutputPort scoreOutPort = getConnectedOutputPort("score"); 190227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameValue scoreFrame = scoreOutPort.fetchAvailableFrame(null).asFrameValue(); 191227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks scoreFrame.setValue(score); 192227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks scoreOutPort.pushFrame(scoreFrame); 193227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 194227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 195227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 196227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private class AsyncOperation extends AsyncTask<Bitmap, Void, String> { 197227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private Bitmap b; 198227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks protected void onPostExecute(String result) { 199227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ImageView view = SmartCamera.getImageView(); 200227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks view.setImageBitmap(b); 201227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 202227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 203227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 204227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks protected String doInBackground(Bitmap... params) { 205227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // TODO Auto-generated method stub 206227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks b = params[0]; 207227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return null; 208227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 209227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 210227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 211227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Returns a number between -1 and 1 212227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float classifierComputeScore(float vectorAccel, float sharpness, float underExposure, 213227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float colorfulness, float contrast, float score) { 214227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float result = (-0.0223f * sharpness + -0.0563f * underExposure + 0.0137f * colorfulness 215227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + 0.3102f * contrast + 0.0314f * vectorAccel + -0.0094f * score + 0.0227f * 216227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks sharpnessMean + 0.0459f * underExposureMean + -0.3934f * contrastMean + 217227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks -0.0697f * motionMean + 0.0091f * scoreMean + -0.0152f); 218227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return result; 219227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 220227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 221227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Returns a number between -1 and 4 representing the score for this picture 222227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float computePictureScore(float vector_accel, float sharpness, 223227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float underExposure, float overExposure, float contrastRating, float colorfulness, 224227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float brightness) { 225227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks final float ACCELERATION_THRESHOLD_VERY_STEADY = 0.1f; 226227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks final float ACCELERATION_THRESHOLD_STEADY = 0.3f; 227227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks final float ACCELERATION_THRESHOLD_MOTION = 2f; 228227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 229227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float score = 0.0f; 230227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (vector_accel > ACCELERATION_THRESHOLD_MOTION) { 231227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks score -= (BIG_SCORE_INC + BIG_SCORE_INC); // set score to -1, bad pic 232227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (vector_accel > ACCELERATION_THRESHOLD_STEADY) { 233227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks score -= BIG_SCORE_INC; 234227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks score = subComputeScore(sharpness, underExposure, overExposure, contrastRating, 235227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks colorfulness, brightness, score); 236227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (vector_accel < ACCELERATION_THRESHOLD_VERY_STEADY) { 237227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks score += BIG_SCORE_INC; 238227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks score = subComputeScore(sharpness, underExposure, overExposure, contrastRating, 239227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks colorfulness, brightness, score); 240227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 241227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks score = subComputeScore(sharpness, underExposure, overExposure, contrastRating, 242227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks colorfulness, brightness, score); 243227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 244227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return score; 245227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 246227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 247227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Changes the score by at most +/- 3.5 248227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float subComputeScore(float sharpness, float underExposure, float overExposure, 249227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float contrastRating, float colorfulness, float brightness, float score) { 250227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // The score methods return values -0.5 to 0.5 251227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks final float SHARPNESS_WEIGHT = 2; 252227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks score += SHARPNESS_WEIGHT * sharpnessScore(sharpness); 253227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks score += underExposureScore(underExposure); 254227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks score += overExposureScore(overExposure); 255227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks score += contrastScore(contrastRating); 256227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks score += colorfulnessScore(colorfulness); 257227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks score += brightnessScore(brightness); 258227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return score; 259227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 260227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 261227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float sharpnessScore(float sharpness) { 262227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (sharpnessMean == 0) { 263227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks sharpnessMean = sharpness; 264227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks sharpnessVar = 0; 265227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return 0; 266227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 267227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks sharpnessMean = sharpnessMean * (1 - DECAY) + sharpness * DECAY; 268227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks sharpnessVar = sharpnessVar * (1 - DECAY) + (sharpness - sharpnessMean) * 269227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks (sharpness - sharpnessMean) * DECAY; 270227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (sharpnessVar < LOW_VARIANCE) { 271227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return BIG_SCORE_INC; 272227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (sharpness < sharpnessMean && sharpnessVar > MEDIUM_VARIANCE) { 273227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return -BIG_SCORE_INC; 274227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (sharpness < sharpnessMean) { 275227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return -SMALL_SCORE_INC; 276227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (sharpness > sharpnessMean && sharpnessVar > HIGH_VARIANCE) { 277227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return 0; 278227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (sharpness > sharpnessMean && sharpnessVar > MEDIUM_VARIANCE) { 279227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return SMALL_SCORE_INC; 280227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 281227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return BIG_SCORE_INC; // low variance, sharpness above the mean 282227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 283227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 284227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 285227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 286227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float underExposureScore(float underExposure) { 287227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (underExposureMean == 0) { 288227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks underExposureMean = underExposure; 289227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks underExposureVar = 0; 290227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return 0; 291227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 292227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks underExposureMean = underExposureMean * (1 - DECAY) + underExposure * DECAY; 293227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks underExposureVar = underExposureVar * (1 - DECAY) + (underExposure - underExposureMean) 294227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * (underExposure - underExposureMean) * DECAY; 295227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (underExposureVar < LOW_VARIANCE) { 296227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return BIG_SCORE_INC; 297227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (underExposure > underExposureMean && underExposureVar > MEDIUM_VARIANCE) { 298227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return -BIG_SCORE_INC; 299227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (underExposure > underExposureMean) { 300227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return -SMALL_SCORE_INC; 301227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (underExposure < underExposureMean && underExposureVar > HIGH_VARIANCE) { 302227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return 0; 303227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (underExposure < underExposureMean && underExposureVar > MEDIUM_VARIANCE) { 304227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return SMALL_SCORE_INC; 305227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 306227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return BIG_SCORE_INC; // low variance, underExposure below the mean 307227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 308227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 309227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 310227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 311227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float overExposureScore(float overExposure) { 312227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (overExposureMean == 0) { 313227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks overExposureMean = overExposure; 314227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks overExposureVar = 0; 315227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return 0; 316227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 317227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks overExposureMean = overExposureMean * (1 - DECAY) + overExposure * DECAY; 318227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks overExposureVar = overExposureVar * (1 - DECAY) + (overExposure - overExposureMean) * 319227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks (overExposure - overExposureMean) * DECAY; 320227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (overExposureVar < LOW_VARIANCE) { 321227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return BIG_SCORE_INC; 322227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (overExposure > overExposureMean && overExposureVar > MEDIUM_VARIANCE) { 323227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return -BIG_SCORE_INC; 324227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (overExposure > overExposureMean) { 325227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return -SMALL_SCORE_INC; 326227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (overExposure < overExposureMean && overExposureVar > HIGH_VARIANCE) { 327227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return 0; 328227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (overExposure < overExposureMean && overExposureVar > MEDIUM_VARIANCE) { 329227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return SMALL_SCORE_INC; 330227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 331227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return BIG_SCORE_INC; // low variance, overExposure below the mean 332227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 333227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 334227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 335227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 336227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float contrastScore(float contrast) { 337227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (contrastMean == 0) { 338227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks contrastMean = contrast; 339227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks contrastVar = 0; 340227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return 0; 341227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 342227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks contrastMean = contrastMean * (1 - DECAY) + contrast * DECAY; 343227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks contrastVar = contrastVar * (1 - DECAY) + (contrast - contrastMean) * 344227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks (contrast - contrastMean) * DECAY; 345227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (contrastVar < LOW_VARIANCE) { 346227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return BIG_SCORE_INC; 347227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (contrast < contrastMean && contrastVar > MEDIUM_VARIANCE) { 348227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return -BIG_SCORE_INC; 349227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (contrast < contrastMean) { 350227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return -SMALL_SCORE_INC; 351227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (contrast > contrastMean && contrastVar > 100) { 352227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return 0; 353227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (contrast > contrastMean && contrastVar > MEDIUM_VARIANCE) { 354227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return SMALL_SCORE_INC; 355227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 356227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return BIG_SCORE_INC; // low variance, contrast above the mean 357227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 358227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 359227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 360227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 361227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float colorfulnessScore(float colorfulness) { 362227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (colorfulnessMean == 0) { 363227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks colorfulnessMean = colorfulness; 364227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks colorfulnessVar = 0; 365227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return 0; 366227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 367227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks colorfulnessMean = colorfulnessMean * (1 - DECAY) + colorfulness * DECAY; 368227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks colorfulnessVar = colorfulnessVar * (1 - DECAY) + (colorfulness - colorfulnessMean) * 369227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks (colorfulness - colorfulnessMean) * DECAY; 370227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (colorfulnessVar < LOW_VARIANCE) { 371227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return BIG_SCORE_INC; 372227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (colorfulness < colorfulnessMean && colorfulnessVar > MEDIUM_VARIANCE) { 373227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return -BIG_SCORE_INC; 374227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (colorfulness < colorfulnessMean) { 375227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return -SMALL_SCORE_INC; 376227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (colorfulness > colorfulnessMean && colorfulnessVar > 100) { 377227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return 0; 378227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (colorfulness > colorfulnessMean && colorfulnessVar > MEDIUM_VARIANCE) { 379227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return SMALL_SCORE_INC; 380227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 381227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return BIG_SCORE_INC; // low variance, colorfulness above the mean 382227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 383227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 384227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 385227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 386227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float brightnessScore(float brightness) { 387227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (brightnessMean == 0) { 388227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks brightnessMean = brightness; 389227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks brightnessVar = 0; 390227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return 0; 391227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 392227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks brightnessMean = brightnessMean * (1 - DECAY) + brightness * DECAY; 393227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks brightnessVar = brightnessVar * (1 - DECAY) + (brightness - brightnessMean) * 394227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks (brightness - brightnessMean) * DECAY; 395227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (brightnessVar < LOW_VARIANCE) { 396227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return BIG_SCORE_INC; 397227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (brightness < brightnessMean && brightnessVar > MEDIUM_VARIANCE) { 398227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return -BIG_SCORE_INC; 399227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (brightness < brightnessMean) { 400227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return -SMALL_SCORE_INC; 401227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (brightness > brightnessMean && brightnessVar > 100) { 402227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return 0; 403227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (brightness > brightnessMean && brightnessVar > MEDIUM_VARIANCE) { 404227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return SMALL_SCORE_INC; 405227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 406227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return BIG_SCORE_INC; // low variance, brightness above the mean 407227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 408227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 409227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 410227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks} 411