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.feature.DoubleFV;
033import org.openimaj.feature.FeatureVectorProvider;
034import org.openimaj.image.FImage;
035import org.openimaj.image.MBFImage;
036import org.openimaj.image.analyser.ImageAnalyser;
037import org.openimaj.image.mask.AbstractMaskedObject;
038
039/**
040 * Extract the average brightness of an image. Brightness can be computed in a
041 * number of different ways, depending on the chosen {@link Mode}.
042 * 
043 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
044 */
045public class AvgBrightness extends AbstractMaskedObject<FImage>
046                implements
047                ImageAnalyser<MBFImage>,
048                FeatureVectorProvider<DoubleFV>
049{
050        /**
051         * Modes for computing brightness.
052         * 
053         * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
054         * 
055         */
056        public enum Mode {
057                /**
058                 * Luminance using the NTSC weighting scheme (equivalent to the Y in the
059                 * YUV colour space)
060                 */
061                NTSC_LUMINANCE {
062                        @Override
063                        public double computeBrightness(MBFImage image, FImage mask) {
064                                final FImage R = image.getBand(0);
065                                final FImage G = image.getBand(1);
066                                final FImage B = image.getBand(2);
067
068                                double brightness = 0;
069
070                                if (mask != null) {
071                                        for (int y = 0; y < R.height; y++) {
072                                                for (int x = 0; x < R.width; x++) {
073                                                        if (mask.pixels[y][x] == 1)
074                                                                brightness += (0.299f * R.pixels[y][x] + 0.587f * G.pixels[y][x] + 0.114f * B.pixels[y][x]);
075                                                }
076                                        }
077                                } else {
078                                        for (int y = 0; y < R.height; y++)
079                                                for (int x = 0; x < R.width; x++)
080                                                        brightness += (0.299f * R.pixels[y][x] + 0.587f * G.pixels[y][x] + 0.114f * B.pixels[y][x]);
081                                }
082
083                                return brightness / (R.height * R.width);
084                        }
085                };
086
087                /**
088                 * Compute the average brightness of the given image (applying the mask
089                 * if it's not <code>null</code>).
090                 * 
091                 * @param img
092                 *            the image to extract the average brightness from
093                 * @param mask
094                 *            the mask
095                 * @return the average brightness
096                 */
097                public abstract double computeBrightness(MBFImage img, FImage mask);
098        }
099
100        private Mode mode;
101        private double brightness;
102
103        /**
104         * Construct with the NTSC_LUMINANCE mode and no mask set
105         */
106        public AvgBrightness() {
107                this(Mode.NTSC_LUMINANCE, null);
108        }
109
110        /**
111         * Construct with the given mode and no mask set
112         * 
113         * @param mode
114         *            the {@link Mode}
115         */
116        public AvgBrightness(Mode mode) {
117                this(mode, null);
118        }
119
120        /**
121         * Construct with the given mode and a mask.
122         * 
123         * @param mode
124         *            the {@link Mode}
125         * @param mask
126         *            the mask.
127         */
128        public AvgBrightness(Mode mode, FImage mask) {
129                super(mask);
130
131                this.mode = mode;
132        }
133
134        @Override
135        public void analyseImage(MBFImage image) {
136                brightness = mode.computeBrightness(image, mask);
137        }
138
139        /**
140         * Get the brightness.
141         * 
142         * @return the brightness
143         */
144        public double getBrightness() {
145                return brightness;
146        }
147
148        @Override
149        public DoubleFV getFeatureVector() {
150                return new DoubleFV(new double[] { brightness });
151        }
152}