欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新
页面位置 : > > > 内容正文

Android 实例开发基于ArcSoft实现人脸识别,

来源: 开发者 投稿于  被查看 10180 次 评论:239

Android 实例开发基于ArcSoft实现人脸识别,


目录
  • 效果图
    • 激活引擎
      • 第一步配置APP_ID和SDK_KEY
      • 第二步:判断是否添加动态链接库(so文件与jar包)
      • 第三步:判断是否申明所有权限
    • 人脸比对 1:N
      • 第一步:初始化本地人脸库
      • 第二步:初始化引擎和相机
      • 第三步:初始化引擎
      • 第四步:活体检测
    • 人脸注册
      • 切换前置、后置摄像头
      • 尾言

        效果图

        激活引擎

        第一步配置APP_ID和SDK_KEY

         int activeCode = FaceEngine.activeOnline( ChooseFunctionActivity.this, Param.APP_ID, Param.SDK_KEY);
        
         public static final String APP_ID = "AwY6okHQHxtM92YRYSEqJQwb8cED5huPvYyMhK1w7BSo";
           public static final String SDK_KEY = "AF8SaLYtP3ALsmaTR55y9UXaykBZjTtMt5gwCBkUGugh";
        

        第二步:判断是否添加动态链接库(so文件与jar包)

         private boolean checkSoFile(String[] libraries) {
                File dir = new File(getApplicationInfo().nativeLibraryDir);
                File[] files = dir.listFiles();
                if (files == null || files.length == 0) {
                    return false;
                }
                List<String> libraryNameList = new ArrayList<>();
                for (File file : files) {
                    libraryNameList.add(file.getName());
                }
                boolean exists = true;
                for (String library : libraries) {
                    exists &= libraryNameList.contains(library);
                }
                return exists;
            }
        

        第三步:判断是否申明所有权限

        protected boolean CheckPermissions(String[] neededPermissions) {
                if (neededPermissions == null || neededPermissions.length == 0) {
                    return true;
                }
                boolean allGranted = true;
                for (String neededPermission : neededPermissions) {
                    allGranted &= ContextCompat.checkSelfPermission(this, neededPermission) == PackageManager.PERMISSION_GRANTED;
                }
                return allGranted;
            }
        

        激活引擎代码如下

        public void ActivationDevice(final View view) {
                if (!libraryExists) {
                    ShowToast(getString(R.string.library_not_found));
                    return;
                }
                if (!CheckPermissions(NEEDED_PERMISSIONS)) {
                    ActivityCompat.requestPermissions(this, NEEDED_PERMISSIONS, ACTION_REQUEST_PERMISSIONS);
                    return;
                }
                if (view != null) {
                    view.setClickable(false);
                }
                Observable.create( new ObservableOnSubscribe<Integer>() {
                    @Override
                    public void subscribe(ObservableEmitter<Integer> emitter) {
                        RuntimeABI runtimeABI = FaceEngine.getRuntimeABI();
                        Log.i(TAG, "subscribe: getRuntimeABI() " + runtimeABI);
        
                        long start = System.currentTimeMillis();
                        int activeCode = FaceEngine.activeOnline( ChooseFunctionActivity.this, Param.APP_ID, Param.SDK_KEY);
                        Log.i(TAG, "subscribe cost: " + (System.currentTimeMillis() - start));
                        emitter.onNext(activeCode);
                    }
                })
                        .subscribeOn( Schedulers.io())
                        .observeOn( AndroidSchedulers.mainThread())
                        .subscribe(new Observer<Integer>() {
                            @Override
                            public void onSubscribe(Disposable d) {
        
                            }
        
                            @Override
                            public void onNext(Integer activeCode) {
                                if (activeCode == ErrorInfo.MOK) {
                                    ShowToast(getString(R.string.activation_succeeded));
                                } else if (activeCode == ErrorInfo.MERR_ASF_ALREADY_ACTIVATED) {
                                    ShowToast(getString(R.string.already_activated));
                                } else {
                                    ShowToast(getString(R.string.active_failed, activeCode));
                                }
        
                                if (view != null) {
                                    view.setClickable(true);
                                }
                                ActiveFileInfo activeFileInfo = new ActiveFileInfo();
                                int res = FaceEngine.getActiveFileInfo(ChooseFunctionActivity.this, activeFileInfo);
                                if (res == ErrorInfo.MOK) {
                                    Log.i(TAG, activeFileInfo.toString());
                                }
        
                            }
        
                            @Override
                            public void onError(Throwable e) {
                                ShowToast(e.getMessage());
                                if (view != null) {
                                    view.setClickable(true);
                                }
                            }
        
                            @Override
                            public void onComplete() {
        
                            }
                        });
        
            }
        

        人脸比对 1:N

        第一步:初始化本地人脸库

        FaceServer.getInstance().init(this);
        

        第二步:初始化引擎和相机

        public void onGlobalLayout() {
                previewView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                if (!CheckPermissions(NEEDED_PERMISSIONS)) {
                    ActivityCompat.requestPermissions(this, NEEDED_PERMISSIONS, ACTION_REQUEST_PERMISSIONS);
                } else {
                    initEngine();
                    initCamera();
                }
            }
        

        第三步:初始化引擎

         private void initEngine() {
                ftEngine = new FaceEngine();
                ftInitCode = ftEngine.init(this, DetectMode.ASF_DETECT_MODE_VIDEO, ConfigUtil.getFtOrient(this),
                        16, MAX_DETECT_NUM, FaceEngine.ASF_FACE_DETECT);
        
                frEngine = new FaceEngine();
                frInitCode = frEngine.init(this, DetectMode.ASF_DETECT_MODE_IMAGE, DetectFaceOrientPriority.ASF_OP_0_ONLY,
                        16, MAX_DETECT_NUM, FaceEngine.ASF_FACE_RECOGNITION);
        
                flEngine = new FaceEngine();
                flInitCode = flEngine.init(this, DetectMode.ASF_DETECT_MODE_IMAGE, DetectFaceOrientPriority.ASF_OP_0_ONLY,
                        16, MAX_DETECT_NUM, FaceEngine.ASF_LIVENESS);
        
                Log.i(TAG, "initEngine:  init: " + ftInitCode);
        
                if (ftInitCode != ErrorInfo.MOK) {
                    String error = getString(R.string.specific_engine_init_failed, "ftEngine", ftInitCode);
                    Log.i(TAG, "initEngine: " + error);
                    ShowToast(error);
                }
                if (frInitCode != ErrorInfo.MOK) {
                    String error = getString(R.string.specific_engine_init_failed, "frEngine", frInitCode);
                    Log.i(TAG, "initEngine: " + error);
                    ShowToast(error);
                }
                if (flInitCode != ErrorInfo.MOK) {
                    String error = getString(R.string.specific_engine_init_failed, "flEngine", flInitCode);
                    Log.i(TAG, "initEngine: " + error);
                    ShowToast(error);
                }
            }
        

        第四步:活体检测

        private void initCamera() {
                DisplayMetrics metrics = new DisplayMetrics();
                getWindowManager().getDefaultDisplay().getMetrics(metrics);
        
                final FaceListener faceListener = new FaceListener() {
                    @Override
                    public void onFail(Exception e) {
                        Log.e(TAG, "onFail: " + e.getMessage());
                    }
        
                    //请求FR的回调
                    @Override
                    public void onFaceFeatureInfoGet(@Nullable final FaceFeature faceFeature, final Integer requestId, final Integer errorCode) {
                        //FR成功
                        if (faceFeature != null) {
        //                    Log.i(TAG, "onPreview: fr end = " + System.currentTimeMillis() + " trackId = " + requestId);
                            Integer liveness = livenessMap.get(requestId);
                            //不做活体检测的情况,直接搜索
                            if (!livenessDetect) {
                                searchFace(faceFeature, requestId);
                            }
                            //活体检测通过,搜索特征
                            else if (liveness != null && liveness == LivenessInfo.ALIVE) {
                                searchFace(faceFeature, requestId);
                            }
                            //活体检测未出结果,或者非活体,延迟执行该函数
                            else {
                                if (requestFeatureStatusMap.containsKey(requestId)) {
                                    Observable.timer(WAIT_LIVENESS_INTERVAL, TimeUnit.MILLISECONDS)
                                            .subscribe(new Observer<Long>() {
                                                Disposable disposable;
        
                                                @Override
                                                public void onSubscribe(Disposable d) {
                                                    disposable = d;
                                                    getFeatureDelayedDisposables.add(disposable);
                                                }
        
                                                @Override
                                                public void onNext(Long aLong) {
                                                    onFaceFeatureInfoGet(faceFeature, requestId, errorCode);
                                                }
        
                                                @Override
                                                public void onError(Throwable e) {
        
                                                }
        
                                                @Override
                                                public void onComplete() {
                                                    getFeatureDelayedDisposables.remove(disposable);
                                                }
                                            });
                                }
                            }
        
                        }
                        //特征提取失败
                        else {
                            if (increaseAndGetValue(extractErrorRetryMap, requestId) > MAX_RETRY_TIME) {
                                extractErrorRetryMap.put(requestId, 0);
        
                                String msg;
                                // 传入的FaceInfo在指定的图像上无法解析人脸,此处使用的是RGB人脸数据,一般是人脸模糊
                                if (errorCode != null && errorCode == ErrorInfo.MERR_FSDK_FACEFEATURE_LOW_CONFIDENCE_LEVEL) {
                                    msg = getString(R.string.low_confidence_level);
                                } else {
                                    msg = "ExtractCode:" + errorCode;
                                }
                                faceHelper.setName(requestId, getString(R.string.recognize_failed_notice, msg));
                                // 在尝试最大次数后,特征提取仍然失败,则认为识别未通过
                                requestFeatureStatusMap.put(requestId, RequestFeatureStatus.FAILED);
                                retryRecognizeDelayed(requestId);
                            } else {
                                requestFeatureStatusMap.put(requestId, RequestFeatureStatus.TO_RETRY);
                            }
                        }
                    }
        
                    @Override
                    public void onFaceLivenessInfoGet(@Nullable LivenessInfo livenessInfo, final Integer requestId, Integer errorCode) {
                        if (livenessInfo != null) {
                            int liveness = livenessInfo.getLiveness();
                            livenessMap.put(requestId, liveness);
                            // 非活体,重试
                            if (liveness == LivenessInfo.NOT_ALIVE) {
                                faceHelper.setName(requestId, getString(R.string.recognize_failed_notice, "NOT_ALIVE"));
                                // 延迟 FAIL_RETRY_INTERVAL 后,将该人脸状态置为UNKNOWN,帧回调处理时会重新进行活体检测
                                retryLivenessDetectDelayed(requestId);
                            }
                        } else {
                            if (increaseAndGetValue(livenessErrorRetryMap, requestId) > MAX_RETRY_TIME) {
                                livenessErrorRetryMap.put(requestId, 0);
                                String msg;
                                // 传入的FaceInfo在指定的图像上无法解析人脸,此处使用的是RGB人脸数据,一般是人脸模糊
                                if (errorCode != null && errorCode == ErrorInfo.MERR_FSDK_FACEFEATURE_LOW_CONFIDENCE_LEVEL) {
                                    msg = getString(R.string.low_confidence_level);
                                } else {
                                    msg = "ProcessCode:" + errorCode;
                                }
                                faceHelper.setName(requestId, getString(R.string.recognize_failed_notice, msg));
                                retryLivenessDetectDelayed(requestId);
                            } else {
                                livenessMap.put(requestId, LivenessInfo.UNKNOWN);
                            }
                        }
                    }
        
        
                };
        
        
                CameraListener cameraListener = new CameraListener() {
                    @Override
                    public void onCameraOpened(Camera camera, int cameraId, int displayOrientation, boolean isMirror) {
                        Camera.Size lastPreviewSize = previewSize;
                        previewSize = camera.getParameters().getPreviewSize();
                        drawHelper = new DrawHelper(previewSize.width, previewSize.height, previewView.getWidth(), previewView.getHeight(), displayOrientation
                                , cameraId, isMirror, false, false);
                        Log.i(TAG, "onCameraOpened: " + drawHelper.toString());
                        // 切换相机的时候可能会导致预览尺寸发生变化
                        if (faceHelper == null ||
                                lastPreviewSize == null ||
                                lastPreviewSize.width != previewSize.width || lastPreviewSize.height != previewSize.height) {
                            Integer trackedFaceCount = null;
                            // 记录切换时的人脸序号
                            if (faceHelper != null) {
                                trackedFaceCount = faceHelper.getTrackedFaceCount();
                                faceHelper.release();
                            }
                            faceHelper = new FaceHelper.Builder()
                                    .ftEngine(ftEngine)
                                    .frEngine(frEngine)
                                    .flEngine(flEngine)
                                    .frQueueSize(MAX_DETECT_NUM)
                                    .flQueueSize(MAX_DETECT_NUM)
                                    .previewSize(previewSize)
                                    .faceListener(faceListener)
                                    .trackedFaceCount(trackedFaceCount == null ? ConfigUtil.getTrackedFaceCount(FaceComparison_RGB.this.getApplicationContext()) : trackedFaceCount)
                                    .build();
                        }
                    }
        
        
                    @Override
                    public void onPreview(final byte[] nv21, Camera camera) {
                        if (faceRectView != null) {
                            faceRectView.clearFaceInfo();
                        }
                        List<FacePreviewInfo> facePreviewInfoList = faceHelper.onPreviewFrame(nv21);
                        if (facePreviewInfoList != null && faceRectView != null && drawHelper != null) {
                            drawPreviewInfo(facePreviewInfoList);
                        }
                        registerFace(nv21, facePreviewInfoList);
                        clearLeftFace(facePreviewInfoList);
        
                        if (facePreviewInfoList != null && facePreviewInfoList.size() > 0 && previewSize != null) {
                            for (int i = 0; i < facePreviewInfoList.size(); i++) {
                                Integer status = requestFeatureStatusMap.get(facePreviewInfoList.get(i).getTrackId());
                                /**
                                 * 在活体检测开启,在人脸识别状态不为成功或人脸活体状态不为处理中(ANALYZING)且不为处理完成(ALIVE、NOT_ALIVE)时重新进行活体检测
                                 */
                                if (livenessDetect && (status == null || status != RequestFeatureStatus.SUCCEED)) {
                                    Integer liveness = livenessMap.get(facePreviewInfoList.get(i).getTrackId());
                                    if (liveness == null
                                            || (liveness != LivenessInfo.ALIVE && liveness != LivenessInfo.NOT_ALIVE && liveness != RequestLivenessStatus.ANALYZING)) {
                                        livenessMap.put(facePreviewInfoList.get(i).getTrackId(), RequestLivenessStatus.ANALYZING);
                                        faceHelper.requestFaceLiveness(nv21, facePreviewInfoList.get(i).getFaceInfo(), previewSize.width, previewSize.height, FaceEngine.CP_PAF_NV21, facePreviewInfoList.get(i).getTrackId(), LivenessType.RGB);
                                    }
                                }
                                /**
                                 * 对于每个人脸,若状态为空或者为失败,则请求特征提取(可根据需要添加其他判断以限制特征提取次数),
                                 * 特征提取回传的人脸特征结果在{@link FaceListener#onFaceFeatureInfoGet(FaceFeature, Integer, Integer)}中回传
                                 */
                                if (status == null
                                        || status == RequestFeatureStatus.TO_RETRY) {
                                    requestFeatureStatusMap.put(facePreviewInfoList.get(i).getTrackId(), RequestFeatureStatus.SEARCHING);
                                    faceHelper.requestFaceFeature(nv21, facePreviewInfoList.get(i).getFaceInfo(), previewSize.width, previewSize.height, FaceEngine.CP_PAF_NV21, facePreviewInfoList.get(i).getTrackId());
        //                            Log.i(TAG, "onPreview: fr start = " + System.currentTimeMillis() + " trackId = " + facePreviewInfoList.get(i).getTrackedFaceCount());
                                }
                            }
                        }
                    }
        
                    @Override
                    public void onCameraClosed() {
                        Log.i(TAG, "onCameraClosed: ");
                    }
        
                    @Override
                    public void onCameraError(Exception e) {
                        Log.i(TAG, "onCameraError: " + e.getMessage());
                    }
        
                    @Override
                    public void onCameraConfigurationChanged(int cameraID, int displayOrientation) {
                        if (drawHelper != null) {
                            drawHelper.setCameraDisplayOrientation(displayOrientation);
                        }
                        Log.i(TAG, "onCameraConfigurationChanged: " + cameraID + "  " + displayOrientation);
                    }
                };
        
                cameraHelper = new CameraHelper.Builder()
                        .previewViewSize(new Point(previewView.getMeasuredWidth(), previewView.getMeasuredHeight()))
                        .rotation(getWindowManager().getDefaultDisplay().getRotation())
                        .specificCameraId(rgbCameraID != null ? rgbCameraID : Camera.CameraInfo.CAMERA_FACING_FRONT)
                        .isMirror(false)
                        .previewOn(previewView)
                        .cameraListener(cameraListener)
                        .build();
                cameraHelper.init();
                cameraHelper.start();
            }
        

        人脸注册

         private void registerFace(final byte[] nv21, final List<FacePreviewInfo> facePreviewInfoList) {
                if (registerStatus == REGISTER_STATUS_READY && facePreviewInfoList != null && facePreviewInfoList.size() > 0) {
                    registerStatus = REGISTER_STATUS_PROCESSING;
                    Observable.create( new ObservableOnSubscribe<Boolean>() {
                        @Override
                        public void subscribe(ObservableEmitter<Boolean> emitter) {
        
                            boolean success = FaceServer.getInstance().registerNv21(FaceComparison_RGB.this, nv21.clone(), previewSize.width, previewSize.height,
                                    facePreviewInfoList.get(0).getFaceInfo(), "registered" + faceHelper.getTrackedFaceCount());
                            emitter.onNext(success);
                        }
                    })
                            .subscribeOn( Schedulers.computation())
                            .observeOn( AndroidSchedulers.mainThread())
                            .subscribe(new Observer<Boolean>() {
                                @Override
                                public void onSubscribe(Disposable d) {
        
                                }
                                /**判断是否注册成功*/
                                @Override
                                public void onNext(Boolean success) {
                                    //String result = success ? "register success!" : "register failed!";
                                    //ShowToast(result);
        //                            AlertDialog.Builder builder = new AlertDialog.Builder( FaceComparison_RGB.this );
        //                            AlertDialog dialog = builder.create();
        //                            View AlertDialog_View = View.inflate( FaceComparison_RGB.this,R.layout.register_result,null );
        //                            dialog.setView( AlertDialog_View );
        //                            dialog.show();
                                    ShowPopWindows(success);
                                    registerStatus = REGISTER_STATUS_DONE;
                                }
        
                                @Override
                                public void onError(Throwable e) {
                                    e.printStackTrace();
                                    ShowToast("register failed!");
                                    ShowFailPopWindows();
                                    registerStatus = REGISTER_STATUS_DONE;
                                }
                                @Override
                                public void onComplete() {
        
                                }
                            });
                }
            }
        

        切换前置、后置摄像头

        public void switchCamera(View view) {
                if (cameraHelper != null) {
                    boolean success = cameraHelper.switchCamera();
                    if (!success) {
                        ShowToast(getString(R.string.switch_camera_failed));
                    } else {
                        ShowToast(getString(R.string.notice_change_detect_degree));
                    }
                }
            }
        

        尾言

        本示例工程基于虹软(ArcSoft)官方Demo改编而成,若有唐突之处,望君海涵

        到此这篇关于Android 实例开发基于ArcSoft实现人脸识别的文章就介绍到这了,更多相关Android 人脸识别内容请搜索3672js教程以前的文章或继续浏览下面的相关文章希望大家以后多多支持3672js教程!

        您可能感兴趣的文章:
        • Android开发人脸识别统计人脸数
        • Android开发人脸识别登录功能
        • android实现人脸识别技术的示例代码
        • Android camera实时预览 实时处理,人脸识别示例

        用户评论