Android 集成Face++ 人脸识别(3.0+SDK)

news/2024/10/18 20:20:16/

写在前面

                    最近项目需求需要输入用户真实姓名 身份证号 再去调用人脸识别 效验是否是本人 所以就首先关注了Face++(旷视)的人脸识别,听说是 正确率很高.....所以就集成了.

 

1.首先去官网去创建应用(其实听说创建应用是比较麻烦的)

 

创建好应用以后需要上传你项目的包名

 

2.下载Demo Demo中会有一个扫描身份证的SDK和人脸识别的SDK 我这个需求呢是人脸识别 所以只集成人脸识别(如下图)

 

 

您可以按照您项目的需求集成不同的SDK(这里只集成人脸识别SDK)

 

3.上面的俩个文件夹都有扫描身份证和人脸识别的Demo

建议您,先把申请应用完以后的AppKey 和secret 配置到Face++的Demo中 跑完这个流程

 

4.开始我们的步骤

 

5.Face++给的Demo中 就会有 我们今天需要集成的SDK(如下图)

 

点击sdk文件夹

 

 

6.我们需要把meglive_still.aar 导入到 lib文件夹中

 

并在app下 build.gradle文件下 dependencies中写入

implementation(name: 'meglive_still', ext: 'aar')

 

在repositories中写入

flatDir { dirs 'libs' }

7.上代码

 

(1)需要调用人脸识别的Activity

private static final int CAMERA_PERMISSION_REQUEST_CODE = 100;
private static final int EXTERNAL_STORAGE_REQ_WRITE_EXTERNAL_STORAGE_CODE = 101;
private ProgressDialog mProgressDialog;
private MegLiveManager megLiveManager;
private static final String GET_BIZTOKEN_URL = "https://api.megvii.com/faceid/v3/sdk/get_biz_token"; //Face++获取BizToken的url
private static final String VERIFY_URL = "https://api.megvii.com/faceid/v3/sdk/verify";   //Face++人脸效验的url
private static final String API_KEY = "您的AppKey";
private static final String SECRET = "您的Secret";
private String sign = "";
private static final String SIGN_VERSION = "hmac_sha1";
private byte[] imageRef;//底库图片
private int buttonType;

 

private void init() {megLiveManager=MegLiveManager.getInstance();mProgressDialog = new ProgressDialog(this);mProgressDialog.setCancelable(false);long currtTime = System.currentTimeMillis() / 1000;long expireTime = (System.currentTimeMillis() + 60 * 60 * 100) / 1000;sign = GenerateSign.appSign(API_KEY, SECRET, currtTime, expireTime);requestCameraPerm();}

 

 

 

//获取BizToken的请求

private void getBizToken(String livenessType, int comparisonType, String idcardName, String idcardNum, String uuid, byte[] image) {mProgressDialog.show();HttpRequestManager.getInstance().getBizToken(this, GET_BIZTOKEN_URL, sign, SIGN_VERSION, livenessType, comparisonType, idcardName, idcardNum, uuid, image, new HttpRequestCallBack() {@Overridepublic void onSuccess(String responseBody) {try {JSONObject json = new JSONObject(responseBody);String bizToken = json.optString("biz_token");megLiveManager.preDetect(FaceIdActivity.this, bizToken,FaceIdActivity.this);} catch (JSONException e) {e.printStackTrace();}}@Overridepublic void onFailure(int statusCode, byte[] responseBody) {}});}
@Override
public void onDetectFinish(String token, int errorCode, String errorMessage, String data) {if (errorCode == 1000) {verify(token, data.getBytes());}
}

 

