| /* |
| * 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 |
| * (<var>EULER_X</var>, <var>EULER_Y</var> or |
| * <var>EULER_Z</var>) |
| * @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 <var>maxFaces</var> 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 <var>maxFaces</var> 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<numFaces ; i++) { |
| if (faces[i] == null) |
| faces[i] = new Face(); |
| fft_get_face(faces[i], i); |
| } |
| return numFaces; |
| } |
| |
| |
| /* no user serviceable parts here ... */ |
| @Override |
| protected void finalize() throws Throwable { |
| fft_destroy(); |
| } |
| |
| /* |
| * We use a class initializer to allow the native code to cache some |
| * field offsets. |
| */ |
| private static boolean sInitialized; |
| native private static void nativeClassInit(); |
| |
| static { |
| sInitialized = false; |
| try { |
| System.loadLibrary("FFTEm"); |
| nativeClassInit(); |
| sInitialized = true; |
| } catch (UnsatisfiedLinkError e) { |
| Log.d("FFTEm", "face detection library not found!"); |
| } |
| } |
| |
| native private int fft_initialize(int width, int height, int maxFaces); |
| native private int fft_detect(Bitmap bitmap); |
| native private void fft_get_face(Face face, int i); |
| native private void fft_destroy(); |
| |
| private long mFD; |
| private long mSDK; |
| private long mDCR; |
| private int mWidth; |
| private int mHeight; |
| private int mMaxFaces; |
| private byte mBWBuffer[]; |
| } |
| |