当前位置:   article > 正文

人脸识别——使用谷歌Firebase-ML Kit实现_mlkit 人脸对比

mlkit 人脸对比

一,前期基础知识储备

1)Firebae是什么

由 Google 提供支持,基于 Google 基础架构而构建,可以自动扩缩的全面移动开发平台。

官网地址:https://firebase.google.com/

2)ML Kit是什么

Firebase提供的面向移动开发者的机器学习产品。

官网地址:https://firebase.google.com/products/ml-kit/

文档地址:https://firebase.google.com/docs/ml-kit/

机器学习套件将 Google 的机器学习技术(如 Google Cloud Vision APITensorFlow Lite 和 Android Neural Networks API)聚集到单个 SDK 中,使您可以在自己的应用中轻松使用机器学习技术。无论您是需要强大的云端处理能力、针对移动设备进行了优化的设备端模型的实时功能,还是自定义 TensorFlow Lite 模型的灵活性,机器学习套件都只需几行代码即可实现。

功能合集:

二,上代码,具体实现

在 Android 上使用机器学习套件检测人脸:https://firebase.google.com/docs/ml-kit/android/detect-faces

1)准备工作:

① 请将Firebase添加到Android项目中(如果尚未添加)。

对于人脸识别而言,需要先在Firebase控制台进行注册,用应用的包名生成一个Json文件,然后将该文件放置到项目中。

测试使用,可直接拿本示例项目的Json文件,文末给出。

② 请务必在您的项目级 build.gradle 文件的 buildscript 和 allprojects 部分添加 Google 的 Maven 代码库。

  1. repositories {
  2. google()
  3. jcenter()
  4. }
  5. ... ...
  6. allprojects {
  7. repositories {
  8. google()
  9. jcenter()
  10. }
  11. }

③ 将 Android 版机器学习套件库的依赖项添加到您的模块(应用级)Gradle 文件(通常为 app/build.gradle):

  1. // ML Kit dependencies
  2. compile 'com.google.firebase:firebase-core:16.0.9'
  3. compile 'com.google.firebase:firebase-ml-vision:20.0.0'
  4. compile 'com.google.firebase:firebase-ml-vision-face-model:17.0.2'

2)输入图片指南:

为了使机器学习套件准确检测人脸,输入图片必须包含由足够像素数据表示的人脸。通常,要在图片中检测的每个人脸应至少为 100x100 像素。如果要检测人脸轮廓,机器学习套件需要更高的分辨率输入:每个人脸应至少为 200x200 像素。

如果您是在实时应用中检测人脸,则可能还需要考虑输入图片的整体尺寸。较小图片的处理速度相对较快,因此,为了减少延迟时间,请以较低的分辨率捕获图片(牢记上述准确性要求),并确保主体的面部在图片中占尽可能大的部分。

配置面部检测器 FirebaseVisionFaceDetectorOptions

  1. FirebaseVisionFaceDetectorOptions options =
  2. new FirebaseVisionFaceDetectorOptions.Builder()
  3. .setPerformanceMode(FirebaseVisionFaceDetectorOptions.FAST)
  4. .setContourMode(FirebaseVisionFaceDetectorOptions.ALL_CONTOURS)
  5. .build();

② 运行面部检测器 FirebaseVisionImage

要检测图片中的人脸,请基于设备上的以下资源创建一个 FirebaseVisionImage 对象:Bitmapmedia.ImageByteBuffer、字节数组或文件。然后,将 FirebaseVisionImage 对象传递给 FirebaseVisionFaceDetector 的 detectInImage 方法。

对于人脸识别,您使用的图片尺寸应至少为 480x360 像素。如果您要实时识别人脸,以此最低分辨率捕获帧有助于减少延迟时间。

1. 通过图片创建 FirebaseVisionImage 对象

FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);

每种输入的方式都有不同,文档里有详细的阐述,可以根据自己的项目,实际选取对应的方式。

2. 获取 FirebaseVisionFaceDetector 的一个实例:

  1. FirebaseVisionFaceDetector detector = FirebaseVision.getInstance()
  2. .getVisionFaceDetector(options);

3. 最后,将图片传递给 detectInImage 方法:

  1. Task<List<FirebaseVisionFace>> result =
  2. detector.detectInImage(image)
  3. .addOnSuccessListener(
  4. new OnSuccessListener<List<FirebaseVisionFace>>() {
  5. @Override
  6. public void onSuccess(List<FirebaseVisionFace> faces) {
  7. // Task completed successfully
  8. // ...
  9. }
  10. })
  11. .addOnFailureListener(
  12. new OnFailureListener() {
  13. @Override
  14. public void onFailure(@NonNull Exception e) {
  15. // Task failed with an exception
  16. // ...
  17. }
  18. });