@Override
public void onPreStart() {showDialogDismiss();
}@Override
public void onPreFinish(String token, int errorCode, String errorMessage) {progressDialogDismiss();if (errorCode == 1000) {megLiveManager.startDetect(this);}
}//人脸识别的url
private void verify(String token, byte[] data) {showDialogDismiss();HttpRequestManager.getInstance().verify(this, VERIFY_URL, sign, SIGN_VERSION, token, data, new HttpRequestCallBack() {@Overridepublic void onSuccess(String responseBody) {Log.w("result", responseBody);progressDialogDismiss();gotoActivity(mContext,FaceIdVerifySuccessActivity.class,null);}@Overridepublic void onFailure(int statusCode, byte[] responseBody) {Log.w("result", new String(responseBody));progressDialogDismiss();gotoActivity(mContext,FaceIdVerifyErrorActivity.class,null);}});
}private void progressDialogDismiss() {runOnUiThread(new Runnable() {@Overridepublic void run() {if (mProgressDialog != null) {mProgressDialog.dismiss();}}});
}private void showDialogDismiss() {runOnUiThread(new Runnable() {@Overridepublic void run() {if (mProgressDialog != null) {mProgressDialog.show();}}});}private void requestCameraPerm() {if (android.os.Build.VERSION.SDK_INT >= M) {if (checkSelfPermission(Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED) {//进行权限请求requestPermissions(new String[]{Manifest.permission.CAMERA},CAMERA_PERMISSION_REQUEST_CODE);} else {requestWriteExternalPerm();}} else {beginDetect();}
}private void requestWriteExternalPerm() {if (android.os.Build.VERSION.SDK_INT >= M) {if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {//进行权限请求requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},EXTERNAL_STORAGE_REQ_WRITE_EXTERNAL_STORAGE_CODE);} else {beginDetect();}} else {beginDetect();  
 
    }
}private void beginDetect() {getBizToken("meglive", 1, "您的真实姓名", "您的身份证号", UUID.randomUUID().toString(), null);
}@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {if (requestCode == CAMERA_PERMISSION_REQUEST_CODE) {if (grantResults.length < 1 || grantResults[0] != PackageManager.PERMISSION_GRANTED) {//拒绝了权限申请} else {requestWriteExternalPerm();}} else if (requestCode == EXTERNAL_STORAGE_REQ_WRITE_EXTERNAL_STORAGE_CODE) {if (grantResults.length < 1 || grantResults[0] != PackageManager.PERMISSION_GRANTED) {//拒绝了权限申请} else {beginDetect();}}
}

(2) CV代码出来的错误

您的人脸识别的Activity需要实现  implements DetectCallback, PreCallback

 

(3)GenerateSign.java

 

public class GenerateSign {public static String appSign(String apiKey, String secret, long currtTime,long expireTime) {try {int rdm = Math.abs(new Random().nextInt());String plainText = String.format("a=%s&b=%d&c=%d&d=%d", apiKey, expireTime, currtTime,rdm);byte[] hmacDigest = HmacSha1(plainText, secret);byte[] signContent = new byte[hmacDigest.length + plainText.getBytes().length];System.arraycopy(hmacDigest, 0, signContent, 0, hmacDigest.length);System.arraycopy(plainText.getBytes(), 0, signContent, hmacDigest.length,plainText.getBytes().length);return Base64Encode(signContent).replaceAll("[\\s*\t\n\r]", "");} catch (Exception e) {e.printStackTrace();}return null;}/*** 生成base64编码** @param binaryData* @return*/public static String Base64Encode(byte[] binaryData) {String encodedstr = Base64.encodeToString(binaryData,Base64.DEFAULT);return encodedstr;}/*** 生成hmacsha1签名** @param binaryData* @param key* @return* @throws Exception*/public static byte[] HmacSha1(byte[] binaryData, String key) throws Exception {Mac mac = Mac.getInstance("HmacSHA1");SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "HmacSHA1");mac.init(secretKey);byte[] HmacSha1Digest = mac.doFinal(binaryData);return HmacSha1Digest;}/*** 生成hmacsha1签名** @param plainText* @param key* @return* @throws Exception*/public static byte[] HmacSha1(String plainText, String key) throws Exception {return HmacSha1(plainText.getBytes(), key);}
}
(4)HttpRequestCallBack
public interface HttpRequestCallBack {void onSuccess(String responseBody);void onFailure(int statusCode, byte[] responseBody);
}

(5)HttpRequestManager.java

public class HttpRequestManager {public final static int TIMEOUT = 10000;private static HttpRequestManager instance;public static HttpRequestManager getInstance() {if (instance == null) {instance = new HttpRequestManager();}return instance;}public void verify(Context context,String url,String sign,String signVersion,String bizToken,byte[] megLiveData,HttpRequestCallBack listener){MultipartEntity entity = new MultipartEntity();entity.addStringPart("sign",sign);entity.addStringPart("sign_version",signVersion);entity.addStringPart("biz_token",bizToken);entity.addBinaryPart("meglive_data",megLiveData);sendMultipartRequest(context,url,entity,new HashMap<String, String>(),listener);}public void getBizToken(Context context,String url,String sign,String signVersoin,String livenessType,int comparisonType,String idcardName,String idcardNum,String uuid,byte[] image_ref1,HttpRequestCallBack listener){MultipartEntity entity = new MultipartEntity();entity.addStringPart("sign",sign);entity.addStringPart("sign_version", signVersoin);entity.addStringPart("liveness_type", livenessType);entity.addStringPart("comparison_type", ""+comparisonType);if (comparisonType==1){entity.addStringPart("idcard_name", idcardName);entity.addStringPart("idcard_number", idcardNum);}else if (comparisonType==0){entity.addStringPart("uuid", uuid);entity.addBinaryPart("image_ref1", image_ref1);}sendMultipartRequest(context,url,entity,new HashMap<String, String>(),listener);}private void sendPostRequest(Context context, String url, final Map<String, String> params, final Map<String, String> header, final HttpRequestCallBack listener) {StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {@Overridepublic void onResponse(String response) {if (listener != null)listener.onSuccess(response);}}, new Response.ErrorListener() {@Overridepublic void onErrorResponse(VolleyError error) {if (error == null) {if (listener != null)listener.onFailure(-1, "timeout exception".getBytes());} else if (error.networkResponse == null) {if (listener != null)listener.onFailure(-1, "timeout exception".getBytes());} else {if (listener != null)listener.onFailure(error.networkResponse.statusCode, error.networkResponse.data);}}}) {@Overrideprotected Map<String, String> getParams() throws AuthFailureError {return params;}@Overridepublic Map<String, String> getHeaders() throws AuthFailureError {return header;}};VolleyHelper.getInstance(context).addToRequestQueue(request);}private void sendGetRequest(Context context, String url, final Map<String, String> header, final HttpRequestCallBack listener) {StringRequest request = new StringRequest(url, new Response.Listener<String>() {@Overridepublic void onResponse(String response) {listener.onSuccess(response);}}, new Response.ErrorListener() {@Overridepublic void onErrorResponse(VolleyError error) {if (error == null) {listener.onFailure(-1, "timeout exception".getBytes());} else if (error.networkResponse == null) {listener.onFailure(-1, "timeout exception".getBytes());} else {listener.onFailure(error.networkResponse.statusCode, error.networkResponse.data);}}}) {@Overridepublic Map<String, String> getHeaders() throws AuthFailureError {return header;}};VolleyHelper.getInstance(context).addToRequestQueue(request);}private void sendMultipartRequest(Context context, String url, MultipartEntity mult, final Map<String, String> header, final HttpRequestCallBack listener) {MultipartRequest multipartRequest = new MultipartRequest(url, new Response.Listener<String>() {@Overridepublic void onResponse(String response) {listener.onSuccess(response);}}, new Response.ErrorListener() {@Overridepublic void onErrorResponse(VolleyError error) {if (error == null) {listener.onFailure(-1, "timeout exception".getBytes());} else if (error.networkResponse == null) {listener.onFailure(-1, "timeout exception".getBytes());} else {listener.onFailure(error.networkResponse.statusCode, error.networkResponse.data);}}}) {@Overridepublic Map<String, String> getHeaders() throws AuthFailureError {return header;}};// 通过MultipartEntity来设置参数multipartRequest.setmMultiPartEntity(mult);VolleyHelper.getInstance(context).addToRequestQueue(multipartRequest);}}
(6)MultipartEntity
public class MultipartEntity implements HttpEntity {private final static char[] MULTIPART_CHARS = "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();/*** 换行符*/private final String NEW_LINE_STR = "\r\n";private final String CONTENT_TYPE = "Content-Type: ";private final String CONTENT_DISPOSITION = "Content-Disposition: ";/*** 文本参数和字符集*/private final String TYPE_TEXT_CHARSET = "text/plain; charset=UTF-8";/*** 字节流参数*/private final String TYPE_OCTET_STREAM = "application/octet-stream";/*** 二进制参数*/private final byte[] BINARY_ENCODING = "Content-Transfer-Encoding: binary\r\n\r\n".getBytes();/*** 文本参数*/private final byte[] BIT_ENCODING = "Content-Transfer-Encoding: 8bit\r\n\r\n".getBytes();/*** 分隔符*/private String mBoundary = null;/*** 输出流*/ByteArrayOutputStream mOutputStream = new ByteArrayOutputStream();public MultipartEntity() {this.mBoundary = generateBoundary();}/*** 生成分隔符** @return*/private final String generateBoundary() {final StringBuffer buf = new StringBuffer();final Random rand = new Random();for (int i = 0; i < 30; i++) {buf.append(MULTIPART_CHARS[rand.nextInt(MULTIPART_CHARS.length)]);}return buf.toString();}/*** 参数开头的分隔符** @throws IOException*/private void writeFirstBoundary() throws IOException {mOutputStream.write(("--" + mBoundary + "\r\n").getBytes());}/*** 添加文本参数** @param paramName* @param value*/public void addStringPart(final String paramName, final String value) {writeToOutputStream(paramName, value.getBytes(), TYPE_TEXT_CHARSET, BIT_ENCODING, "");}/*** 将数据写入到输出流中** @param paramName* @param rawData* @param type* @param encodingBytes* @param fileName*/private void writeToOutputStream(String paramName, byte[] rawData, String type,byte[] encodingBytes,String fileName) {try {writeFirstBoundary();mOutputStream.write((CONTENT_TYPE + type + NEW_LINE_STR).getBytes());mOutputStream.write(getContentDispositionBytes(paramName, fileName));mOutputStream.write(encodingBytes);mOutputStream.write(rawData);mOutputStream.write(NEW_LINE_STR.getBytes());} catch (final IOException e) {e.printStackTrace();}}/*** 添加二进制参数, 例如Bitmap的字节流参数** @param paramName* @param rawData*/public void addBinaryPart(String paramName, final byte[] rawData) {writeToOutputStream(paramName, rawData, TYPE_OCTET_STREAM, BINARY_ENCODING,paramName);}/*** 添加文件参数,可以实现文件上传功能** @param key* @param file*/public void addFilePart(final String key, final File file) {InputStream fin = null;try {fin = new FileInputStream(file);writeFirstBoundary();final String type = CONTENT_TYPE + TYPE_OCTET_STREAM + NEW_LINE_STR;mOutputStream.write(getContentDispositionBytes(key, file.getName()));mOutputStream.write(type.getBytes());mOutputStream.write(BINARY_ENCODING);final byte[] tmp = new byte[4096];int len = 0;while ((len = fin.read(tmp)) != -1) {mOutputStream.write(tmp, 0, len);}mOutputStream.flush();} catch (final IOException e) {e.printStackTrace();} finally {closeSilently(fin);}}private void closeSilently(Closeable closeable) {try {if (closeable != null) {closeable.close();}} catch (final IOException e) {e.printStackTrace();}}private byte[] getContentDispositionBytes(String paramName, String fileName) {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append(CONTENT_DISPOSITION + "form-data; name=\"" + paramName + "\"");// 文本参数没有filename参数,设置为空即可  if (fileName != null && !"".equals(fileName)) {stringBuilder.append("; filename=\""+ fileName + "\"");}return stringBuilder.append(NEW_LINE_STR).toString().getBytes();}@Overridepublic long getContentLength() {return mOutputStream.toByteArray().length;}@Overridepublic Header getContentType() {return new BasicHeader("Content-Type", "multipart/form-data; boundary=" + mBoundary);}@Overridepublic boolean isChunked() {return false;}@Overridepublic boolean isRepeatable() {return false;}@Overridepublic boolean isStreaming() {return false;}@Overridepublic void writeTo(final OutputStream outstream) throws IOException {// 参数最末尾的结束符  final String endString = "--" + mBoundary + "--\r\n";// 写入结束符  mOutputStream.write(endString.getBytes());//  outstream.write(mOutputStream.toByteArray());}@Overridepublic Header getContentEncoding() {return null;}@Overridepublic void consumeContent() throws IOException,UnsupportedOperationException {if (isStreaming()) {throw new UnsupportedOperationException("Streaming entity does not implement #consumeContent()");}}@Overridepublic InputStream getContent() {return new ByteArrayInputStream(mOutputStream.toByteArray());}
}  
(7)MultipartRequest
public class MultipartRequest extends Request<String> {private MultipartEntity mMultiPartEntity;private Map<String, String> mHeaders = new HashMap<String, String>();private final Response.Listener<String> mListener;/*** Creates a new request with the given url.** @param url      URL to fetch the string at* @param listener Listener to receive the String response*/public MultipartRequest(String url, Response.Listener<String> listener) {this(url, listener, null);}/*** Creates a new POST request.** @param url           URL to fetch the string at* @param listener      Listener to receive the String response* @param errorListener Error listener, or null to ignore errors*/public MultipartRequest(String url, Response.Listener<String> listener, Response.ErrorListener errorListener) {super(Method.POST, url, errorListener);mListener = listener;}/*** @return*/public MultipartEntity getMultiPartEntity() {if (mMultiPartEntity == null) {mMultiPartEntity = new MultipartEntity();}return mMultiPartEntity;}public void setmMultiPartEntity(MultipartEntity mMultiPartEntity) {this.mMultiPartEntity = mMultiPartEntity;}@Overridepublic String getBodyContentType() {return mMultiPartEntity.getContentType().getValue();}public void addHeader(String key, String value) {mHeaders.put(key, value);}@Overridepublic Map<String, String> getHeaders() throws AuthFailureError {return mHeaders;}@Overridepublic byte[] getBody() {ByteArrayOutputStream bos = new ByteArrayOutputStream();try {// multipart body  mMultiPartEntity.writeTo(bos);} catch (IOException e) {Log.e("", "IOException writing to ByteArrayOutputStream");}return bos.toByteArray();}@Overrideprotected Response<String> parseNetworkResponse(NetworkResponse response) {String parsed = "";try {parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));} catch (UnsupportedEncodingException e) {parsed = new String(response.data);}return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));}@Overrideprotected void deliverResponse(String response) {if (mListener != null) {mListener.onResponse(response);}}}
(8)VolleyHelper   
public class VolleyHelper {private static VolleyHelper mInstance;private RequestQueue mRequestQueue;private static Context mCtx;private VolleyHelper(Context context) {mCtx = context;mRequestQueue = getRequestQueue();}public static synchronized VolleyHelper getInstance(Context context) {if (mInstance == null) {mInstance = new VolleyHelper(context);}return mInstance;}public RequestQueue getRequestQueue() {   if (mRequestQueue == null) {// getApplicationContext() is key, it keeps you from leaking the// Activity or BroadcastReceiver if someone passes one in.if (mCtx==null){return null;}mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());}return mRequestQueue; }public <T> boolean addToRequestQueue(Request<T> req) {if (getRequestQueue()==null){return false;}req.setRetryPolicy(new DefaultRetryPolicy(10000, 0, 1.0f));getRequestQueue().add(req);return true;}public void clearRequestQueue(){if (getRequestQueue()!=null){getRequestQueue().cancelAll(mCtx.getApplicationContext());}}}

8.您可能遇到的问题

(1)

现象:

Face++ 底层使用的是Volley网络请求 我使用的时候第一个错就是 Face++SDK中关于Volley的包 全部报错

解决: 在我们的项目中 重新导入 Volley 的依赖

implementation 'com.mcxiaoke.volley:library:1.0.19'

(2)Face++SDK并没有把相关识别的方法弄成API 在CV的时候务必CV完整

(3)Face++集成从看Demo到看文档 集成起来也是蛮顺利的 祝快快集成

 

(4)我看了关于Face++的博客 本质是 我们用户输入真实姓名和身份证号以后 Face++会调取身份证和我们的人脸进行比对

 

Face++ 集成就到这里了,希望能给您带来帮助。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


http://www.ppmy.cn/news/836841.html

相关文章

Android集成百度人脸识别(一)基础版SDK

首先Android Studio版本&#xff1a;3.2.0 1、注册百度账号并企业认证 2、创建应用生成API Key和Secret Key 3、下载对应的SDK&#xff08;下载SDK的时候需要新建授权&#xff09; 因为下载的时候需要选择授权文件&#xff08;授权文件包含包名和签名文件的MD5&#xff09; 如…

Android人脸与指纹识别

基础人脸识别模块 添加依赖 请添加基本依赖&#xff0c;不要添加 ktx 版本的依赖&#xff0c;因为他需要 API33 及以上才可以使用&#xff01; implementation androidx.biometric:biometric:1.1.0 人脸识别工具类 package com.zhiyiyi.bio.bioimport android.content.Conte…

Android人脸识别(已开源)

Android人脸识别&#xff08;已开源&#xff09; 见链接

Android自带人脸识别

前言 碰到项目需求要判断上传的图片里只能有一个人&#xff0c;就像到了人脸识别功能&#xff0c;网上查资料说需要用opencv等各种图像库&#xff0c;项目肯定不能接受&#xff0c;没想到Android很早就已经集成了人脸识别的功能&#xff0c;这里记录一下。 实现效果 实现接口…

Android人脸识别技术

Android人脸识别技术用到的底层库&#xff1a;android/external/neven/&#xff0c;framework 层&#xff1a;frameworks/base/media/java/android/media/FaceDetector.java。 java层接口的限制: 1、只能接受bitmap的数据。 2、只能识别出双眼睛距离不大于20像素的人脸。 3、只…

安卓人脸识别笔记

人脸识别的SDK来自虹软的人脸识别SDK&#xff0c;开源免费 虹软的官网 http://www.arcsoft.com.cn/ai/arcface.html faceDemo实现效果&#xff1a; 在项目实现过程中遇到的一些问题&#xff0c;记一下。 一、调用系统相机方法 这里使用FileProvider.getUriForFile();获取…

Android人脸识别

文章目录 Android自带的人脸识别API第三方提供大牛们的封装 Android自带的人脸识别API Android实现人脸识别可以通过google原生自带API实现&#xff0c;只能识别静态图片&#xff0c;缺点是精度不高&#xff0c;识别信息很少&#xff0c;只有眼睛的识别 栗子 在页面上放一个…

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

转载请注明作者及出处&#xff1a;https://www.jianshu.com/p/ca3a12bc4911 引言 人脸识别这件事想来早已经不新鲜&#xff0c;在 Android 中的应用也并不广泛&#xff0c;所以网上相关资料乏善可陈。但是在面对特殊的应用场景时&#xff0c;人脸识别的功能还是有一定的用处的…