转自:http://blog.csdn.net/feishixin/article/details/77718680

引言

人工智能时代快速来临,其中人脸识别是当前比较热门的技术,在国内也越来越多的运用,例如刷脸打卡,刷脸APP,身份识别,人脸门禁等。当前的人脸识别技术分为WEBAPI和SDK调用两种方式,WEBAPI需要实时联网,SDK调用可以离线使用。

Android作为一个比较广泛的平台,如何实现人脸识别功能呢。

本文章将以一个示例的形式介绍一下我在这方面的经验。

本次使用的虹软提供的人脸识别的SDK,此SDK也可根据不同应用场景设计,针对性强。包括人脸检测、人脸跟踪、人脸识别,即使在离线环境下也可正常运行。
虹软公司是一家具有硅谷背景的图像处理公司,除了人脸技术以外,还有多项图像及视频处理技术。他们的双摄像头处理算法和人脸美化算法囊括了包括OPPO VIVO,SUMAMNG一系列手机厂商。

项目的目标

我们需要实现一个人脸识别功能。简单来说,就是机的后置摄像头,识别摄像头中实时拍到的人脸信息,如果人库注册过,则显示识别后的人脸信息,如登记的名字;如果不在,提示未注册。
这个功能具有多个应用场景,比如,火车站或者打卡和门禁系统中。

人脸识别的过程

人脸识别包括两个必备的过程,人脸注册和实时识别。
人脸注册是指把人脸的特征信息注册到人脸信息库中。人脸注册的来源可以有很多种,比如

国家身份证库

企业自建人脸识别库

互联网大数据库

人脸特征提取是一个不可逆的过程,你无法从人脸特征信息还原一个人的脸部照片。

在线库在使用时,需要传递照片信息,或者提取图像特征值,

离线的SDK相对安全,但是,在线的SDK通常提供更多的接入和调用方式,这个要结合实际情况来选择。

人脸注册和识别的过程可以用下面的图来表示。

准备工作

在开发之前需要到虹软的官网
http://www.arcsoft.com.cn/ai/arcface.html
下载用到的android库,下载的压缩包中有3个压缩包,如下图:

其中,第一个Face Detection,人脸检测。

人脸检测是人脸技术的基础,使用虹软人脸引擎,能够帮助您检测并且定位到影像(图片或者视频)中的人脸。

第二个Face Recognition,

人脸识别。引擎可独立运行在终端设备或者独立服务器中,应用端可独立完成算法运行,能保证用户数据的私密性,自主运营与保护用户敏感信息。
第三个Face Tracking,

人脸跟踪。精确定位并追踪面部区域位置,随着人物脸部位置的变化能够快速定位人脸位置,并且适用于不同表情、性别、年龄、姿态、光照等条件。

这三包的结构基本相同,我们需要把它们解压。
- doc 此目录中存放GUIDE文档,是说明文档,里面介绍了公开发布的一些API,并提供了示例代码。
- libs 开发中需要用到的库,需要把它们目录结构不变的全部引用到你的项目项目中。
- sampleCode 示例代码

注意:开发中还需要APP_Id和SDK_Key的激活码,这些激活码可以在账号管理–》您的申请记录,对应的下载应用中找到相应的激活码。

版本与环境要求

根据SDK的说明,我们使用的版本为android arm32,版本为5.0.我们使用的IDE为android studio,你也可以使用eclipse,不过依然建议你使用android studio,因为它现在已经是事实上的标准。

一步一步实现人脸识别功能

本文将以这三个库为基础,从人脸注册开始,到人脸识别结束。全程演示人脸识别的流程。如果你不想从头开始,你可以到https://github.com/asdfqwrasdf/ArcFaceDemo 下载完整的示例程序

新建项目

打开android studio,建立项目,API兼容性选择4.0。

导入依赖包

虹软人脸SDK的包是so包,你可以在下载的压缩包中把这些文件找到并导入。
导入后的工程文件夹如下所示。

定义并实现人脸库的相关功能

如前面所述,我们希望定义自己 的人脸库,人脸库在程序中使用List存储,在系统中保存为txt文件。

通过查询引擎,可以知道人脸信息是保存在AFR_FSDKFace类中的。这的主要结构为

  public static final int FEATURE_SIZE = 22020;byte[] mFeatureData;
  • 1
  • 2

如果要进行人脸注册,我们需要定义另外一个类来把人脸信息和姓名关联起来。

