Android 百度离线人脸识别小案例

妖狐艹你老母 2022-02-28 14:50 902阅读 0赞

步骤:

第一步:有账号直接登入百度云,没有接自己注册,地址https://login.bce.baidu.com/

第二步:登入上去以后,点击离线采集sdk管理,如果没有认证,先进行企业认证,只有企业认证了,才能进行下面的操作。

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1bnNoaW5lXzA3MDc_size_16_color_FFFFFF_t_70

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1bnNoaW5lXzA3MDc_size_16_color_FFFFFF_t_70 1 第三步:认证之后,下载sdk压缩包

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1bnNoaW5lXzA3MDc_size_16_color_FFFFFF_t_70 2

第四步:先将sdk导入到Android Studio ,运行sdk,得到设备指纹。然后选择联网或者这里离线激活方式,我这里选的是离线激活,按照离线激活方式的文档提供的步骤,完成离线激活,然后下载授权文件。

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1bnNoaW5lXzA3MDc_size_16_color_FFFFFF_t_70 3

第五步:将授权文件的压缩包,放到sdk提示的路径下,再输入序列号,点击离线激活。

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1bnNoaW5lXzA3MDc_size_16_color_FFFFFF_t_70 4

第六步:集成源码

  1. 1.facelibrary库添加到自己的工程中:
  2. 1`settings.gradle` 添加`‘:facelibrary’`
  3. 2app->build.gradle->dependencies->compile project(":facelibrary")。

2.自己选择需要的代码,添加到自己的项目里

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1bnNoaW5lXzA3MDc_size_16_color_FFFFFF_t_70 5

第七步:SDK的参数设置

1.SDK初始化,采用默认的参数进行初始化(在源码的的MainActivity的initSDK方法里,这里必须初始化好,如果没有初始化好,在后面抽取图片的特征的时候,会抽取不到,那就不能进行对比,所以处理这个,我们可以用个阻塞队列处理,让它们同步)

  1. private void initSDK() {
  2. FaceSDKManager.getInstance().init(this, new FaceSDKManager.SdkInitListener() {
  3. @Override
  4. public void initStart() {
  5. toast("sdk init start");
  6. }
  7. @Override
  8. public void initSuccess() {
  9. toast("sdk init success");
  10. if (FaceSDKManager.getInstance().initStatus() == FaceSDKManager.SDK_UNACTIVATION) {
  11. toast("SDK还未激活初始化,请先激活初始化");
  12. return;
  13. } else if (FaceSDKManager.getInstance().initStatus() == FaceSDKManager.SDK_INIT_FAIL) {
  14. toast("SDK初始化失败,请重新激活初始化");
  15. return;
  16. } else if (FaceSDKManager.getInstance().initStatus() == FaceSDKManager.SDK_INIT_SUCCESS) {
  17. toast("SDK正在加载模型,请稍后再试");
  18. return;
  19. } else if (FaceSDKManager.getInstance().initStatus() == FaceSDKManager.SDK_MODEL_LOAD_SUCCESS) {
  20. /* startActivity(new Intent(MainActivity.this, FaceIdCompareActivity.class));
  21. finish();*/
  22. }
  23. }
  24. @Override
  25. public void initFail(int errorCode, String msg) {
  26. toast("sdk init fail:" + msg);
  27. }
  28. });
  29. }

