/* * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.media; import android.graphics.Bitmap; import android.graphics.PointF; import android.util.Log; import java.lang.IllegalArgumentException; /** * Identifies the faces of people in a * {@link android.graphics.Bitmap} graphic object. */ public class FaceDetector { /** * A Face contains all the information identifying the location * of a face in a bitmap. */ public class Face { /** The minimum confidence factor of good face recognition */ public static final float CONFIDENCE_THRESHOLD = 0.4f; /** The x-axis Euler angle of a face. */ public static final int EULER_X = 0; /** The y-axis Euler angle of a face. */ public static final int EULER_Y = 1; /** The z-axis Euler angle of a face. */ public static final int EULER_Z = 2; /** * Returns a confidence factor between 0 and 1. This indicates how * certain what has been found is actually a face. A confidence * factor above 0.3 is usually good enough. */ public float confidence() { return mConfidence; } /** * Sets the position of the mid-point between the eyes. * @param point the PointF coordinates (float values) of the * face's mid-point */ public void getMidPoint(PointF point) { // don't return a PointF to avoid allocations point.set(mMidPointX, mMidPointY); } /** * Returns the distance between the eyes. */ public float eyesDistance() { return mEyesDist; } /** * Returns the face's pose. That is, the rotations around either * the X, Y or Z axis (the positions in 3-dimensional Euclidean space). * * @param euler the Euler axis to retrieve an angle from * (EULER_X, EULER_Y or * EULER_Z) * @return the Euler angle of the of the face, for the given axis */ public float pose(int euler) { // don't use an array to avoid allocations if (euler == EULER_X) return mPoseEulerX; else if (euler == EULER_Y) return mPoseEulerY; else if (euler == EULER_Z) return mPoseEulerZ; throw new IllegalArgumentException(); } // private ctor, user not supposed to build this object private Face() { } private float mConfidence; private float mMidPointX; private float mMidPointY; private float mEyesDist; private float mPoseEulerX; private float mPoseEulerY; private float mPoseEulerZ; } /** * Creates a FaceDetector, configured with the size of the images to * be analysed and the maximum number of faces that can be detected. * These parameters cannot be changed once the object is constructed. * Note that the width of the image must be even. * * @param width the width of the image * @param height the height of the image * @param maxFaces the maximum number of faces to identify * */ public FaceDetector(int width, int height, int maxFaces) { if (!sInitialized) { return; } fft_initialize(width, height, maxFaces); mWidth = width; mHeight = height; mMaxFaces = maxFaces; mBWBuffer = new byte[width * height]; } /** * Finds all the faces found in a given {@link android.graphics.Bitmap}. * The supplied array is populated with {@link FaceDetector.Face}s for each * face found. The bitmap must be in 565 format (for now). * * @param bitmap the {@link android.graphics.Bitmap} graphic to be analyzed * @param faces an array in which to place all found * {@link FaceDetector.Face}s. The array must be sized equal * to the maxFaces value set at initialization * @return the number of faces found * @throws IllegalArgumentException if the Bitmap dimensions don't match * the dimensions defined at initialization or the given array * is not sized equal to the maxFaces value defined * at initialization */ public int findFaces(Bitmap bitmap, Face[] faces) { if (!sInitialized) { return 0; } if (bitmap.getWidth() != mWidth || bitmap.getHeight() != mHeight) { throw new IllegalArgumentException( "bitmap size doesn't match initialization"); } if (faces.length < mMaxFaces) { throw new IllegalArgumentException( "faces[] smaller than maxFaces"); } int numFaces = fft_detect(bitmap); if (numFaces >= mMaxFaces) numFaces = mMaxFaces; for (int i=0 ; i