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.processing.face.detection;
031
032import java.io.DataInput;
033import java.io.DataOutput;
034import java.io.IOException;
035
036import org.openimaj.image.FImage;
037import org.openimaj.image.ImageUtilities;
038import org.openimaj.io.ReadWriteableBinary;
039import org.openimaj.math.geometry.shape.Rectangle;
040import org.openimaj.math.geometry.shape.Shape;
041
042/**
043 * A DetectedFace models a face detected by a face detector, together with the
044 * locations of certain facial features localised on the face.
045 *
046 * @author Jonathon Hare
047 *
048 */
049public class DetectedFace implements ReadWriteableBinary {
050        /**
051         * The upright bounds of the face in the image in which it was detected
052         */
053        protected Rectangle bounds;
054
055        /**
056         * The extracted sub-image representing the face. This is normally extracted
057         * directly from the bounds rectangle in the original image, but in some
058         * cases might be extracted from a sub-region of the bounds rectangle.
059         */
060        protected FImage facePatch;
061
062        /**
063         * The confidence of the detection; higher numbers mean higher confidence.
064         */
065        protected float confidence = 1;
066
067        /**
068         * Default constructor with an empty rectangle as bounds
069         */
070        public DetectedFace() {
071                this.bounds = new Rectangle();
072        }
073
074        /**
075         * Construct with a bounds rectangle (the bounding box of the face in the
076         * detection image) and an image patch that describes the contents of the
077         * bounds rectangle from the original image.
078         *
079         * @param bounds
080         *            The bounding box of the face in the detection image.
081         * @param patch
082         *            The subimage describing the contents of the bounding box.
083         * @param confidence
084         *            The confidence of the detection.
085         */
086        public DetectedFace(final Rectangle bounds, final FImage patch, final float confidence) {
087                this.bounds = bounds;
088                this.facePatch = patch;
089                this.confidence = confidence;
090        }
091
092        /**
093         *      Returns the sub-image representing the face.
094         *      @return Get the sub-image representing the detected face
095         */
096        public FImage getFacePatch() {
097                return this.facePatch;
098        }
099
100        /**
101         *      Reset the face patch image
102         *      @param img The image
103         */
104        public void setFacePatch( final FImage img )
105        {
106                this.facePatch = img;
107        }
108
109        /**
110         * Get the bounding box of the face in the detection image. This might be
111         * the same as the shape returned by {@link #getShape()}, or it might
112         * encompass that shape.
113         *
114         * @return The bounding box of the face in the detection image
115         */
116        public Rectangle getBounds() {
117                return this.bounds;
118        }
119
120        /**
121         *      Set the bounds of this face. This is so that detected face objects
122         *      can be updated if the bounds were inaccurate, or tracking is taking
123         *      place on the object.
124         *      @param rect The new bounds
125         */
126        public void setBounds( final Rectangle rect )
127        {
128                this.bounds = rect;
129        }
130
131        @Override
132        public void writeBinary(final DataOutput out) throws IOException {
133                this.bounds.writeBinary(out);
134                ImageUtilities.write(this.facePatch, "png", out);
135        }
136
137        @Override
138        public byte[] binaryHeader() {
139                return "DF".getBytes();
140        }
141
142        @Override
143        public void readBinary(final DataInput in) throws IOException {
144                this.bounds.readBinary(in);
145                this.facePatch = ImageUtilities.readF(in);
146        }
147
148        /**
149         * Get the confidence of the detection. Higher numbers mean higher
150         * confidence.
151         *
152         * @return the confidence.
153         */
154        public float getConfidence() {
155                return this.confidence;
156        }
157
158        /**
159         * Get the shape of the detection. In most cases, this will just return the
160         * bounds rectangle, however, subclasses can override to return a better
161         * geometric description of the detection area.
162         *
163         * @return the shape describing the detection in the original image.
164         */
165        public Shape getShape() {
166                return this.bounds;
167        }
168
169        /**
170         * Set the confidence of the detection. Higher numbers mean higher
171         * confidence.
172         *
173         * @param confidence
174         *            the confidence.
175         */
176        public void setConfidence(final int confidence) {
177                this.confidence = confidence;
178        }
179}