2.在FaceEnvironment里查看或者设置SDK全局配置信息

  1. public class FaceEnvironment {
  2. // SDK版本号
  3. public static final String VERSION = "2.0.0";
  4. public static final float LIVENESS_RGB_THRESHOLD = 0.8f;
  5. public static final float LIVENESS_IR_THRESHOLD = 0.8f;
  6. public static final float LIVENESS_DEPTH_THRESHOLD = 0.8f;
  7. public static boolean isFeatureDetect = false;
  8. private BDFaceSDKConfig config;
  9. /**
  10. * 最小人脸检测大小 建议50
  11. */
  12. public int minFaceSize;
  13. /**
  14. * 最大人脸检测大小 建议-1(不做限制)
  15. */
  16. public int maxFaceSize;
  17. /**
  18. * 人脸跟踪,检测的时间间隔 默认 500ms
  19. */
  20. public int trackInterval;
  21. /**
  22. * 人脸跟踪,跟踪时间间隔 默认 1000ms
  23. */
  24. public int detectInterval;
  25. /**
  26. * 人脸置信度阈值,建议值0.5
  27. */
  28. public float noFaceSize;
  29. /**
  30. * 人脸姿态角 pitch,yaw,roll
  31. */
  32. public int pitch;
  33. public int yaw;
  34. public int roll;
  35. /**
  36. * 质量检测模糊,遮挡,光照,默认不做质量检测
  37. */
  38. public boolean isCheckBlur;
  39. public boolean isOcclusion;
  40. public boolean isIllumination;
  41. /**
  42. * 检测图片类型,可见光或者红外
  43. */
  44. public FaceDetect.DetectType detectMethodType;
  45. public BDFaceSDKConfig getConfig() {
  46. if (config == null) {
  47. config = new BDFaceSDKConfig();
  48. setFaceConfig();
  49. } else {
  50. setFaceConfig();
  51. }
  52. return config;
  53. }
  54. private void setFaceConfig() {
  55. config.minFaceSize = getMinFaceSize();
  56. config.maxFaceSize = getMaxFaceSize();
  57. config.trackInterval = getTrackInterval();
  58. config.detectInterval = getDetectInterval();
  59. config.noFaceSize = getNoFaceSize();
  60. config.pitch = getPitch();
  61. config.yaw = getYaw();
  62. config.roll = getRoll();
  63. config.isCheckBlur = isCheckBlur;
  64. config.isOcclusion = isOcclusion;
  65. config.isIllumination = isIllumination;
  66. config.detectMethodType = getDetectMethodType();
  67. }
  68. 3.RgbVideoTrackActivity里设置质量参数(开启质量检测,性能会下降,可以选择不开启质量检测)
  69. /**
  70. * 质量筛选
  71. *
  72. * @param faceInfos
  73. * @param imageFrame
  74. */
  75. private void qualitySelect(FaceInfo[] faceInfos, ImageFrame imageFrame) {
  76. if (faceInfos == null || faceInfos.length == 0) {
  77. clearTip();
  78. return;
  79. }
  80. int qualityType = PreferencesUtil.getInt(TYPE_QUALITY, GlobalSet.TYPE_QUALITY_CLOSE);
  81. if (qualityType == GlobalSet.TYPE_QUALITY_CLOSE) {
  82. if (from == GlobalSet.TYPE_LIVING_SHOW) {
  83. featureIdenty(imageFrame, faceInfos);
  84. } else if (from == GlobalSet.TYPE_COLLECT_IMAGE) {
  85. faceCollect(imageFrame, faceInfos);
  86. }
  87. } else if (qualityType == GlobalSet.TYPE_QUALITY_OPEN) {
  88. float blurrValue = Float.parseFloat(PreferencesUtil.getString(TYPE_BLURR_THRESHOLD,
  89. String.valueOf(0.70)));
  90. float occlusionValue = Float.parseFloat(PreferencesUtil.getString(TYPE_OCCLUSION_THRESHOLD,
  91. String.valueOf(0.70)));
  92. float illuminateValue = Float.parseFloat(PreferencesUtil.getString(TYPE_ILLUMINATION_THRESHOLD,
  93. String.valueOf(40)));
  94. FaceInfo faceInfo = faceInfos[0];
  95. float[] occlu = faceInfo.occlu;
  96. if (occlu != null && occlu.length > 0) {
  97. float leftEye = occlu[0];
  98. float rightEye = occlu[1];
  99. float nose = occlu[2];
  100. float mouth = occlu[3];
  101. float lContour = occlu[4];
  102. float rContour = occlu[5];
  103. float chinContour = occlu[6];
  104. if ((faceInfo.blur < blurrValue) && (leftEye < occlusionValue) && (rightEye < occlusionValue)
  105. && (nose < occlusionValue) && (mouth < occlusionValue) && (lContour < occlusionValue)
  106. && (rContour < occlusionValue) && (chinContour < occlusionValue)
  107. && (faceInfo.illum > illuminateValue)) {
  108. if (from == GlobalSet.TYPE_LIVING_SHOW) {
  109. featureIdenty(imageFrame, faceInfos);
  110. } else if (from == GlobalSet.TYPE_COLLECT_IMAGE) {
  111. faceCollect(imageFrame, faceInfos);
  112. }
  113. } else {
  114. handler.post(new Runnable() {
  115. @Override
  116. public void run() {
  117. tvTopShowState.setText("人脸质量差");
  118. }
  119. });
  120. }
  121. } else {
  122. if (from == GlobalSet.TYPE_LIVING_SHOW) {
  123. featureIdenty(imageFrame, faceInfos);
  124. } else if (from == GlobalSet.TYPE_COLLECT_IMAGE) {
  125. faceCollect(imageFrame, faceInfos);
  126. }
  127. }
  128. }
  129. }

第八步:在FaceIdCompareActivity里选择图片和在RgbVideoTrackActivity视频里检测到图片对比

  1. 1.设置图片显示和完成图片的特征抽取
  2. try {
  3. final Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream( getImageContentUri(FaceIdCompareActivity.this, new File("/sdcard/faces/face.jpg"))));
  4. if (bitmap != null) {
  5. imgFirst.setImageBitmap(bitmap);
  6. if ((bitmap.getWidth() * bitmap.getHeight()) > pictureSize) {
  7. // 超过限制 缩放图片
  8. pictureResize(bitmap, 1);
  9. } else {
  10. syncFeature(bitmap, firstFeature, 1);
  11. }
  12. }
  13. } catch (Exception e) {
  14. e.printStackTrace();
  15. }

