最近公司项目用到了
人脸识别
,花了一天半搞出来了,现在总结以下供大家参考(用到的sdk均为百度提供)
http://ai.baidu.com/docs#/FaceSDK-Collect-WithLiveness-Android/top。
想要人脸识别正常逻辑应该为:人脸采集➡️人脸库创建➡️人脸识别等三大步骤,我们一个个来,但一定要先注册好百度AI智能平台账号。
1、人脸离线采集
-
1.1创建应用
登录上号➡️进入控制台➡️选择左侧人脸识别
点击创建应用
创建页面如下(按照步骤填写完就行)
- 1.2下载Android、Ios离线采集sdk
点击管理应用
点击应用名称
下载sdk
此时当你点击离线采集sdk管理时,会发现需要认证,大家直接企业认证一下就行,按部就班填写就可以,很简单,我就不做太多叙述了。
认证完成以后再次下载Android、Ios离线采集sdk,页面如下:
不管是ios还是Android都选择有动作活体版本sdk
-
1.3 下载license文件
安卓配置
安卓的license文件放在assets
文件,没有assets文件就自己创建个。
将刚刚下载的安卓离线采集sdk里面的
faceplatform
和
faceplatform-ui
文件放在安卓根目录,如下图。
在android/app/build.gradle下的dependencies中添加compile project(path: ':faceplatform-ui')
:
dependencies {
....
compile project(path: ':faceplatform-ui')
}
在Setting.gradle中添加:
include ':faceplatform-ui'
include ':faceplatform'
在AndroidManifest.xml中添加以下代码: 切记!!!所有标签不要重复!!!
标签下配置采界面:
将自己项目下android/app/src/main/res/values/styles.xml
里面的内容替换为以下内容:
在android/app/src/main/res/
下创建layout
文件夹➡️分别创建widget_face_dialog.xml、activity_settings.xml
- widget_face_dialog.xml代码如下
- activity_settings.xml代码如下
重点:倒入人脸采集封装模块:将整个baiduface
文件夹放在如下图的位置
整个
baiduface
文件下载地址:
链接: https://pan.baidu.com/s/1gBxPXJcrtnO2lCwfmTRftA
提取码:
pjwv
当把
baiduface
文件复制到自己项目内以后,在
baiduface
文件全局搜索
com.lelian
,将其更改为自己项目的包名,这点一定
不能忘记!!!!!!!!
接下来在MainApplication
文件内添加以下代码:
package com.lelian;
import android.app.Application;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;
import com.lelian.baiduface.module.BaiduFacePackage; // 添加此代码,同样将com.lelian改为自己的包名
import java.util.Arrays;
import java.util.List;
public class MainApplication extends Application implements ReactApplication {
private static final BaiduFacePackage baiduFacePackage = new BaiduFacePackage(); // 添加此代码,创建package实例
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List getPackages() {
return Arrays.asList(
new MainReactPackage(),
baiduFacePackage //添加此代码,注册 package
);
}
@Override
protected String getJSMainModuleName() {
return "index";
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
}
/**
* 添加此代码,获取人脸识别package实例
*/
public static BaiduFacePackage getBaiduFacePackage() {
return baiduFacePackage;
}
}
最后配置签名文件
1.生成签名Keystore文件,并将keystore签名文件放到android/app根目录下
keytool -genkey -v -keystore cuitao-android-release.keystore -alias cuitao-android-alias -keyalg RSA -keysize 2048 -validity 10000
2.在gradle.properties文件下增加常量标识
MYAPP_RELEASE_STORE_FILE=cuitao-android-release.keystore
MYAPP_RELEASE_KEY_ALIAS=cuitao-android-alias
MYAPP_RELEASE_STORE_PASSWORD=*****
MYAPP_RELEASE_KEY_PASSWORD=*****
3.在app的build.gradle下的增加如下配置
android {
…………省略其他配置
signingConfigs {
debug {
storeFile file(MYAPP_RELEASE_STORE_FILE)
storePassword MYAPP_RELEASE_STORE_PASSWORD
keyAlias MYAPP_RELEASE_KEY_ALIAS
keyPassword MYAPP_RELEASE_KEY_PASSWORD
}
release {
storeFile file(MYAPP_RELEASE_STORE_FILE)
storePassword MYAPP_RELEASE_STORE_PASSWORD
keyAlias MYAPP_RELEASE_KEY_ALIAS
keyPassword MYAPP_RELEASE_KEY_PASSWORD
}
}
buildTypes {
release {
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
signingConfig signingConfigs.release
debuggable false
jniDebuggable false
}
}
}
具体打包流程可以看下我的另外一篇文章:https://www.jianshu.com/p/6cb8a7b44902
IOS配置
用xcode将之前下载的ios离线采集sdk里面的FaceSDK文件里面的所有内容岛入到ios项目下面
用xcode将之前下载的ios离线采集sdk里面的FaceParameterConfig.h倒入到如下位置。
选择链接C++标准库。
如果没有使用pod管理第三方库的话,请在Build Setting >Linking > Other Linker Flags 上面加入 –ObjC 选项。如果用了pod请忽略,因为pod会自动添加上。
因为需要使用相机权限:所以编辑Info.plist文件,添加
Privacy- Camera Usage Description
的Key值,Value为使用相机时候的提示语,可以填写:『使用相机』。
将'biadufaceIOS'文件夹的内容放到以下指定位置:
下载链接:
https://pan.baidu.com/s/1kSVF6De-mTpW2Yr01l85ZA
提取码:
4u66
最后,再项目的 AppDelegate.m 文件中添加SDK的初始化代码 :
#import "IDLFaceSDK/IDLFaceSDK.h"
#import "FaceParameterConfig.h"
NSString* licensePath = [[NSBundle mainBundle] pathForResource:FACE_LICENSE_NAME ofType:FACE_LICENSE_SUFFIX];
NSAssert([[NSFileManager defaultManager] fileExistsAtPath:licensePath]
[[FaceSDKManager sharedInstance] setLicenseID:FACE_LICENSE_ID andLocalLicenceFile:licensePath];
NSLog(@"canWork = %d",[[FaceSDKManager sharedInstance] canWork]);
react-native使用:
import React, {Component} from 'react';
import {
StyleSheet,
Text,
View,
Image,
NativeModules,
NativeEventEmitter,
ScrollView,
Platform
} from 'react-native';
const FaceCheckHelper = NativeModules.PushFaceViewControllerModule;
const FaceCheckModules = Platform.select({
android: ()=> FaceCheckHelper,
ios: ()=> NativeModules.RNIOSExportJsToReact
})();
const NativeModule = new NativeEventEmitter(FaceCheckModules);
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
imagesArray : [] // 采集的人脸样本结果
};
}
componentDidMount() {
NativeModule.addListener('FaceCheckHelper', (data) => this.faceCheckCallback(data));
}
/**
* 人脸检测结果
*/
faceCheckCallback(data) {
this.setState({
text: Object.keys(data)
})
if (data.remindCode == 0){
let imagesArray = [];
let imagesName = Object.keys(data.images); // bestImage liveEye liveYaw liveMouth yawRight yawLeft pitchUp pitchDown
imagesName.map((info,index) =>{
let image = data.images[info]
if (Platform.OS === 'ios' && info === 'bestImage' && typeof(image) !== 'string') {
image = data.images.bestImage[0]
}
imagesArray.push(
{info}
)
console.log(image,'ssss')
})
this.setState({imagesArray})
} else if (data.remindCode == 36) {
alert('采集超时');
}
}
/**
* 检测参数配置
*/
liveness() {
let obj = {
//质量校验设置
'quality':{
'minFaceSize' : 200,// 设置最小检测人脸阈值 默认是200
'cropFaceSizeWidth' : 400,// 设置截取人脸图片大小 默认是 400
'occluThreshold' : 0.5,// 设置人脸遮挡阀值 默认是 0.5
'illumThreshold' : 40,// 设置亮度阀值 默认是 40
'blurThreshold' : 0.7,// 设置图像模糊阀值 默认是 0.7
'EulurAngleThrPitch' : 10,// 设置头部姿态角度 默认是 10
'EulurAngleThrYaw' : 10,// 设置头部姿态角度 默认是 10
'EulurAngleThrRoll' : 10,// 设置头部姿态角度 默认是 10
'isCheckQuality' : true,// 设置是否进行人脸图片质量检测 默认是 true
'conditionTimeout' : 10,// 设置超时时间 默认是 10
'notFaceThreshold' : 0.6,// 设置人脸检测精度阀值 默认是0.6
'maxCropImageNum' : 1,// 设置照片采集张数 默认是 1
},
'liveActionArray' :[
0, //眨眨眼
1, //张张嘴
2, //向右摇头
3, //向左摇头
4, //抬头
5, //低头
6, //摇头
], //活体动作列表
'order': true,//是否按顺序进行活体动作
'sound': false, // 提示音,默认不开启
};
// FaceCheckHelper.openPushFaceViewController( obj );
// 如果都不设置,需要传 {} 空对象, 建议设置 liveActionArray
FaceCheckHelper.openPushFaceViewController( {} );
}
render() {
return (
this.liveness()}>点击进入活体检测界面
{this.state.imagesArray}
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
// alignItems: 'center',
// justifyContent: 'center',
backgroundColor: '#F5FCFF',
},
buttons:{
color:'black',
fontSize:20,
marginTop:100,
},
});
2、人脸库创建
http://ai.baidu.com/docs#/Face-Set-V3/top
请求示例
HTTP方法:POST
请求URL: https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/add
URL参数:
参数 | 值 |
---|---|
access_token | 通过API Key和Secret Key获取的access_token,参考“Access Token获取” |
Header如下:
参数 | 值 |
---|---|
Content-Type | application/json |
Body中放置请求参数,参数详情如下:
请求参数
参数 | 必选 | 类型 | 说明 |
---|---|---|---|
image | 是 | string | 图片信息(总数据大小应小于10M),图片上传方式根据image_type来判断。 |
注:组内每个uid下的人脸图片数目上限为20张 | |||
image_type | 是 | string | 图片类型 |
BASE64:图片的base64值,base64编码后的图片数据,编码后的图片大小不超过2M;
URL:图片的 URL地址( 可能由于网络等原因导致下载图片时间过长);
FACE_TOKEN:人脸图片的唯一标识,调用人脸检测接口时,会为每个人脸图片赋予一个唯一的FACE_TOKEN,同一张图片多次检测得到的FACE_TOKEN是同一个。 |
| group_id | 是 | string | 用户组id,标识一组用户(由数字、字母、下划线组成),长度限制48B。产品建议:根据您的业务需求,可以将需要注册的用户,按照业务划分,分配到不同的group下,例如按照会员手机尾号作为groupid,用于刷脸支付、会员计费消费等,这样可以尽可能控制每个group下的用户数与人脸数,提升检索的准确率 |
| user_id | 是 | string | 用户id(由数字、字母、下划线组成),长度限制128B |
| user_info | 否 | string | 用户资料,长度限制256B 默认空 |
| quality_control | 否 | string | 图片质量控制
NONE: 不进行控制
LOW:较低的质量要求
NORMAL: 一般的质量要求
HIGH: 较高的质量要求
默认 NONE
若图片质量不满足要求,则返回结果中会提示质量检测失败 |
| liveness_control | 否 | string | 活体检测控制
NONE: 不进行控制
LOW:较低的活体要求(高通过率 低攻击拒绝率)
NORMAL: 一般的活体要求(平衡的攻击拒绝率, 通过率)
HIGH: 较高的活体要求(高攻击拒绝率 低通过率)
默认NONE
若活体检测结果不满足要求,则返回结果中会提示活体检测失败 |
| action_type | 否 | string | 操作方式
APPEND: 当user_id在库中已经存在时,对此user_id重复注册时,新注册的图片默认会追加到该user_id下
REPLACE : 当对此user_id重复注册时,则会用新图替换库中该user_id下所有图片
默认使用APPEND |
说明:人脸注册完毕后,生效时间一般为5s以内,之后便可以进行人脸搜索或认证操作。
请求代码示例
提示一:使用示例代码前,请记得替换其中的示例Token、图片地址或Base64信息。
提示二:部分语言依赖的类或库,请在代码注释中查看下载地址。
bash PHP Java Python C++ C#
人脸注册
curl -i -k 'https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/add?access_token=【调用鉴权接口获取的token】' --data '{"image":"027d8308a2ec665acb1bdf63e513bcb9","image_type":"FACE_TOKEN","group_id":"group_repeat","user_id":"user1","user_info":"abc","quality_control":"LOW","liveness_control":"NORMAL"}' -H 'Content-Type:application/json; charset=UTF-8'
返回说明
返回参数
字段 | 必选 | 类型 | 说明 |
---|---|---|---|
log_id | 是 | uint64 | 请求标识码,随机数,唯一 |
face_token | 是 | string | 人脸图片的唯一标识 |
location | 是 | array | 人脸在图片中的位置 |
+left | 是 | double | 人脸区域离左边界的距离 |
+top | 是 | double | 人脸区域离上边界的距离 |
+width | 是 | double | 人脸区域的宽度 |
+height | 是 | double | 人脸区域的高度 |
+rotation | 是 | int64 | 人脸框相对于竖直方向的顺时针旋转角,[-180,180] |
返回示例
{
"face_token": "2fa64a88a9d5118916f9a303782a97d3",
"location": {
"left": 117,
"top": 131,
"width": 172,
"height": 170,
"rotation": 4
}
}
3、人脸识别
http://ai.baidu.com/docs#/Face-Search-V3/top
请求示例
HTTP方法:POST
请求URL: https://aip.baidubce.com/rest/2.0/face/v3/multi-search
URL参数:
参数 | 值 |
---|---|
access_token | 通过API Key和Secret Key获取的access_token,参考“Access Token获取” |
Header如下:
参数 | 值 |
---|---|
Content-Type | application/json |
Body中放置请求参数,参数详情如下:
请求参数
参数 | 必选 | 类型 | 说明 |
---|---|---|---|
image | 是 | string | 图片信息(数据大小应小于10M) |
image_type | 是 | string | 图片类型 |
BASE64:图片的base64值;
URL:图片的 URL( 下载图片时可能由于网络原因导致下载图片时间过长)
FACE_TOKEN: face_token 人脸标识 |
| group_id_list | 是 | string | 从指定的group中进行查找 用逗号分隔,上限10个 |
| max_face_num | 否 | int | 最多处理人脸的数目
默认值为1(仅检测图片中面积最大的那个人脸) 最大值10 |
| match_threshold | 否 | int | 匹配阈值(设置阈值后,score低于此阈值的用户信息将不会返回) 最大100 最小0 默认80
此阈值设置得越高,检索速度将会越快,推荐使用默认阈值80
|
| quality_control | 否 | string | 质量控制(质量不符合要求的人脸不会出现在返回结果中)
NONE: 不进行控制
LOW:较低的质量要求
NORMAL: 一般的质量要求
HIGH: 较高的质量要求
默认NONE |
| liveness_control | 否 | string | 活体控制(活体分数不符合要求的人脸不会出现在返回结果中)
NONE: 不进行控制
LOW:较低的活体要求(高通过率 低攻击拒绝率)
NORMAL: 一般的活体要求(平衡的攻击拒绝率, 通过率)
HIGH: 较高的活体要求(高攻击拒绝率 低通过率)
默认NONE |
| max_user_num | 否 | unit32 | 识别返回的最大用户数,默认为1,最大50个 |
请求示例
{
"image": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKD...",
"image_type": "BASE64",
"group_id_list": "group1",
"max_face_num" : 5,
"quality_control": "LOW",
"liveness_control": "NORMAL"
}
返回说明
返回参数
字段 | 必选 | 类型 | 说明 |
---|---|---|---|
face_num | 是 | int | 图片中的人脸数量 |
face_list | 是 | array | 人脸信息列表 |
+face_token | 是 | string | 人脸标志 |
+location | 是 | array | 人脸在图片中的位置 |
++left | 是 | double | 人脸区域离左边界的距离 |
++top | 是 | double | 人脸区域离上边界的距离 |
++width | 是 | double | 人脸区域的宽度 |
++height | 是 | double | 人脸区域的高度 |
++rotation | 是 | int64 | 人脸框相对于竖直方向的顺时针旋转角,[-180,180] |
+user_list | 是 | array | 匹配的用户信息列表 |
++group_id | 是 | string | 用户所属的group_id |
++user_id | 是 | string | 用户的user_id |
++user_info | 是 | string | 注册用户时携带的user_info |
++score | 是 | float | 用户的匹配得分 |
80分以上可以判断为同一人,此分值对应万分之一误识率 |
返回示例
{
"error_code": 0,
"error_msg": "SUCCESS",
"log_id": 240483475,
"timestamp": 1535533440,
"cached": 0,
"result": {
"face_num": 2,
"face_list": [
{
"face_token": "6fe19a6ee0c4233db9b5bba4dc2b9233",
"location": {
"left": 31.95568085,
"top": 120.3764267,
"width": 87,
"height": 85,
"rotation": -5
},
"user_list": [
{
"group_id": "group1",
"user_id": "5abd24fd062e49bfa906b257ec40d284",
"user_info": "userinfo1",
"score": 69.85684967041
},
{
"group_id": "group1",
"user_id": "2abf89cffb31473a9948268fde9e1c3f",
"user_info": "userinfo2",
"score": 66.586112976074
}
]
},
{
"face_token": "fde61e9c074f48cf2bbb319e42634f41",
"location": {
"left": 219.4467773,
"top": 104.7486954,
"width": 81,
"height": 77,
"rotation": 3
},
"user_list": [
{
"group_id": "group1",
"user_id": "088717532b094c3990755e91250adf7d",
"user_info": "userinfo",
"score": 65.154159545898
}
]
}
]
}
}