203 lines
6.8 KiB
Java
203 lines
6.8 KiB
Java
/*
|
|
* 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 int mFD;
|
|
private int mSDK;
|
|
private int mDCR;
|
|
private int mWidth;
|
|
private int mHeight;
|
|
private int mMaxFaces;
|
|
private byte mBWBuffer[];
|
|
}
|
|
|