虹软人脸识别使用教程

首先到虹软人脸AI开放平台https://ai.arcsoft.com.cn/product/arcface.html?utm_source=baidu1f&utm_medium=cpc&audience=313092完成注册登陆,并且添加一个Arcface应用,获得应用的激活码,然后下载sdk‘到本地,里面有个simpleDemo/ArcfaceDemo的android demo,还有sdk的doc文档,下面是对二者的分析和如何使用sdk

虹软人脸识别使用教程_第1张图片

 

        调用流程:

虹软人脸识别使用教程_第2张图片

 

1.先重写activity的startActivityForResult()方法,访问手机的所有图片,并获取到图片文件

2.再通过重写activity的onActivityResult()方法,处理startActivityForResult返回的文件数据(人脸图片),处理方式:

   2.1拿到文件的路径后,通过调用processImage()方法:关键代码如下:

public void processImage(Bitmap bitmap, int type) {
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        //bitmap转NV21
        final byte[] nv21 = ImageUtil.bitmapToNv21(bitmap, width, height);
}

将图片文件转成bitMap形式,便于计算机处理图片信息(图片的人脸信息)

   2.2将bitmap转为nv21,得到图片的nv21格式,宽,高后,就调用FaceEngine对象的detectFaces()方法

List faceInfoList = new ArrayList<>();
//人脸检测
int detectCode = faceEngine.detectFaces(nv21, width, height, FaceEngine.CP_PAF_NV21, faceInfoList);

   detectFaces()方法的关键代码如下:

                    faceInfoList.clear();
                    int count = this.detectFaces(this.handle, data, width, height, format, this.mFaceInfoArray, this.error);
                    if (count > 0) {
                        for(int i = 0; i < count; ++i) {
                            faceInfoList.add(new FaceInfo(this.mFaceInfoArray[i]));
                        }
                    }

                    return this.error.code;

 

3.拿到预处理的图像数据faceInfo后就调用extractFaceFeature()方法

FaceFeature faceFeature = new FaceFeature();
int frCode = faceEngine.extractFaceFeature(nv21Data, width, height, format, faceInfo, faceFeature);
//该方法的返回值是int,frCode代表的是错误码的意思,返回的错误码为ErrorInfo.MOK表示特征提取成功
//MOK调用成功    MERR_INVALID_PARAM无效的参数     MERR_EXPIRED操作时间过期............

 extractFaceFeature()方法的关键代码如下:

 this.extractFaceFeature(this.handle, data, width, height, format, faceInfo.getRect(), faceInfo.getOrient(), feature.getFeatureData(), this.error);
              return this.error.code;

 进一步追踪this.后面的extractFaceFeature():

    private native void extractFaceFeature(long var1, byte[] var3, int var4, int var5, int var6, Rect var7, int var8, byte[] var9, ErrorInfo var10);

这是一个原生方法,它是通过sdk中的 so库里的c或c++的函数实现的(人脸识别的一系列算法),先new一个FaceFeature(人脸特征对象,用于输出人脸特征数据)以参数形式传入到extractFaceFeature中,通过人脸识别算法为FaceFeature对象的字段FEATURE_SIZE人脸特征数据的长度赋值,再调用FaceFeature对象的setFeatureData(byte[] data)设置人脸特征数据,从而提取出人脸特征,调用FaceFeature的getFeatureData()就能获取到人脸特征数据

 
4.拿到FaceFuture后,就调用compareFaceFeature()比对人脸:

FaceFeature mainFeature = new FaceFeature();
int res = faceEngine.extractFaceFeature(nv21, width, height, FaceEngine.CP_PAF_NV21, faceInfoList.get(0), mainFeature);
FaceSimilar faceSimilar = new FaceSimilar();
/**
*compareFaceFeature方法
*/
int compareResult = faceEngine.compareFaceFeature(mainFeature, faceFeature, faceSimilar);
ItemShowInfo showInfo = new ItemShowInfo(bitmap, ageInfoList.get(0).getAge(), genderInfoList.get(0).getGender(), faceSimilar.getScore());
//List showInfoList;
showInfoList.add(showInfo);

 5.调用 FaceEngine 的 process 方法,传入不同的 combineMask 组合可对 Age、 Gender、Face3Dangle、Liveness 进行检测,传入的 combineMask 的任一属性都需要在 init 时进行初始化,process ()关键代码 :

 int faceProcessCode = faceEngine.process(nv21, width, height, FaceEngine.CP_PAF_NV21, faceInfoList, FaceEngine.ASF_AGE | FaceEngine.ASF_GENDER | FaceEngine.ASF_FACE3DANGLE);
    //年龄信息结果
            List ageInfoList = new ArrayList<>();
            //性别信息结果
            List genderInfoList = new ArrayList<>();
            //三维角度结果
            List face3DAngleList = new ArrayList<>();
            //获取年龄、性别、三维角度
            int ageCode = faceEngine.getAge(ageInfoList);
            int genderCode = faceEngine.getGender(genderInfoList);
            int face3DAngleCode = faceEngine.getFace3DAngle(face3DAngleList);
            
            

