android 人脸检测代码,在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);
}
}
我们知道,相机预览是用 SurfaceView来显示图片的;在我们画提示框时,不能直接用那个view的,会出现黑屏的状态,预览的画面也不流畅的。
添加一个一样大小的SurfaceView来提示。
在xml布局中添加
android:layout_width="match_parent"
android:layout_height="match_parent"/>
android:id="@+id/faces_rectangle"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
我的画提示框代码:
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);
}
}
遇到一个问题,在预览时频繁的全屏普通切换,容易粗出现识别库无效。请高手指点指点。
本文转载自:CSDN博客
欢迎加入我爱机器学习QQ14群:336582044
微信扫一扫,关注我爱机器学习公众号
android 人脸检测代码,在Android实现人脸识别的详细过程相关推荐
- OpenCvSharp人脸检测(一) HaarCascade与LbpCascade人脸检测
本文作者Color Space,文章未经作者允许禁止转载! 本文将介绍OpenCvSharp人脸检测(一) HaarCascade与LbpCascade人脸检测效果对比! 前言: 实例来源(OpenC ...
- 人脸检测概述(不是人脸识别)
目录 1 引言... 3 2 人脸检测技术的发展与现状... 4 3 人脸检测算法相关工作... 4 3.1 评价指标... 5 3.2 人脸检测常用数据库... 6 3.2.1 FDDB ...
- MTCNN人脸检测与对齐和FaceNet人脸识别
一 MTCNN算法结构 MTCNN算法是一种基于深度学习的人脸检测和人脸对齐方法,它可以同时完成人脸检测和人脸对齐的任务,相比于传统的算法,它的性能更好,检测速度更快. MTCNN算法包含三个子网络: ...
- 人工智能Java SDK:人脸检测,应用于包括人脸门禁系统、刷脸支付等各行各业
人脸检测SDK 人脸识别 广义的人脸识别实际包括构建人脸识别系统的一系列相关技术,包括人脸图像采集.人脸定位.人脸识别预处理.身份确认以及身份查找等: 而狭义的人脸识别特指通过人脸进行身份确认或者身份 ...
- android关闭人脸检测功能,【Android知识】录像预览模式下打开人脸检测
开发的一款高通平台Android 9.0基于Camera2实现的预览界面通过侧键实现拍照,录像等功能的应用中,预览界面默认是采用的原生的VideoModule.java界面实现,测试发现设置中开启人脸 ...
- android 人脸识别边框_在Android实现人脸识别的详细过程
照相时,在预览画面上提示用户人脸的位置,并完成自动对焦等,是个错的应用; 下面是实现细节 我们知道在android的代码中已有人脸识别的底层算法代码,而且在framework层也封了调用的API函数 ...
- 【机器学习】最容易实现的基于OpenCV的人脸检测代码、检测器及检测效果
基于opencv自带的人脸检测模型,实现简单的人脸检测功能,可作为机器学习初学者练手使用.简单易学,具体的方法及代码如下. 1.运行结果 输入原图 输出结果 2.工程需要加载的opencv库如下: 3 ...
- python人脸检测代码_python实现人脸识别代码
从实时视频流中识别出人脸区域,从原理上看,其依然属于机器学习的领域之一,本质上与谷歌利用深度学习识别出猫没有什么区别.程序通过大量的人脸图片数据进行训练,利用数学算法建立建立可靠的人脸特征模型,如此即 ...
- python人脸检测代码_如何用不到25行Python代码实现人脸检测
本文我们会讲讲怎样利用不到 25 行 Python 代码和开源库 OpenCV,以很简单的方式实现人脸识别. 在正式开始前,先提以下两点小小的建议:先别急着跳到代码部分,最好在前文理解一下代码是干什么 ...
最新文章
- delphi与java 类型转换_java中的数据类型转换
- linux usb驱动
- python就业方向有哪些-Python如何零基础入门?就业方向有哪些?
- LeetCode Linked List Cycle II
- 可靠性测试设备技术含量_电子产品可靠性测试及设备
- DataSnap 2009 系列之二 (方法篇)
- linux 内存被修改,linux 查询内存(linux 修改 openfiles)
- Android ListView避免多线程加载一个同一资源
- mysql索引的增删_mysql索引的增删改查怎么实现?
- 如何在 CentOS 中设置 NTP 服务器
- shell开启飞行模式_手机飞行模式有什么用 手机飞行模式介绍【详解】
- android 透明度_Android智能视图翻转器
- 无人机可能又闯祸了:这次导致美国一架直升机坠毁
- 重磅!原清华副校长任职南科大校长:他考研三次,读博七年,想做科研人偶像...
- macOS Big Sur 11.6.5 (20G527) Boot ISO 原版可引导镜像
- 2、解读中台 -- 中台的作用
- 怎么用Python测网速?
- it人成功的六大步骤
- 水星路由器短信认证配置流程
- 航顺HK HK32F103CBT6 MCU