3)获取检测到的面部的相关信息

如果人脸识别操作成功,系统会向成功侦听器传递一组 FirebaseVisionFace 对象。每个 FirebaseVisionFace 对象都代表一张在图片中检测到的面孔。对于每张面孔,您可以获取它在输入图片中的边界坐标,以及您已配置面部检测器查找的任何其他信息。

自定义“点”类,用以存储人脸识别的点位

  1. public class MyPoint {
  2. public double x;
  3. public double y;
  4. public MyPoint(double x, double y){
  5. this.x = x;
  6. this.y = y;
  7. }
  8. public double getX(){
  9. return x;
  10. }
  11. public double getY(){
  12. return y;
  13. }
  14. }

获取点位和这张图片,然后将点位画出来

  1. public Bitmap drawMlkiLandmarks(Bitmap bitmap, ArrayList<MyPoint> facePoints) {
  2. Log.d(TAG, "drawMlkiLandmarks: 1," + bitmap);
  3. Log.d(TAG, "drawMlkiLandmarks: 2," + facePoints);
  4. Bitmap bitmap3 = bitmap.copy(bitmap.getConfig(), true);
  5. Canvas canvas = new Canvas(bitmap3);
  6. for (int j = 0; j < facePoints.size(); j++) {
  7. int cx = (int) facePoints.get(j).x;
  8. int cy = (int) facePoints.get(j).y;
  9. Log.d(TAG, "drawMlkiLandmarks: " + j + ",," + cx + ",," + cy);
  10. paint.setStyle(Paint.Style.FILL_AND_STROKE);
  11. paint.setColor(Color.GREEN);
  12. paint.setStrokeWidth(3f);
  13. textPaint.setStrokeWidth(35f);
  14. textPaint.setColor(Color.WHITE);
  15. canvas.drawCircle(cx, cy, 3f, paint);
  16. canvas.drawText(String.valueOf(j), cx, cy, textPaint);
  17. }
  18. Log.d(TAG, "drawMlkiLandmarks: 3," + bitmap3);
  19. img.setImageBitmap(bitmap3);
  20. return bitmap3;
  21. }

以下是笔者的运行结果 —— 一共识别点位128个:运行在模拟器上,图片可能不够清晰。

另外,我们可以单独拿到各个点位,这样就可以对单个或多个点位进行攫取和调整,实际项目中非常方便。

 

最后给出主干代码,可以直接运行。

Activity代码:

  1. public class StillImageActivity extends AppCompatActivity {
  2. private static final String TAG = "StillImageActivity";
  3. private ImageView img;
  4. private Bitmap bitmap;
  5. private Paint paint;
  6. @Override
  7. protected void onCreate(@Nullable Bundle savedInstanceState) {
  8. super.onCreate(savedInstanceState);
  9. setContentView(R.layout.activity_stillimage);
  10. img = findViewById(R.id.img);
  11. imgTwo = findViewById(R.id.img_two);
  12. bitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.face_3);
  13. paint = new Paint();
  14. initMlkiFace(bitmap);
  15. }
  16. private volatile FirebaseVisionFaceDetector detector;
  17. private void initMlkiFace(final Bitmap bitmap) {
  18. final float scaleX = 1;
  19. final float scaleY = 1;
  20. final float transX = 0;
  21. final float transY = 0;
  22. if (bitmap != null) {
  23. FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);
  24. if (detector == null) {
  25. FirebaseVisionFaceDetectorOptions options =
  26. new FirebaseVisionFaceDetectorOptions.Builder()
  27. .setPerformanceMode(FirebaseVisionFaceDetectorOptions.FAST)
  28. .setContourMode(FirebaseVisionFaceDetectorOptions.ALL_CONTOURS)
  29. .build();
  30. detector = FirebaseVision.getInstance().getVisionFaceDetector(options);
  31. }
  32. detector.detectInImage(image).addOnSuccessListener(new OnSuccessListener<List<FirebaseVisionFace>>() {
  33. @Override
  34. public void onSuccess(List<FirebaseVisionFace> faces) {
  35. Log.d(TAG, "onSuccess: 识别成功");
  36. ArrayList<MyPoint> facePoints = new ArrayList<>();
  37. facePoints.clear();
  38. if (faces.size() > 0) {
  39. for (int i = 0; i < 1; i++) {
  40. List<FirebaseVisionPoint> contour = faces.get(i).getContour(FirebaseVisionFaceContour.ALL_POINTS).getPoints();
  41. for (int j = 0; j < contour.size(); j++) {
  42. MyPoint myPoint = new MyPoint(contour.get(j).getX() * scaleX + transX, contour.get(j).getY() * scaleY + transY);
  43. facePoints.add(myPoint);
  44. }
  45. }
  46. }
  47. drawMlkiLandmarks(bitmap, facePoints);
  48. try {
  49. if (detector != null) {
  50. detector.close();
  51. detector = null;
  52. }
  53. } catch (IOException e) {
  54. e.printStackTrace();
  55. }
  56. }
  57. }).addOnFailureListener(new OnFailureListener() {
  58. @Override
  59. public void onFailure(@NonNull Exception e) {
  60. Log.d(TAG, "onFailure: 识别失败" + e);
  61. ArrayList<MyPoint> facePoints = new ArrayList<>();
  62. facePoints.clear();
  63. drawMlkiLandmarks(bitmap, facePoints);
  64. try {
  65. if (detector != null) {
  66. detector.close();
  67. detector = null;
  68. }
  69. } catch (IOException e1) {
  70. e1.printStackTrace();
  71. }
  72. }
  73. });
  74. }
  75. }
  76. public Bitmap drawMlkiLandmarks(Bitmap bitmap, ArrayList<MyPoint> facePoints) {
  77. Log.d(TAG, "drawMlkiLandmarks: 1," + bitmap);
  78. Log.d(TAG, "drawMlkiLandmarks: 2," + facePoints);
  79. Bitmap bitmap3 = bitmap.copy(bitmap.getConfig(), true);
  80. Canvas canvas = new Canvas(bitmap3);
  81. for (int j = 0; j < facePoints.size(); j++) {
  82. int cx = (int) facePoints.get(j).x;
  83. int cy = (int) facePoints.get(j).y;
  84. Log.d(TAG, "drawMlkiLandmarks: " + j + ",," + cx + ",," + cy);
  85. paint.setStyle(Paint.Style.FILL_AND_STROKE);
  86. paint.setColor(Color.GREEN);
  87. paint.setStrokeWidth(3f);
  88. textPaint.setStrokeWidth(35f);
  89. textPaint.setColor(Color.WHITE);
  90. canvas.drawCircle(cx, cy, 3f, paint);
  91. canvas.drawText(String.valueOf(j), cx, cy, textPaint);
  92. }
  93. Log.d(TAG, "drawMlkiLandmarks: 3," + bitmap3);
  94. img.setImageBitmap(bitmap3);
  95. return bitmap3;
  96. }
  97. }

