android 人脸识别边框_Android实现简单的人脸识别
时间:2019-09-03
概述:人脸识别
Android实现简单的人脸识别,人脸检测(这里用的是科大讯飞的人脸识别),因此需要此库导入后,测试本代码:
private final static String TAG = MainActivity.class.getSimpleName();
private SurfaceView mPreviewSurface;//用于显示预览图像
private SurfaceView mFaceSurface;//用于绘制检测人脸的返回信息
private SurfaceHolder mSurfaceHolder;//纹理控制器
private ImageButton changeCamera;//切换摄像头按钮
private Camera mCamera;//摄像头对象
private int mCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;//设置为默认开启前置摄像头
// 默认设置640*480,截至目前也只是支持640*480
private int PREVIEW_WIDTH = 640;
private int PREVIEW_HEIGHT = 480;
// 预览帧数据存储数组和缓存数组
private byte[] nv21;
private byte[] buffer;
// 缩放矩阵
private Matrix mScaleMatrix = new Matrix();
// 加速度感应器,用于获取手机的朝向
private Accelerometer accelerometer;
private FaceDetector mFaceDetector;//调用讯飞的SDK来实现人脸识别
private boolean stop;//人脸检测开关
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SpeechUtility.createUtility(this, "appid=" + "5833f456"); //设置AppKey用于注册,AppID
initView();//初始化布局
initData();//初始化数据
requestPermission(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1000);
}
@Override
public void permissionSuccess(int requestCode) {
super.permissionSuccess(requestCode);
if (requestCode == 1000){
Toast.makeText(MainActivity.this,"获取文件写入权限成功!",Toast.LENGTH_SHORT).show();
}
if (requestCode == 2000){
openCamera();//打开摄像头
}
}
/**
* 用于显示摄像头拍摄到的图像
*/
private SurfaceHolder.Callback mPreviewCallback = new SurfaceHolder.Callback() {
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
closeCamera();//关闭摄像头,并释放资源
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
requestPermission(new String[]{Manifest.permission.CAMERA},2000);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mScaleMatrix.setScale(width / (float) PREVIEW_HEIGHT,
height / (float) PREVIEW_WIDTH);//设置缩放比例
}
};
/**
* 设置纹理尺寸
*/
private void setSurfaceSize() {
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int width = metrics.widthPixels;
int height = (int) (width * PREVIEW_WIDTH / (float) PREVIEW_HEIGHT);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(width, height);
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
mPreviewSurface.setLayoutParams(params);
}
/**
* 初始化数据
*/
private void initData(){
nv21 = new byte[PREVIEW_WIDTH * PREVIEW_HEIGHT * 2];
buffer = new byte[PREVIEW_WIDTH * PREVIEW_HEIGHT * 2];
accelerometer = new Accelerometer(this);
mFaceDetector = FaceDetector.createDetector(this, null);//实例化人脸检测对象
}
/**
* 初始化控件
*/
private void initView() {
mPreviewSurface = (SurfaceView) findViewById(R.id.preview);
mFaceSurface = (SurfaceView) findViewById(R.id.face);
changeCamera = (ImageButton) findViewById(R.id.change);
mPreviewSurface.getHolder().addCallback(mPreviewCallback);
mSurfaceHolder = mFaceSurface.getHolder();
mSurfaceHolder.setFormat(PixelFormat.TRANSPARENT);
mFaceSurface.setZOrderOnTop(true);
// 点击SurfaceView,切换摄相头
changeCamera.setOnClickListener(v -> {
// 只有一个摄相头,不支持切换
if (Camera.getNumberOfCameras() == 1) {
Toast.makeText(this, "只有后置摄像头,不能切换", Toast.LENGTH_SHORT).show();
return;
}
closeCamera();
if (Camera.CameraInfo.CAMERA_FACING_FRONT == mCameraId) {
mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
} else {
mCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
}
openCamera();
});
setSurfaceSize();
}
/**
* 打开摄像头
*/
private void openCamera() {
if (mCamera != null) {
return;
}
try {
mCamera = Camera.open(mCameraId);
if (Camera.CameraInfo.CAMERA_FACING_FRONT == mCameraId) {
Toast.makeText(this, "前置摄像头已开启,点击可切换", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this,"后置摄像头已开启,点击可切换",Toast.LENGTH_SHORT).show();
}
setCameraDisplayOrientation(this, mCameraId, mCamera);//设置摄像头的预览方向
} catch (Exception e) {
e.printStackTrace();
closeCamera();
return;
}
//获取摄像头参数对象
Camera.Parameters params = mCamera.getParameters();
//设置预览的格式
params.setPreviewFormat(ImageFormat.NV21);
//设置预览的分辨率,这里设置640*480,到目前为止只支持该分辨率的人脸检测
params.setPreviewSize(PREVIEW_WIDTH, PREVIEW_HEIGHT);
//给摄像头设置参数配置
mCamera.setParameters(params);
//给摄像头设置预览回到,这里使用的Lambda表达式代表的只有一个回调函数的匿名内部类
mCamera.setPreviewCallback((data, camera) -> System.arraycopy(data, 0, nv21, 0, data.length));
try {
mCamera.setPreviewDisplay(mPreviewSurface.getHolder());
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 释放摄像头资源
*/
private void closeCamera() {
if (null != mCamera) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
@Override
protected void onResume() {
super.onResume();
if (null != accelerometer) {
accelerometer.start();
}
stop = false;
new Thread(()->{
while (!stop) {
if (null == nv21) {
continue;
}
synchronized (nv21) {
System.arraycopy(nv21, 0, buffer, 0, nv21.length);
}
int direction = Accelerometer.getDirection();// 获取手机朝向
boolean frontCamera = (Camera.CameraInfo.CAMERA_FACING_FRONT == mCameraId);
if (frontCamera) {
direction = (4 - direction) % 4;// 0,1,2,3,4分别表示0,90,180,270和360度
}
String result = mFaceDetector.trackNV21(
buffer, PREVIEW_WIDTH, PREVIEW_HEIGHT, 1, direction);//获取人脸检测结果
FaceRect face = Result.result(result);//获取返回的数据
Log.e(TAG, "result:" + result);//输出检测结果,该结果为JSON数据
Canvas canvas =mSurfaceHolder.lockCanvas();//锁定画布用于绘制
if (null == canvas) {
continue;
}
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);//清除之前的绘制图像
canvas.setMatrix(mScaleMatrix);
if (face == null) {
mSurfaceHolder.unlockCanvasAndPost(canvas);
continue;
}
if (face != null) {
face.bound = DrawFaceRect.RotateDeg90(face.bound, PREVIEW_HEIGHT);//绘制人脸的区域
if (face.point != null) {//绘制脸上关键点
for (int i = 0; i < face.point.length; i++) {
face.point[i] = DrawFaceRect.RotateDeg90(face.point[i], PREVIEW_HEIGHT);
}
//绘制人脸检测的区域
DrawFaceRect.drawFaceRect(canvas, face, PREVIEW_WIDTH, frontCamera);
}
} else {
Log.e(TAG, "没有检测出人脸");
}
mSurfaceHolder.unlockCanvasAndPost(canvas);
}
}).start();
}
解析人脸返回结果:
FaceRect rect = null;
if (TextUtils.isEmpty(json)) {
return null;
}
try {
JSONObject joResult = new JSONObject(json);
JSONArray items = joResult.getJSONArray("face");//解析face数组
JSONObject position = items.getJSONObject(0).getJSONObject("position");
//获取人脸检测框数据
rect = new FaceRect();
rect.bound.left = position.getInt("left");//左边起始位置点
rect.bound.top = position.getInt("top");//上端起始位置点
rect.bound.right = position.getInt("right");//右边结束位置点
rect.bound.bottom = position.getInt("bottom");//下端结束位置点
// 提取关键点数据
JSONObject landmark = items.getJSONObject(0).getJSONObject("landmark");
int keyPoint = landmark.length();//人脸检测点数据
rect.point = new Point[keyPoint];//人脸检测点数组
Iterator it = landmark.keys();//使用迭代器解析人脸监测点数据
int point = 0;
while (it.hasNext()) {//检测点,的坐标
String key = (String) it.next();
JSONObject object = landmark.getJSONObject(key);
rect.point[point] = new Point(object.getInt("x"), object.getInt("y"));
point++;
}
} catch (JSONException e) {
e.printStackTrace();
}
return rect;
android 人脸识别边框_Android实现简单的人脸识别相关推荐
- android 弹窗有边框_Android 多种简单的弹出框样式设置代码
简介 这是一个基于AlertDialog和Dialog这两个类封装的多种弹出框样式,其中提供各种简单样式的弹出框使用说明.同时也可自定义弹出框. 特性 1.使用链式开发代码简洁明了 2.所有的弹出框样 ...
- android 人脸识别边框_android Arcface人脸识别框/人脸抓拍框/人脸追踪框
为什么要改? 先来看看sdk demo中提供的人脸框样式,这个框看上去并不是非常美观(个人觉得) 再看看下面这个框是不是就要顺眼一点 怎么换? 先来看看原始的画法: @Override public ...
- android 人脸识别边框_android自定义Arcface人脸识别框/人脸抓拍框/人脸追踪框
为什么要改? 先来看看sdk demo中提供的人脸框样式,这个框看上去并不是非常美观(个人觉得) 在这里插入图片描述 再看看下面这个框是不是就要顺眼一点 在这里插入图片描述 怎么换? 先来看看原始的画 ...
- 人脸识别手机端APK分享 | 极速体验人脸识别功能 创建一个简单的人脸识别手机APP程序
1.前言 虹软公司提供免费离线人脸识别,对于开发者提供了比较友好.完整的可配置demo.但是如需直接体验功能,还是要花一点时间去完成项目编译.配置等一系列工作,对于初学者.不怎么熟悉整个项目的人来说可 ...
- android绘制半圆弧线_android实现简单圆弧效果
最近项目完成就开始搞一些有用没用的东西,以前面试的时候有人问我那种圆弧效果怎么做,还问我翻牌效果,我只看过,没有做过,现在有空了,而且想到可能会用到就做个简单的 圆弧很简单,自定义个View,创建个P ...
- android 弹窗有边框_android中常用的弹出提示框
我们在平时做开发的时候,免不了会用到各种各样的对话框,相信有过其他平台开发经验的朋友都会知道,大部分的平台都只提供了几个最简单的实现,如果我们想实现自己特定需求的对话框,大家可能首先会想到,通过继承等 ...
- 关于Vuforia扫描识别图片,最简单的设置识别区域
因为需要做个Vuforia扫描并设置识别区域,查了一些资料发现网上并没太多介绍这块内容. 有看到一个帖子上给了两个解决方案,一个是图片裁剪,但是这个方法太烦了.还有个是遮罩不过因为Vuforia插件中 ...
- OCR识别缺点_常用的OCR文字识别软件有哪些_软件动态论坛
随着大家办公需求的增加,办公软件如雨后春笋般纷纷面世,旨在提高大家的工作效率,OCR文字识别软件便是不可缺少的办公软件之一.那么,有哪些专业又好用的OCR文字识别软件呢?小编来为大家推荐几款,以供参考 ...
- android 人脸识别边框_人脸框抠图如何实现
最近在尝试做一个人脸识别项目,在对比几款主流人脸识别SDK后,采用了虹软的Arcface SDK,因为它提供了免费版本,并且可以离线使用,接入难度也比较低.项目中有一个需求就是显示检测到的人脸,但是如 ...
- android 人脸识别边框_【技术分享】虹软人脸识别 - Android Camera实时人脸追踪画框适配...
在使用虹软人脸识别Android SDK的过程中 ,预览时一般都需要绘制人脸框,但是和PC平台相机应用不同,在Android平台相机进行应用开发还需要考虑前后置相机切换.设备横竖屏切换等情况,因此在人 ...
最新文章
- 广州Robotaxi铁三角又落地,文远知行商业化通行证摊牌
- java的内省有用么_JAVA中的内省使用
- 深度学习未来十大趋势
- mysql proxy读写分离实现_使用mysql-proxy实现读写分离
- Raft算法的Leader选举和日志复制过程
- 在 MyEclipse 中配置 tomcat
- SAP 开发陷阱一箩筐(05)——绘制屏幕时无法给单选按钮分组
- Softether软件原理分析
- 采用UltraISO软碟通制作Dos启动盘教程
- 小型oa服务器系统,大型、中小型企业OA系统实施差异对比
- RGB色彩,HSV色彩模式、灰度图,亮度,对比度,饱和度、图像平滑、降噪、锐化、增强
- 【推荐】泰坦尼克号乘客生存分析——用机器学习告诉你,如果你在当时的船上,有多大机率生还?
- 用c语言写出一个金字塔
- 导出带有表格的word文件时,换页自带表头,避免复杂的表格数行数计算
- 项管行知02--工作环境
- 在谷歌上安装倍速播放的插件video-speed-controller
- 如何无损放大图片?用这5个图片无损放大工具,图片方法也超高清
- Android软件开发之获取通讯录联系人信息
- 丰沛数_不足数_完全数
- Linux命令--tail
热门文章
- 21天学通C语言-学习笔记(6)
- 脚本录制软件python 按键精灵 tc_喜讯。tc也能录脚本了!录制鼠标键盘,tc脚本录制工具!!...
- 哈理工OJ 1184 早起一水(水题)
- 面试官:说说什么是 Java 内存模型(JMM)?
- NXP iMX8基于eIQ框架测试Machine Learning
- 『Asp.Net 组件』Asp.Net 服务器组件 内嵌CSS:将CSS封装到程序集中
- 微信信息轰炸【简易版】
- 算法导论(第三版)第一章习题答案
- 基于 attention 机制的 LSTM 神经网络 超短期负荷预测方法学习记录
- 天翼网关获取超级密码