获取相似度的评分代码如下:

float similarScore=faceSimilar.getScore();

也可以通过如下获得:

 List showInfoList;
 ItemShowInfo showInfo = new ItemShowInfo(bitmap, ageInfoList.get(0).getAge(), genderInfoList.get(0).getGender(), faceSimilar.getScore());
 showInfoList.add(showInfo);
 int age=showInfoList.getAge();
 int gender=showInfoList.getGender();
 float similar=showInfoList.getSimilar();

 

 

人脸注册 :

给出人脸文件夹

File dir = new File(REGISTER_DIR);
final File[] jpgFiles = dir.listFiles()
final int totalCount = jpgFiles.length;
for (int i = 0; i < totalCount; i++) {
          final File jpgFile = jpgFiles[i];
                    Bitmap bitmap = BitmapFactory.decodeFile(jpgFile.getAbsolutePath());
//处理过的Bitmap对象
            bitmap = ImageUtil.alignBitmapForNv21(bitmap);
            byte[] nv21 = ImageUtil.bitmapToNv21(bitmap, bitmap.getWidth(), bitmap.getHeight());
                    boolean success = FaceServer.getInstance().register(FaceManageActivity.this, nv21, bitmap.getWidth(), bitmap.getHeight(),
                            jpgFile.getName().substring(0, jpgFile.getName().lastIndexOf(".")));
}

nv21注册:

 public boolean register(Context context, byte[] nv21, int width, int height, String name) {
     /**
             * 人脸注册关键代码
             * ****************************重点关注**************************************************
             */
            //特征存储的文件夹
            File featureDir = new File(ROOT_PATH + File.separator + SAVE_FEATURE_DIR);
  //图片存储的文件夹
            File imgDir = new File(ROOT_PATH + File.separator + SAVE_IMG_DIR);
 //1.人脸检测
            List faceInfoList = new ArrayList<>();
            int code = faceEngine.detectFaces(nv21, width, height, FaceEngine.CP_PAF_NV21, faceInfoList);
            if (code == ErrorInfo.MOK && faceInfoList.size() > 0) {
                FaceFeature faceFeature = new FaceFeature();

                //2.特征提取
                code = faceEngine.extractFaceFeature(nv21, width, height, FaceEngine.CP_PAF_NV21, faceInfoList.get(0), faceFeature);
                String userName = name == null ? String.valueOf(System.currentTimeMillis()) : name;
                try {
                    //3.保存注册结果(注册图、特征数据)
                    if (code == ErrorInfo.MOK) {
                        YuvImage yuvImage = new YuvImage(nv21, ImageFormat.NV21, width, height, null);
                        //为了美观,扩大rect截取注册图
                        Rect cropRect = getBestRect(width, height, faceInfoList.get(0).getRect());
                        if (cropRect == null) {
                            return false;
                        }
                        File file = new File(imgDir + File.separator + userName + IMG_SUFFIX);
                        FileOutputStream fosImage = new FileOutputStream(file);
                        yuvImage.compressToJpeg(cropRect, 100, fosImage);
                        fosImage.close();
                        Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());

                        //判断人脸旋转角度,若不为0度则旋转注册图
                        boolean needAdjust = false;
                        if (bitmap != null) {
                            switch (faceInfoList.get(0).getOrient()) {
                                case FaceEngine.ASF_OC_0:
                                    break;
                                case FaceEngine.ASF_OC_90:
                                    bitmap = ImageUtil.getRotateBitmap(bitmap, 90);
                                    needAdjust = true;
                                    break;
                                case FaceEngine.ASF_OC_180:
                                    bitmap = ImageUtil.getRotateBitmap(bitmap, 180);
                                    needAdjust = true;
                                    break;
                                case FaceEngine.ASF_OC_270:
                                    bitmap = ImageUtil.getRotateBitmap(bitmap, 270);
                                    needAdjust = true;
                                    break;
                                default:
                                    break;
                            }
                        }
                        if (needAdjust) {
                            fosImage = new FileOutputStream(file);
                            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fosImage);
                            fosImage.close();
                        }

                        FileOutputStream fosFeature = new FileOutputStream(featureDir + File.separator + userName);
                        fosFeature.write(faceFeature.getFeatureData());
                        fosFeature.close();

                        //内存中的数据同步
                        if (faceRegisterInfoList == null) {
                            faceRegisterInfoList = new ArrayList<>();
                        }
                        faceRegisterInfoList.add(new FaceRegisterInfo(faceFeature.getFeatureData(), userName));
                        return true;
                    }

}

 

你可能感兴趣的:(android)