1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
|
/*
* 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[];
}
|