本项目Json文件:google-services.json,注意文件名不可更改。

注意,两个package_name需要同自己的项目保持一致。

  1. {
  2. "project_info": {
  3. "project_number": "48812919930",
  4. "firebase_url": "https://mlkit-a1dbd.firebaseio.com",
  5. "project_id": "mlkit-a1dbd",
  6. "storage_bucket": "mlkit-a1dbd.appspot.com"
  7. },
  8. "client": [
  9. {
  10. "client_info": {
  11. "mobilesdk_app_id": "1:48812919930:android:3b4e1d01e0aecbef",
  12. "android_client_info": {
  13. "package_name": "com.google.mlkit"
  14. }
  15. },
  16. "oauth_client": [
  17. {
  18. "client_id": "48812919930-ghfk9cm82ojhurb1uou7le4u42v10esv.apps.googleusercontent.com",
  19. "client_type": 1,
  20. "android_info": {
  21. "package_name": "com.google.mlkit",
  22. "certificate_hash": "0956e1fccbb13565a4543708cbf648a0858ffc43"
  23. }
  24. },
  25. {
  26. "client_id": "48812919930-ouugkae6qhraaf6b97h3ea2fvd187lrh.apps.googleusercontent.com",
  27. "client_type": 3
  28. },
  29. {
  30. "client_id": "48812919930-ouugkae6qhraaf6b97h3ea2fvd187lrh.apps.googleusercontent.com",
  31. "client_type": 3
  32. }
  33. ],
  34. "api_key": [
  35. {
  36. "current_key": "AIzaSyDorgdUVL_rlk8IGrX9x5IdYvAAt-sx7M0"
  37. }
  38. ],
  39. "services": {
  40. "analytics_service": {
  41. "status": 1
  42. },
  43. "appinvite_service": {
  44. "status": 2,
  45. "other_platform_oauth_client": [
  46. {
  47. "client_id": "48812919930-ouugkae6qhraaf6b97h3ea2fvd187lrh.apps.googleusercontent.com",
  48. "client_type": 3
  49. }
  50. ]
  51. },
  52. "ads_service": {
  53. "status": 2
  54. }
  55. }
  56. }
  57. ],
  58. "configuration_version": "1"
  59. }

 

最后,使用ML Kit,不仅能够识别静态图片的点位,摄像头获取的动态帧数据流人脸的点位也可以获取到。所以在相机项目中的人脸识别也可以使用ML Kit来进行人脸识别。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小惠珠哦/article/detail/748713
推荐阅读
相关标签
  

闽ICP备14008679号