在Android实现人脸识别的详细过程
照相时,在预览画面上提示用户人脸的位置,并完成自动对焦等,是个错的应用; 下面是实现细节
我们知道在android的代码中已有人脸识别的底层算法代码,而且在framework层也封了调用的API函数
extern/neven 目录下是实现人脸识别的算法代码。
添加获取照相时预览图片数据,可以在onPreviewFrame回调函数中得。在开始预览的地方,用mCameraDevice.setPreviewCallback(mPreviewCallback);设置预览回调函数。
import android.media.FaceDetector;
import android.media.FaceDetector.Face;
//Harrison add
private void DrawRectOnFace() {
if (numberOfFaceDetected != 0) {
Face mFace1 = mFace[0];
PointF midPoint = new PointF();
mFace1.getMidPoint(midPoint);
if ((Math.abs(mPreMidPoint.x-midPoint.x) < 50) && (Math.abs(mPreMidPoint.y-midPoint.y) < 50)) {
Log.i("Harrison", "not draw Rect .");
return ;
}
mPreMidPoint.x = midPoint.x;
mPreMidPoint.y = midPoint.y;
mFindFaceView.setVisibility(View.VISIBLE);
} else {
mPreMidPoint.x = 0;
mPreMidPoint.y = 0;
mFindFaceView.clearDraw();
mFindFaceView.setVisibility(View.GONE);
return;
}
mFindFaceView.drawRects(mFace, numberOfFaceDetected);
}
//调用API找人脸,需要import进软件包哦!
private void FindFacesInBitmap(Bitmap myBitmap) {
imageWidth = myBitmap.getWidth();
imageHeight = myBitmap.getHeight();
Log.i("Harrison", "imageWidth="+imageWidth+", imageHeight="+imageHeight);
mFace = new FaceDetector.Face[numberOfFace];
mFaceDetect = new FaceDetector(imageWidth, imageHeight, numberOfFace);
numberOfFaceDetected = mFaceDetect.findFaces(myBitmap, mFace);
Log.i("Harrison", "numberOfFaceDetected="+numberOfFaceDetected);
}
private Bitmap rotateMyBitmap(Bitmap bitmap) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
Matrix matrix = new Matrix();
matrix.postRotate(90); //椤烘椂閽熸棆杞?0搴︺€?
Bitmap rotateBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
return rotateBitmap;
}
private Bitmap scaleMyBitmap(Bitmap bitmap) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int nWidth = mFindFaceView.getFaceViewWidth();;
int nHeight = mFindFaceView.getFaceViewHeight();
// Log.i("Harrison", "nWidth="+nWidth+", nHeight"+nHeight);
float scaleWidth = ((float) nWidth)/width;
float scaleHeight = ((float)nHeight)/height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
return resizedBitmap;
}
//处理图片格式,一般摄像头抓到的数据为ImageFormat.NV21,不同的格式,需要调整的。
private void decodeToBitMap(byte[] data, android.hardware.Camera _camera) {
mCameraDevice.setPreviewCallback(null);
Size size = mCameraDevice.getParameters().getPreviewSize();
//FileOutputStream outStream = null;
try {
YuvImage image = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);
if (image != null) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
image.compressToJpeg(new Rect(0, 0, size.width, size.height), 80, stream);
// outStream = new FileOutputStream(String.format("/sdcard/%d.jpg", System.currentTimeMillis()));
// outStream.write(stream.toByteArray());
// outStream.close();
// Log.i("Harrison", "write file to sdcard.");
//在我的手机上有两种预览模式,发现全屏模式时需要调整图片的大小才能正确定位。
Bitmap myBitmap=BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size());
stream.close();
if (mPreviewLayoutProxy.getFullScreenMode()) { // fullscreen mode
Bitmap tmpScaleBmp=null;
Bitmap tmpRotateBmp=null;
//手机是竖屏横排是与其别的哦
if (((mOrientation/90) == 0) || ((mOrientation/90) == 2)) {
tmpRotateBmp = rotateMyBitmap(myBitmap);
tmpScaleBmp = scaleMyBitmap(tmpRotateBmp);
FindFacesInBitmap(tmpScaleBmp);
if (tmpRotateBmp != null) {
tmpRotateBmp.recycle();
tmpRotateBmp = null;
}
} else {
FindFacesInBitmap(scaleMyBitmap(myBitmap));
}
if (tmpScaleBmp != null) {
tmpScaleBmp.recycle();
tmpScaleBmp = null;
}
} else { //normal mode
FindFacesInBitmap(myBitmap);
}
DrawRectOnFace();
if (myBitmap != null) {
myBitmap.recycle();
myBitmap = null;
}
}
} catch (Exception ex) {
Log.e("Sys", "Error:" + ex.getMessage());
}
mCameraDevice.setPreviewCallback(mPreviewCallback);
}
private final class PostPreviewCallback implements PreviewCallback {
@Override
public void onPreviewFrame(byte[] data, android.hardware.Camera camera) {
decodeToBitMap(data, camera);
}
}
我们知道,相机预览是用 Su易做图ceView来显示图片的;在我们画提示框时,不能直接用那个view的,会出现黑屏的状态,预览的画面也不流畅的。
添加一个一样大小的Su易做图ceView来提示。
在xml布局中添加
<Su易做图ceView android:id="@+id/camera_preview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<!-- Harrison add finding faces Rectangle-->
<com.android.camera.FindFaceView
android:id="@+id/faces_rectangle"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<!-- end add 20121119 -->
我的画提示框代码:
package com
补充:移动开发 , Android ,