1.1 因为在源码的操作步骤和处理是,点击按钮,进入到系统相册选取界面,选择图片,返回图片的uri,因为我们这是文件路径,所以我们转换成uri getImageContentUri(FaceIdCompareActivity.this, new File(“/sdcard/faces/face.jpg”)))

1.2接下来是特征抽取,只有图片和视频检测到的图片的特征都抽取成功,才能进行接下来的识别。

  1. private void syncFeature(final Bitmap bitmap, final byte[] feature, final int index) {
  2. float ret = -1;
  3. ret = FaceApi.getInstance().extractIdPhotoFeature(bitmap, feature, 50);
  4. Log.i("wtf", "ret:" + ret);
  5. Log.d("firstFeatureFinished",index+".ret="+ret);
  6. if (ret == 128 && index == 1) {
  7. firstFeatureFinished = true;
  8. } else if (ret == 128 && index == 2) {
  9. secondFeatureFinished = true;
  10. }
  11. if (ret == 128) {
  12. toast("图片" + index + "特征抽取成功");
  13. } else if (ret == -100) {
  14. toast("未完成人脸比对,可能原因,图片1为空");
  15. } else if (ret == -101) {
  16. toast("未完成人脸比对,可能原因,图片2为空");
  17. } else if (ret == -102) {
  18. toast("未完成人脸比对,可能原因,图片1未检测到人脸");
  19. } else if (ret == -103) {
  20. toast("未完成人脸比对,可能原因,图片2未检测到人脸");
  21. } else {
  22. toast("未完成人脸比对,可能原因,"
  23. + "人脸太小(小于sdk初始化设置的最小检测人脸)"
  24. + "人脸不是朝上,sdk不能检测出人脸");
  25. }
  26. if(index==2 && ret == 128){ //这里是图片和视频检测的图片特征斗殴抽取成功后,直接调用match()方法,进行识别
  27. match();
  28. }
  29. }

2.把从RgbVideoTrackActivity视频里获取到的图片显示到控件上,并完成特征抽取。

