请选择 进入手机版 | 继续访问电脑版

[Android] 【人脸识别】Google的Facenet移植到安卓

编程语言 编程语言 1574 人阅读 | 0 人回复

发表于 2020-10-10 09:12:55 | 显示全部楼层 |阅读模式

准确来说,这个项目包含两部分:
(1)人脸检测,从图中找出人脸,也就是之前的那个项目包含到这个项目里面。
(2)人脸识别,识别出当前人脸是谁。其实就是提取特征,然后直接比较两个人之间的特征欧几里得距离D.。
       如果D小于某个阈值(官方的设置值是1.204),就判断为两个人脸图是同一个。
用的卷积神经网络是别人训练好的,90MB+,在公共数据集上有99+%的准确率。

核心代码【这个代码比较简单,一两百行代码】:

Facenet.java
  1. package com.example.vcvyc.myapplication;

  2. import android.app.Activity;
  3. import android.content.res.AssetManager;
  4. import android.graphics.Bitmap;
  5. import android.graphics.Matrix;
  6. import android.util.Log;
  7. /*
  8. import android.graphics.Bitmap;
  9. import android.os.Trace;
  10. import android.util.Log;
  11. import java.io.BufferedReader;
  12. import java.io.IOException;
  13. import java.io.InputStreamReader;
  14. import java.util.ArrayList;
  15. import java.util.Comparator;
  16. import java.util.List;
  17. import java.util.PriorityQueue;
  18. import java.util.Vector;
  19. */
  20. import org.tensorflow.Operation;
  21. import org.tensorflow.contrib.android.TensorFlowInferenceInterface;

  22. import java.io.IOException;
  23. import java.nio.IntBuffer;

  24. /**功能:人脸转换为512维特征向量
  25. */
  26. public class Facenet{
  27.     private static final String MODEL_FILE  = "file:///android_asset/20180402-114759.pb";
  28.     private static final String INPUT_NAME  = "input:0";
  29.     private static final String OUTPUT_NAME = "embeddings:0";
  30.     private static final String PHASE_NAME  = "phase_train:0";
  31.     private static final String[] outputNames = new String[] {OUTPUT_NAME};
  32.     //神经网络输入大小
  33.     private static final int INPUT_SIZE=160;
  34.     private float[] floatValues;  //保存input的值
  35.     private int[] intValues;      //像素值
  36.     private AssetManager assetManager;
  37.     private TensorFlowInferenceInterface inferenceInterface;
  38.     Facenet(AssetManager mgr){
  39.         assetManager=mgr;
  40.         loadModel();
  41.         floatValues=new float[INPUT_SIZE*INPUT_SIZE*3];
  42.         intValues = new int[INPUT_SIZE * INPUT_SIZE];
  43.     }
  44.     private boolean loadModel(){
  45.         //AssetManager
  46.         try {
  47.             inferenceInterface = new TensorFlowInferenceInterface(assetManager, MODEL_FILE);
  48.             Log.d("Facenet","[*]load model success");
  49.         }catch(Exception e){
  50.             Log.e("Facenet","[*]load model failed"+e);
  51.             return false;
  52.         }
  53.         return true;
  54.     }
  55.     //Bitmap to floatValues
  56.     private int normalizeImage(final Bitmap _bitmap){
  57.         // (0) bitmap缩放到INPUT_SIZE*INPUT_SIZE
  58.         float scale_width=((float)INPUT_SIZE)/_bitmap.getWidth();
  59.         float scale_height=((float)INPUT_SIZE)/_bitmap.getHeight();
  60.         Matrix matrix = new Matrix();
  61.         matrix.postScale(scale_width,scale_height);
  62.         Bitmap bitmap = Bitmap.createBitmap(_bitmap,0,0,_bitmap.getWidth(),_bitmap.getHeight(),matrix,true);
  63.         //Log.d("Facenet","[*]bitmap size:"+bitmap.getHeight()+"x"+bitmap.getWidth());
  64.         // (1) 将像素映射到[-1,1]区间内
  65.         float imageMean=127.5f;
  66.         float imageStd=128;
  67.         bitmap.getPixels(intValues,0,bitmap.getWidth(),0,0,bitmap.getWidth(),bitmap.getHeight());
  68.         for (int i=0;i<intValues.length;i++){
  69.             final int val=intValues[i];
  70.             floatValues[i * 3 + 0] = (((val >> 16) & 0xFF) - imageMean) / imageStd;
  71.             floatValues[i * 3 + 1] = (((val >> 8) & 0xFF) - imageMean) / imageStd;
  72.             floatValues[i * 3 + 2] = ((val & 0xFF) - imageMean) / imageStd;
  73.         }
  74.         //Log.d("Facenet","[*]normalizeImage");
  75.         //Log.d("Facenet","[*]normalizeImage"+intValues.length);
  76.         return 0;
  77.     }
  78.     public FaceFeature recognizeImage(final Bitmap bitmap){
  79.         //Log.d("Facenet","[*]recognizeImage");
  80.         //(0)图片预处理,normailize
  81.         normalizeImage(bitmap);
  82.         //(1)Feed
  83.         try {
  84.             inferenceInterface.feed(INPUT_NAME, floatValues, 1, INPUT_SIZE, INPUT_SIZE, 3);
  85.             boolean []phase=new boolean[1];
  86.             phase[0]=false;
  87.             inferenceInterface.feed(PHASE_NAME,phase);
  88.         }catch (Exception e){
  89.             Log.e("Facenet","[*] feed Error\n"+e);
  90.             return null;
  91.         }
  92.         //(2)run
  93.        // Log.d("Facenet","[*]Feed:"+INPUT_NAME);
  94.         try {
  95.             inferenceInterface.run(outputNames, false);
  96.         }catch (Exception e){
  97.             Log.e("Facenet","[*] run error\n"+e);
  98.             return null;
  99.         }
  100.         //(3)fetch
  101.         FaceFeature faceFeature=new FaceFeature();
  102.         float[] outputs=faceFeature.getFeature();
  103.         try {
  104.             inferenceInterface.fetch(OUTPUT_NAME, outputs);
  105.         }catch (Exception e){
  106.             Log.e("Facenet","[*] fetch error\n"+e);
  107.             return null;
  108.         }
  109.         return faceFeature;
  110.     }
  111. }
复制代码
FaceFeature.java
  1. package com.example.vcvyc.myapplication;
  2. /* by cjf 1801615 [email]352871242@qq.com[/email]*/
  3. /**
  4. * 人脸特征(512维特征值)
  5. * 相似度取特征向量之间的欧式距离.
  6. */
  7. public class FaceFeature {
  8.     public static final int DIMS=512;
  9.     private float fea[];
  10.     FaceFeature(){
  11.         fea=new float[DIMS];
  12.     }
  13.     public float[] getFeature(){
  14.         return fea;
  15.     }
  16.     //比较当前特征和另一个特征之间的相似度
  17.     public double compare(FaceFeature ff){
  18.         double dist=0;
  19.         for (int i=0;i<DIMS;i++)
  20.             dist+=(fea[i]-ff.fea[i])*(fea[i]-ff.fea[i]);
  21.         dist=Math.sqrt(dist);
  22.         return dist;
  23.     }
  24. }
复制代码
1.png

点评回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则