照相时,在预览画面上提示用户人脸的位置,并完成自动对焦等,是个错的应用; 下面是实现细节,我们知道在android的代码中已有人脸识别的底层算法代码,而且在framework层也封了调用的API函数
复制代码
我们知道,相机预览是用 SurfaceView来显示图片的;在我们画提示框时,不能直接用那个view的,会出现黑屏的状态,预览的画面也不流畅的。添加一个一样大小的SurfaceView来提示。
在xml布局中添加
复制代码
我的画提示框代码:
复制代码
- 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);
- 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);
-
- }
-
- }
在xml布局中添加
- <SurfaceView 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.camera;
- import android.content.Context;
-
- import android.graphics.Canvas;
-
- import android.graphics.Bitmap;
-
- import android.graphics.Color;
-
- import android.graphics.Paint;
-
- import android.graphics.Rect;
-
- import android.graphics.Paint.Style;
-
- import android.graphics.PixelFormat;
-
- import android.graphics.PorterDuffXfermode;
-
- import android.graphics.PorterDuff;
-
- import android.util.AttributeSet;
-
- import android.util.Log;
-
- import android.view.SurfaceHolder;
-
- import android.view.SurfaceView;
-
- import android.view.View;
-
- import android.graphics.PointF;
-
- import android.media.FaceDetector;
-
- import android.media.FaceDetector.Face;
- public class FindFaceView extends SurfaceView implements SurfaceHolder.Callback{
- protected SurfaceHolder sh;
-
- private SurfaceHolder mCameraSh;
-
- private int mWidth;
-
- private int mHeight;
-
- private float mEyesDistance;
- public FindFaceView(Context context, AttributeSet attrs) {
-
- super(context, attrs);
-
- // TODO Auto-generated constructor stub
-
- sh = getHolder();
-
- sh.addCallback(this);
-
- sh.setFormat(PixelFormat.TRANSPARENT);
-
- setZOrderOnTop(true);
-
- }
- public void surfaceChanged(SurfaceHolder arg0, int arg1, int w, int h) {
-
- // TODO Auto-generated method stub
-
- mWidth = w;
-
- mHeight = h;
-
- }
- public void surfaceCreated(SurfaceHolder arg0) {
-
- // TODO Auto-generated method stub
- }
- public void surfaceDestroyed(SurfaceHolder arg0) {
-
- // TODO Auto-generated method stub
- }
- void setCameraPreviewSurfaceHolder(SurfaceHolder sh) {
-
- mCameraSh = sh;
-
- }
-
- public int getFaceViewWidth() {
-
- return mWidth;
-
- }
-
- public int getFaceViewHeight() {
-
- return mHeight;
-
- }
- void clearDraw() {
-
- Canvas canvas = sh.lockCanvas();
-
- Paint clipPaint = new Paint();
-
- clipPaint.setAntiAlias(true);
-
- clipPaint.setStyle(Paint.Style.STROKE);
-
- clipPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
-
- canvas.drawPaint(clipPaint);
-
- sh.unlockCanvasAndPost(canvas);
-
- }
-
-
- public void drawRects(FaceDetector.Face[] mFace, int numberOfFaceDetected) {
-
- Canvas canvas = sh.lockCanvas();
- Paint clipPaint = new Paint();
-
- clipPaint.setAntiAlias(true);
-
- clipPaint.setStyle(Paint.Style.STROKE);
-
- clipPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
-
- canvas.drawPaint(clipPaint);
-
-
-
- canvas.drawColor(Color.TRANSPARENT);
-
- Paint p = new Paint();
-
- p.setAntiAlias(true);
-
- p.setColor(Color.RED);
-
- p.setStyle(Style.STROKE);
- for (int i = 0; i < numberOfFaceDetected; i++) {
-
- // if (0 == i) {
-
- // p.setColor(Color.WHITE);
-
- // } else {
-
- // p.setColor(Color.GRAY);
-
- // }
-
- Face face = mFace[i];
-
- PointF myMidPoint = new PointF();
-
- face.getMidPoint(myMidPoint);
-
- mEyesDistance = face.eyesDistance();
-
- Log.i("Harrison", "i="+i+"("+myMidPoint.x+", "+myMidPoint.y+")");
-
- canvas.drawRect((int)(myMidPoint.x-mEyesDistance),
-
- (int)(myMidPoint.y-mEyesDistance),
-
- (int)(myMidPoint.x+mEyesDistance),
-
- (int)(myMidPoint.y+mEyesDistance),
-
- p);
-
- }
-
- sh.unlockCanvasAndPost(canvas);
-
- }
- //测试两个View是否错移
-
- public void drawBitmap(Bitmap myBitmap) {
-
- Canvas canvas = sh.lockCanvas();
-
- canvas.drawBitmap(myBitmap, 0, 0, null);
-
- sh.unlockCanvasAndPost(canvas);
-
- // mImage.setImageBitmap(myBitmap);
-
- // mImage.invalidate();
-
- }
-
- public void doDraw() {
-
- Canvas canvas = sh.lockCanvas();
-
- canvas.drawColor(Color.TRANSPARENT);// 这里是绘制背景
-
- Paint p = new Paint(); // 笔触
-
- p.setAntiAlias(true); // 反锯齿
-
- p.setColor(Color.RED);
-
- p.setStyle(Style.STROKE);
-
- canvas.drawLine(mWidth/2 - 100, 0, mWidth/2 - 100, mHeight, p);
-
- canvas.drawLine(mWidth/2 + 100, 0, mWidth/2 + 100, mHeight, p);
-
- // ------------------------
-
- // 画边框---------------------
-
- Rect rec = canvas.getClipBounds();
-
- rec.bottom--;
-
- rec.right--;
-
- p.setColor(Color.GRAY);
-
- // 颜色
-
- p.setStrokeWidth(5);
-
- canvas.drawRect(rec, p);
-
- // 提交绘制
-
- sh.unlockCanvasAndPost(canvas);
-
- }
-
- }