class FaceRegist {String mName;List<AFR_FSDKFace> mFaceList;public FaceRegist(String name) {mName = name;mFaceList = new ArrayList<>();}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

包含特征信息的长度和内容的byte数组。
我们把这些功能定义在类FaceDB中。FaceDB需要包含引擎定义,初始化,把人脸信息保存在版本库和从版本库中读出人脸信息这些功能

初始化引擎

为了程序结构性考虑,我们将人脸识别相关的代码独立出来一个类FaceDB,并定义必要的变量

public static String appid = "bCx99etK9Ns4Saou1EbFdC18xHdY9817EKw****";
public static String ft_key = "CopwZarSihp1VBu5AyGxfuLQdRMPyoGV2C2opc****";
public static String fd_key = "CopwZarSihp1VBu5AyGxfuLXnpccQbWAjd86S8****";
public static String fr_key = "CopwZarSihp1VBu5AyGxfuLexDsi8yyELdgsj4****";String mDBPath;
List<FaceRegist> mRegister;
AFR_FSDKEngine mFREngine;
AFR_FSDKVersion mFRVersion;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

定义有参数的构造函数来初始化引擎

public FaceDB(String path) {mDBPath = path;mRegister = new ArrayList<>();mFRVersion = new AFR_FSDKVersion();mUpgrade = false;mFREngine = new AFR_FSDKEngine();AFR_FSDKError error = mFREngine.AFR_FSDK_InitialEngine(FaceDB.appid, FaceDB.fr_key);if (error.getCode() != AFR_FSDKError.MOK) {Log.e(TAG, "AFR_FSDK_InitialEngine fail! error code :" + error.getCode());} else {mFREngine.AFR_FSDK_GetVersion(mFRVersion);Log.d(TAG, "AFR_FSDK_GetVersion=" + mFRVersion.toString());}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

定义析构函数释放引擎占用的系统资源

public void destroy() {if (mFREngine != null) {mFREngine.AFR_FSDK_UninitialEngine();}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

实现人脸增加和读取功能

通常人脸库会存放在数据库中,本次我们使用List来进行简单的模拟,并将其保存在文本文件中,需要时从文本中读取,保存时写入到文件中。

我们使用addFace方法将待注册的人脸信息添加到人脸库中

public  void addFace(String name, AFR_FSDKFace face) {try {//check if already registered.boolean add = true;for (FaceRegist frface : mRegister) {if (frface.mName.equals(name)) {frface.mFaceList.add(face);add = false;break;}}if (add) { // not registered.FaceRegist frface = new FaceRegist(name);frface.mFaceList.add(face);mRegister.add(frface);}if (!new File(mDBPath + "/face.txt").exists()) {if (!saveInfo()) {Log.e(TAG, "save fail!");}}//save nameFileOutputStream fs = new FileOutputStream(mDBPath + "/face.txt", true);ExtOutputStream bos = new ExtOutputStream(fs);bos.writeString(name);bos.close();fs.close();//save featurefs = new FileOutputStream(mDBPath + "/" + name + ".data", true);bos = new ExtOutputStream(fs);bos.writeBytes(face.getFeatureData());bos.close();fs.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
  • 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

使用loadFaces从文件中读取人脸

public boolean loadFaces(){if (loadInfo()) {try {for (FaceRegist face : mRegister) {Log.d(TAG, "load name:" + face.mName + "'s face feature data.");FileInputStream fs = new FileInputStream(mDBPath + "/" + face.mName + ".data");ExtInputStream bos = new ExtInputStream(fs);AFR_FSDKFace afr = null;do {if (afr != null) {if (mUpgrade) {//upgrade data.}face.mFaceList.add(afr);}afr = new AFR_FSDKFace();} while (bos.readBytes(afr.getFeatureData()));bos.close();fs.close();}return true;} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}} else {if (!saveInfo()) {Log.e(TAG, "save fail!");}}return false;}
  • 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

实现业务逻辑

实现人脸注册功能

人脸识别的前提条件就是人脸信息要先注册到人脸库中,注册人脸库

第一步当然是获取待注册的照片,我们可以可以使用摄像头,也可以使用照片。我们使用AlertDialog弹出选择框

new AlertDialog.Builder(this).setTitle("请选择注册方式").setIcon(android.R.drawable.ic_dialog_info).setItems(new String[]{"打开图片", "拍摄照片"}, this).show();
  • 1
  • 2
  • 3
  • 4
  • 5

在对应的事件处理函数中进行处理

switch (which){case 1://摄像头Intent getImageByCamera = new Intent("android.media.action.IMAGE_CAPTURE");ContentValues values = new ContentValues(1);values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");mPath = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);getImageByCamera.putExtra(MediaStore.EXTRA_OUTPUT, mPath);startActivityForResult(getImageByCamera, REQUEST_CODE_IMAGE_CAMERA);break;case 0://图片Intent getImageByalbum = new Intent(Intent.ACTION_GET_CONTENT);getImageByalbum.addCategory(Intent.CATEGORY_OPENABLE);getImageByalbum.setType("image/jpeg");startActivityForResult(getImageByalbum, REQUEST_CODE_IMAGE_OP);break;default:;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

获取一张照片后,后续我们就需要实现人脸检测功能。

    if (requestCode == REQUEST_CODE_IMAGE_OP && resultCode == RESULT_OK) {mPath = data.getData();String file = getPath(mPath);//TODO: add image coversion}
  • 1
  • 2
  • 3
  • 4
  • 5

在上面的代码中,我们获取到了我们需要的图像数据bmp,把图片取出来
我们在Application类用函数 decodeImage中实现这段代码

public static Bitmap decodeImage(String path) {Bitmap res;try {ExifInterface exif = new ExifInterface(path);int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);BitmapFactory.Options op = new BitmapFactory.Options();op.inSampleSize = 1;op.inJustDecodeBounds = false;//op.inMutable = true;res = BitmapFactory.decodeFile(path, op);//rotate and scale.Matrix matrix = new Matrix();if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {matrix.postRotate(90);} else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {matrix.postRotate(180);} else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {matrix.postRotate(270);}Bitmap temp = Bitmap.createBitmap(res, 0, 0, res.getWidth(), res.getHeight(), matrix, true);Log.d("com.arcsoft", "check target Image:" + temp.getWidth() + "X" + temp.getHeight());if (!temp.equals(res)) {res.recycle();}return temp;} catch (Exception e) {e.printStackTrace();}return null;}
  • 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

调用AFD_FSDK_StillImageFaceDetection返回检测到的人脸信息

人脸注册 ,首先要先检测出来人脸,对于静态图片,虹软人脸SDK中对应的是FD,提供了一个方法名称,叫AFD_FSDK_StillImageFaceDetection 。
我们来看一下参数列表

类型 名称 说明
byte[] data 输入的图像数据
int width 图像宽度
int height 图像高度
int format 图像格式
List list 检测到的人脸会放到到该列表里。

注意AFD_FSDKFace对象引擎内部重复使用,如需保存,请clone一份AFD_FSDKFace对象或另外保存

AFD_FSDKFace是人脸识别的结果,定义如下

public class AFD_FSDKFace {Rect mRect;int mDegree;}
  • 1
  • 2
  • 3
  • 4

mRect定义一个了一个矩形框Rect

在此之前我们需要注意虹软人脸SDK使用的图像格式是NV21的格式,所以我们需要将获取到的图像转化为对应的格式。在Android_extend.jar中提供了对应的转换函数

    byte[] data = new byte[mBitmap.getWidth() * mBitmap.getHeight() * 3 / 2];ImageConverter convert = new ImageConverter();convert.initial(mBitmap.getWidth(), mBitmap.getHeight(), ImageConverter.CP_PAF_NV21);if (convert.convert(mBitmap, data)) {Log.d(TAG, "convert ok!");}convert.destroy();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

现在我们就可以调用AFD_FSDK_StillImageFaceDetection方法了

err  = engine.AFD_FSDK_StillImageFaceDetection(data, mBitmap.getWidth(), mBitmap.getHeight(), AFD_FSDKEngine.CP_PAF_NV21, result);
  • 1
  • 2

绘出人脸框

在List中保存了检测到的人脸的位置信息和深度信息。
我们可以将检测到的人脸位置信息在图片上用一个矩形框绘制出来表示检测到的人脸信息。

Canvas canvas = mSurfaceHolder.lockCanvas();if (canvas != null) {Paint mPaint = new Paint();boolean fit_horizontal = canvas.getWidth() / (float)src.width() < canvas.getHeight() / (float)src.height() ? true : false;float scale = 1.0f;if (fit_horizontal) {scale = canvas.getWidth() / (float)src.width();dst.left = 0;dst.top = (canvas.getHeight() - (int)(src.height() * scale)) / 2;dst.right = dst.left + canvas.getWidth();dst.bottom = dst.top + (int)(src.height() * scale);} else {scale = canvas.getHeight() / (float)src.height();dst.left = (canvas.getWidth() - (int)(src.width() * scale)) / 2;dst.top = 0;dst.right = dst.left + (int)(src.width() * scale);dst.bottom = dst.top + canvas.getHeight();}canvas.drawBitmap(mBitmap, src, dst, mPaint);canvas.save();canvas.scale((float) dst.width() / (float) src.width(), (float) dst.height() / (float) src.height());canvas.translate(dst.left / scale, dst.top / scale);for (AFD_FSDKFace face : result) {mPaint.setColor(Color.RED);mPaint.setStrokeWidth(10.0f);mPaint.setStyle(Paint.Style.STROKE);canvas.drawRect(face.getRect(), mPaint);}canvas.restore();mSurfaceHolder.unlockCanvasAndPost(canvas);break;}
}
  • 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

将人脸注册到人脸库

检测到了人脸,我们可以输入相应的描述信息,加入到人脸库中。

为了提高识别的准确性,我们可以对一个人多次注册人脸信息。

public  void addFace(String name, AFR_FSDKFace face) {try {//check if already registered.boolean add = true;for (FaceRegist frface : mRegister) {if (frface.mName.equals(name)) {frface.mFaceList.add(face);add = false;break;}}if (add) { // not registered.FaceRegist frface = new FaceRegist(name);frface.mFaceList.add(face);mRegister.add(frface);}if (!new File(mDBPath + "/face.txt").exists()) {if (!saveInfo()) {Log.e(TAG, "save fail!");}}//save nameFileOutputStream fs = new FileOutputStream(mDBPath + "/face.txt", true);ExtOutputStream bos = new ExtOutputStream(fs);bos.writeString(name);bos.close();fs.close();//save featurefs = new FileOutputStream(mDBPath + "/" + name + ".data", true);bos = new ExtOutputStream(fs);bos.writeBytes(face.getFeatureData());bos.close();fs.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}
}
  • 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

最后,别忘记了销毁人脸检测引擎哦

err = engine.AFD_FSDK_UninitialFaceEngine();
Log.d("com.arcsoft", "AFD_FSDK_UninitialFaceEngine =" + err.getCode());
  • 1
  • 2
  • 3

实现人脸识别

上面的代码准备完毕后,就可以开始我们的人脸识别的功能了。我们使用一个第三方的扩展库,ExtGLSurfaceView的扩展 库CameraGLSurfaceView,用ImageView和TextView显示检测到的人脸和相应的描述信息。

首先是定义layout。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent" ><com.guo.android_extend.widget.CameraSurfaceView
        android:id="@+id/surfaceView"android:layout_width="1dp"android:layout_height="1dp"/><com.guo.android_extend.widget.CameraGLSurfaceView
        android:id="@+id/glsurfaceView"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_centerInParent="true"/><ImageView
        android:id="@+id/imageView"android:layout_width="120dp"android:layout_height="120dp"android:layout_marginLeft="10dp"android:layout_marginTop="10dp"/><TextView
        android:id="@+id/textView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignLeft="@+id/imageView"android:layout_alignRight="@+id/imageView"android:layout_below="@+id/imageView"android:layout_marginTop="10dp"android:text="@string/app_name"android:textAlignment="center"/><TextView
        android:id="@+id/textView1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignLeft="@+id/imageView"android:layout_alignRight="@+id/imageView"android:layout_below="@+id/textView"android:layout_marginTop="10dp"android:text="@string/app_name"android:textAlignment="center"/>
</RelativeLayout>
  • 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

因为引擎需要的图像格式是NV21的,所以需要将摄像头中的图像格式预设置为NV21

public Camera setupCamera() {// TODO Auto-generated method stubmCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);try {Camera.Parameters parameters = mCamera.getParameters();parameters.setPreviewSize(mWidth, mHeight);parameters.setPreviewFormat(ImageFormat.NV21);for( Camera.Size size : parameters.getSupportedPreviewSizes()) {Log.d(TAG, "SIZE:" + size.width + "x" + size.height);}for( Integer format : parameters.getSupportedPreviewFormats()) {Log.d(TAG, "FORMAT:" + format);}List<int[]> fps = parameters.getSupportedPreviewFpsRange();for(int[] count : fps) {Log.d(TAG, "T:");for (int data : count) {Log.d(TAG, "V=" + data);}}mCamera.setParameters(parameters);} catch (Exception e) {e.printStackTrace();}if (mCamera != null) {mWidth = mCamera.getParameters().getPreviewSize().width;mHeight = mCamera.getParameters().getPreviewSize().height;}return mCamera;
}
  • 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

从摄像头识别人脸,需要使用FT库,FT库在人脸跟踪算法上对人脸检测部分进行了优化,是专门为视频处理而优化的库。

初始化人脸检测引擎(FT)

和FD一样,我们需要初始化人脸识别FT引擎。

Log.d(TAG, "AFT_FSDK_InitialFaceEngine =" + err.getCode());
err = engine.AFT_FSDK_GetVersion(version);
Log.d(TAG, "AFT_FSDK_GetVersion:" + version.toString() + "," + err.getCode());
  • 1
  • 2
  • 3
  • 4

在摄像头的预览事件处理函数中,先调用FT的人脸识函数函数,然后再调用FR中的人脸信息特征提取数函数。

AFT_FSDKError err = engine.AFT_FSDK_FaceFeatureDetect(data, width, height, AFT_FSDKEngine.CP_PAF_NV21, result);AFR_FSDKError error = engine.AFR_FSDK_ExtractFRFeature(mImageNV21, mWidth, mHeight, AFR_FSDKEngine.CP_PAF_NV21,mAFT_FSDKFace.getRect(), mAFT_FSDKFace.getDegree(), result);
  • 1
  • 2
  • 3
  • 4

这里面的result中保存了人脸特征信息。我们可以将其保存下来或下来并与系统中的其它信息进行对比。

AFR_FSDKMatching score = new AFR_FSDKMatching();
float max = 0.0f;
String name = null;
for (FaceDB.FaceRegist fr : mResgist) {for (AFR_FSDKFace face : fr.mFaceList) {error = engine.AFR_FSDK_FacePairMatching(result, face, score);Log.d(TAG,  "Score:" + score.getScore() + ", AFR_FSDK_FacePairMatching=" + error.getCode());if (max < score.getScore()) {max = score.getScore();name = fr.mName;}}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

当score的特征信息大于0.6时,我们就可以认为匹配到了人脸。显示人脸匹配信息。

上面的循环中,可以看到,是遍历了真个库进行寻找。我们的目的是为了演示,实际情况下,我们可以在找到一个匹配值比较高的人脸后,就跳出循环。

运行结果

我们来看一下运行的结果。
效果还不错吧。钟汉良帅哥一枚。

本文档中所有的代码都可以在https://github.com/asdfqwrasdf/ArcFaceDemo 下载。如果你需要寻找更多的人脸识别的demo,也可以到虹软的论坛中去寻找。
http://www.arcsoft.com.cn/bbs/forum.php?mod=forumdisplay&fid=45&page=1

附录:会遇到的问题及解决方案

如果你使用的是github中的示例,你可能会遇到下面的问题。

Plugin with id ‘com.android.application’ not found

直接从github上下载的源代码会有这个问题。

解决方案:打开 [项目文件夹]\app\build.gradle 文件

在文件末尾添加

buildscript {repositories {mavenCentral()}dependencies {classpath 'com.android.tools.build:gradle:1.0.0'}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

Failed to find build tools revision 25.0.0.2

这个主要是build 的版本和gradle中指定的版本不一致,按照提示下载或者修改版本指定就可以了。

android {compileSdkVersion 24buildToolsVersion "25.0.2"}
  • 1
  • 2
  • 3
  • 4

install_failed_no_maching_abis

下载的代码在gradle编译完成后,直接默认运行会出现这个错误。原因是由于使用了native libraries 。该native libraries 不支持当前的cpu的体系结构。
首先请检查是否导入了必要的so文件。一共需要导入四个.so文件。
另外,请确认使用是的真机调试。因为调用了摄像头,请使用真机调试。

后记

人脸识别是当前的热点技术,使用范围广,用户体验良好,对硬件的依赖低,不需要昂贵的传感器芯片。一个高清的摄像头就可以完成。以前的成本是人脸识别的SDK比较贵,但现在虹软的SDK免费之后,集成的成本就大大降低了。

Android人脸识别开发入门--基于虹软免费SDK实现相关推荐

  1. android 人脸识别 方法研究,基于Android平台的人脸识别技术研究

    摘要: 在计算机视觉与模式识别领域中,人脸检测与识别技术是一个非常热门的研究课题,同时也具备非常广阔的商业价值.在诸多的目标检测算法中,基于AdaBoost算法的目标检测方法具有检测速度快,检测效果好 ...

  2. android虹软人脸识别简书,基于虹软人脸识别API和Qt5的人脸识别

    测试和使用了虹软的人脸API在QT5环境下设计了一个简单的人脸识别软件,实现了对人脸的跟踪和人脸识别.摄像头的控制以及图像格式的转换使用了Opencv,图像显示使用的是QT5的Qimage控件.下面是 ...

  3. android人脸识别应用架构,基于Android平台人脸识别系统的设计与实现

    摘要: 伴随着社会信息化,自动化的发展,以及科技的进步,未来将是移动互联网的时 代,为适应移动互联网的发展智能化的小型移动终端将是未来的发展趋势.与此同时人们对信息的安全性要求不断的提高,高自动化和高 ...

  4. android人脸识别demo_C#开发实录:基于免费SDK实现人脸识别应用开发

    随着人脸识别技术应用范围不断扩展,如何在Windows C#上基于免费SDK实现人脸识别应用开发,正成为开发者们关心的话题之一. 对于该需求,我推荐虹软视觉开放平台的ArcFace 3.0,免费.离线 ...

  5. 基于android系统的人脸检测系统设计 论文,基于Android人脸识别系统设计与实现.doc...

    基于Android人脸识别系统设计与实现 基于Android人脸识别系统设计与实现 摘要:人脸识别是公共安全领域的研究重点.随着移动互联网的快速发展,移动式终端人脸识别应用日益广泛.探讨人脸识别在An ...

  6. Android 人脸识别了解一下 (上)

    转载请注明作者及出处:https://www.jianshu.com/p/ca3a12bc4911 引言 人脸识别这件事想来早已经不新鲜,在 Android 中的应用也并不广泛,所以网上相关资料乏善可 ...

  7. Python人脸识别——从入门到工程实践

    参考书籍:<Python人脸识别从入门到工程实践> 全书共8章: 第 1 章:介绍了人脸识别的基础知识和必备常识: 第 2~4 章:详细讲解了与人脸识别相关的数学.机器学习.计算机视觉.O ...

  8. 码农在使用人脸识别开发套件中的硬件主板如何调用底层接口步骤

    DLT-RK3288C人脸识别开发套件 是由深圳市宁远电子科技有限公司 自主研发推出,基于行业最小最薄的DLT-RK3288C 高性能人脸识别专用主板,融合百度AI 精准的离线人脸识别技术,集算法与软 ...

  9. Android人脸识别和证件识别

    Android人脸识别和证件识别 程帅 由于疫情原因,最近的大数据和人脸识别检测就进入了大家的视线.对于技术的爱好,我也试着做了一下人脸识别和证件识别. 人脸识别用的是虹软的人脸识别SDK,目前是免费 ...

最新文章

  1. rcnn 改进mask_李沐团队提出最强ResNet改进版,多项任务达到SOTA | 已开源
  2. 如何聚焦自己的研究方向?一个实例研究
  3. HTML5应用 + Cordova = 平台相关的混合应用
  4. Linux之定时任务补充
  5. Science子刊:喝酒脸红的人,患胃癌风险大增,他们都有同一个基因突变
  6. 信息学奥赛一本通(1082:求小数的某一位)
  7. JAVA并发编程的基础
  8. Java设计模式之代理(动态代理,静态代理)
  9. Chronometer控件实现的Android计时器
  10. linux下LAMP环境的搭配
  11. 【android自定义控件】LinearLayout定义ActionBar样式
  12. Excel2007快捷键大全
  13. R语言解决安装rgl包问题:ERROR: compilation failed for package ‘rgl‘
  14. deepin更新失败_更新失败
  15. 【数据库实验】镶嵌查询
  16. fastapi 大型应用_fastapi使用教程
  17. C/C++中,数组作为函数参数传入
  18. 论文写作学习之引言章节撰写(学习深度之眼课程笔记,侵删)
  19. C语言 指针数组和指向指针的指针
  20. macOS--使用Boot Camp安装双系统后win10下罗技鼠标蓝牙连接延迟(卡顿、不跟手)的解决办法

热门文章

  1. 从零开始学keras之使用 LSTM 生成文本
  2. windows绕开强制更新
  3. Java判断一个数是不是素数
  4. matlab求根的原程序,MATLAB求根程序求帮助
  5. php中文件读写总结,PHP中文件读写操作
  6. python模块request怎么安装_安装 request模块
  7. vue标签旋转_vue.js编写移动端页面,检测旋转屏幕,横竖屏。
  8. java 删除桌面快捷方式_能否在桌面创建快捷方式运行java程序?
  9. 基于Python的接口自动化unittest测试框架和ddt数据驱动详解
  10. 导致网站服务器负担过重,利用httpd.ini实现图片和文件的防盗链