2.1 在界面可见时,就开启摄像头预览

  1. @Override
  2. protected void onResume() {
  3. super.onResume();
  4. //摄像头预览
  5. startCameraPreview();
  6. }
  7. /**
  8. * 摄像头图像预览
  9. */
  10. private void startCameraPreview() {
  11. // 设置前置摄像头
  12. // Camera1PreviewManager.getInstance().setCameraFacing(Camera1PreviewManager.CAMERA_FACING_FRONT);
  13. // 设置后置摄像头
  14. // Camera1PreviewManager.getInstance().setCameraFacing(Camera1PreviewManager.CAMERA_FACING_BACK);
  15. // 设置USB摄像头
  16. Camera1PreviewManager.getInstance().setCameraFacing(Camera1PreviewManager.CAMERA_USB);
  17. Camera1PreviewManager.getInstance().startPreview(this, mPreviewView, mWidth, mHeight, new CameraDataCallback() {
  18. @Override
  19. public void onGetCameraData(int[] data, Camera camera, int width, int height) {
  20. dealCameraData(data, width, height);
  21. }
  22. });
  23. }
  24. /**
  25. * 摄像头数据处理
  26. *
  27. * @param data
  28. * @param width
  29. * @param height
  30. */
  31. private void dealCameraData(int[] data, int width, int height) {
  32. if (selectType == TYPE_PREVIEWIMAGE_OPEN) {
  33. setTrackAngle(data, width, height); // 显示检测的图片。用于调试,如果人脸sdk检测的人脸需要朝上,可以通过该图片判断。实际应用中可注释掉
  34. }
  35. // 摄像头预览数据进行人脸检测
  36. faceDetect(data, width, height);
  37. }
  38. /**
  39. * 人脸检测
  40. *
  41. * @param argb
  42. * @param width
  43. * @param height
  44. */
  45. private void faceDetect(int[] argb, int width, int height) {
  46. if (liveType == LivenessSettingActivity.TYPE_NO_LIVENSS) {
  47. FaceTrackManager.getInstance().setAliving(false); // 无活体检测
  48. } else if (liveType == LivenessSettingActivity.TYPE_RGB_LIVENSS) {
  49. FaceTrackManager.getInstance().setAliving(true); // 活体检测
  50. }
  51. FaceTrackManager.getInstance().faceTrack(argb, width, height, new FaceDetectCallBack() {
  52. @Override
  53. public void onFaceDetectCallback(LivenessModel livenessModel) {
  54. showFrame(livenessModel); //在这个方法里,如果符合检测要求,就会绘制绿框
  55. checkResult(livenessModel);//这个方法里,先是关于质量检测的,然后是关于脸的角度的,如果合格,就保存图片到本地,并且intent传数据到其它界面显示。
  56. }
  57. @Override
  58. public void onTip(int code, final String msg) {
  59. displayTip(msg);
  60. }
  61. });
  62. }
  63. /**
  64. * 图片收集
  65. *
  66. * @param faceInfo
  67. * @param imageFrame
  68. */
  69. private void faceCollect(ImageFrame imageFrame, FaceInfo[] faceInfos) {
  70. FaceInfo faceInfo = faceInfos[0];
  71. float[] headPose = faceInfo.headPose;
  72. if (Math.abs(headPose[0]) > 30 || Math.abs(headPose[1]) > 30 || Math.abs(headPose[2]) > 30) {
  73. handler.post(new Runnable() {
  74. @Override
  75. public void run() {
  76. tvTopShowState.setText("人脸置角度太大,请正对屏幕");
  77. }
  78. });
  79. } else {
  80. saveFace(faceInfo, imageFrame);
  81. }
  82. }
  83. /**
  84. * 图片截取
  85. *
  86. * @param faceInfo
  87. * @param imageFrame
  88. */
  89. private void saveFace(FaceInfo faceInfo, ImageFrame imageFrame) {
  90. final Bitmap bitmap = FaceCropper.getFace(imageFrame.getArgb(), faceInfo, imageFrame.getWidth());
  91. try {
  92. // 其他来源保存到临时目录
  93. final File file = File.createTempFile(UUID.randomUUID().toString() + "", ".jpg");
  94. // 人脸识别不需要整张图片。可以对人脸区别进行裁剪。减少流量消耗和,网络传输占用的时间消耗。
  95. ImageUtils.resize(bitmap, file, 300, 300);
  96. Intent intent = new Intent();
  97. intent.putExtra("file_path", file.getAbsolutePath());
  98. setResult(Activity.RESULT_OK, intent);
  99. finish();
  100. } catch (IOException e) {
  101. e.printStackTrace();
  102. }
  103. }

然后显示从视频里获取到的人脸图片,显示在界面上,和从照片进行识别

  1. Bitmap bitmap = BitmapFactory.decodeFile(faceImagePath);
  2. if (bitmap != null) {
  3. imgSecond.setImageBitmap(bitmap);
  4. if ((bitmap.getWidth() * bitmap.getHeight()) > pictureSize) {
  5. // 超过限制 缩放图片
  6. pictureResize(bitmap, 1);
  7. } else {
  8. syncFeature(bitmap, secondFeature, 2);//将识别的方法match()放到方法里if(index==2 && ret == 128){ match();} 自动识别
  9. }
  10. }

第九步:小案例的显示和效果

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1bnNoaW5lXzA3MDc_size_16_color_FFFFFF_t_70 6

发表评论

表情:
评论列表 (有 0 条评论,902人围观)

还没有评论,来说两句吧...

相关阅读