Android 集成虹软人脸识别SDK的问题

如何集成

  • 虹软开发者中心登录[虹软官网](https://ai.arcsoft.com.cn/ucenter/user/userlogin)
  • 进入开发者中心,新建应用获取APPID 和 APPSDKKEY 后面要用到
  • 下载所需要的SDK
  • 查看集成文档,官方文档写的很详细地址(https://ai.arcsoft.com.cn/manual/arcface_windows_guideV2.html)

如何调用

-在你集成的应用内Activity或SplashActivity

编写如下方法,引擎初始化

/**
     * 激活引擎
     *
     */
    public void activeEngine() {
        Observable.create(new ObservableOnSubscribe() {
            @Override
            public void subscribe(ObservableEmitter emitter) throws Exception {
                FaceEngine faceEngine = new FaceEngine();
                int activeCode = faceEngine.active(SplashActivity.this, CommMacro.ARC_APPID, CommMacro.ARC_SDKKEY);
                emitter.onNext(activeCode);
            }
        })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Integer activeCode) {
                        if (activeCode == ErrorInfo.MOK) {
                            Toast.makeText(getApplicationContext(),"激活成功",Toast.LENGTH_SHORT).show();
                            Log.d("Arc", "激活成功了: ");
                        } else if (activeCode == ErrorInfo.MERR_ASF_ALREADY_ACTIVATED) {
                            //Toast.makeText(getApplicationContext(),"已激活,无需再次激活",Toast.LENGTH_SHORT).show();
                        } else {
                            Toast.makeText(getApplicationContext(),"激活失败",Toast.LENGTH_SHORT).show();
                        }

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });

    }
  • 代码中的APPID 和 SDKKEY就是你在开发者中心申请的

如何使用

  • 人脸识别初始化
/**
     * 人脸识别初始化
     */
    private void initArcSetting() {

        //本地人脸库初始化
        FaceServer.getInstance().init(SignActivity.this);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            WindowManager.LayoutParams attributes = getWindow().getAttributes();
            attributes.systemUiVisibility = View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
            getWindow().setAttributes(attributes);
        }

        // Activity启动后就锁定为启动时的方向
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);

        previewView = findViewById(R.id.sign_texture_preview);
        faceRectView = findViewById(R.id.sign_face_rect_view);
        previewView.getViewTreeObserver().addOnGlobalLayoutListener(this);

        compareResultList = new ArrayList<>();

    }
  • 其中的FaceServer是在demo中直接使用额


    Android 集成虹软人脸识别SDK的问题_第1张图片
    image.png
  • 声明代码

    /**
     * 相机预览显示的控件,可为SurfaceView或TextureView
     */
    private View previewView;
    private ArcCameraHelper cameraHelper;
    private DrawHelper drawHelper;
    private Camera.Size previewSize;
    private FaceRectView faceRectView;
    private Integer rgbCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;//前置摄像头
    private FaceEngine faceEngine;
    private FaceHelper faceHelper;
    private int afCode = -1;
    /**
     * 活体检测的开关
     */
    private boolean livenessDetect = true;
    /**
     * 当FR成功,活体未成功时,FR等待活体的时间
     */
    private static final int WAIT_LIVENESS_INTERVAL = 10;
    private static final int MAX_DETECT_NUM = 10;
    private List compareResultList;
    private ConcurrentHashMap requestFeatureStatusMap = new ConcurrentHashMap<>();
    private ConcurrentHashMap livenessMap = new ConcurrentHashMap<>();
    private CompositeDisposable getFeatureDelayedDisposables = new CompositeDisposable();
    private static final int ACTION_REQUEST_PERMISSIONS = 0x001;
    private static final float SIMILAR_THRESHOLD = 0.8F;
  • 相机初始化代码部分
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) {
                //FR成功
                if (faceFeature != null) {
                    Log.i(TAG, "onPreview: fr end = " + System.currentTimeMillis() + " trackId = " + requestId);

                    //不做活体检测的情况,直接搜索
                    if (!livenessDetect) {
                        Log.d(TAG, "不做活体检测的情况,直接搜索: ");
                        searchFace(faceFeature, requestId);
                    }
                    //活体检测通过,搜索特征
                    else if (livenessMap.get(requestId) != null && livenessMap.get(requestId) == LivenessInfo.ALIVE) {
                        Log.d(TAG, "活体检测通过,搜索特征: ");
                        searchFace(faceFeature, requestId);

                    }
                    //活体检测未出结果,延迟100ms再执行该函数
                    else if (livenessMap.get(requestId) != null && livenessMap.get(requestId) == LivenessInfo.UNKNOWN) {
                        Log.d(TAG, "活体检测未出结果,延迟10ms再执行该函数: ");
                        getFeatureDelayedDisposables.add(Observable.timer(WAIT_LIVENESS_INTERVAL, TimeUnit.MILLISECONDS)
                                .subscribe(new Consumer() {
                                    @Override
                                    public void accept(Long aLong) {
                                        onFaceFeatureInfoGet(faceFeature, requestId);
                                    }
                                }));
                    }
                    //活体检测失败
                    else {
                        Log.d(TAG, "活体检测失败");
                        requestFeatureStatusMap.put(requestId, CompareResult.NOT_ALIVE);
                    }

                }
                //FR 失败
                else {
                    requestFeatureStatusMap.put(requestId, CompareResult.FAILED);
                }
            }

        };
 ArcCameraListener arcCameraListener = new ArcCameraListener() {
            @Override
            public void onCameraOpened(Camera camera, int cameraId, int displayOrientation, boolean isMirror) {
                Log.i(TAG, "onCameraOpened: " + cameraId + "  " + displayOrientation + " " + isMirror);
                previewSize = camera.getParameters().getPreviewSize();

                drawHelper = new DrawHelper(previewSize.width, previewSize.height, previewView.getWidth(), previewView.getHeight(), displayOrientation
                        , cameraId, isMirror,false,false);
                faceHelper = new FaceHelper.Builder()
                        .faceEngine(faceEngine)
                        .frThreadNum(MAX_DETECT_NUM)
                        .previewSize(previewSize)
                        .faceListener(faceListener)
                        .currentTrackId(ConfigUtil.getTrackId(SignActivity.this.getApplicationContext()))
                        .build();

            }

            @Override
            public void onPreview(byte[] nv21, Camera camera) {

                if (faceRectView != null) {
                    faceRectView.clearFaceInfo();
                }

                if (faceHelper == null) {
                    return;
                }

                final List facePreviewInfoList = faceHelper.onPreviewFrame(nv21);
                if (facePreviewInfoList != null && faceRectView != null && drawHelper != null) {
                    List drawInfoList = new ArrayList<>();
                    boolean isAlive = false;//活体判断
                    //识别有人脸后进入此处,facePreviewInfoList为已注册过的人脸数据
                    for (int i = 0; i < facePreviewInfoList.size(); i++)
                    {
                        String name = faceHelper.getName(facePreviewInfoList.get(i).getTrackId());
                        /*drawInfoList.add(new DrawInfo(facePreviewInfoList.get(i).getFaceInfo().getRect(), GenderInfo.UNKNOWN, AgeInfo.UNKNOWN_AGE, LivenessInfo.UNKNOWN,
                                name == null ? String.valueOf(facePreviewInfoList.get(i).getTrackId()) : name));*/
                        //name 置为空字符,为了人脸识别框上不显示文字

                        drawInfoList.add(new DrawInfo(drawHelper.adjustRect(facePreviewInfoList.get(i).getFaceInfo().getRect()), GenderInfo.UNKNOWN, AgeInfo.UNKNOWN_AGE, facePreviewInfoList.get(i).getLivenessInfo().getLiveness(),
                                ""));
                        isAlive = facePreviewInfoList.get(i).getLivenessInfo().getLiveness() == 1 ? true : false;
                    }
                    drawHelper.draw(faceRectView, drawInfoList);
                }
                clearLeftFace(facePreviewInfoList);
                if (facePreviewInfoList != null && facePreviewInfoList.size() > 0 && previewSize != null) {
                    for (int i = 0; i < facePreviewInfoList.size(); i++) {
                        if (livenessDetect) {
                            livenessMap.put(facePreviewInfoList.get(i).getTrackId(), facePreviewInfoList.get(i).getLivenessInfo().getLiveness());
                        }
                        /**
                         * 对于每个人脸,若状态为空或者为失败,则请求FR(可根据需要添加其他判断以限制FR次数),
                         * FR回传的人脸特征结果在{@link FaceListener#onFaceFeatureInfoGet(FaceFeature, Integer)}中回传
                         */
                        if (requestFeatureStatusMap.get(facePreviewInfoList.get(i).getTrackId()) == null
                                || requestFeatureStatusMap.get(facePreviewInfoList.get(i).getTrackId()) == CompareResult.FAILED) {
                            requestFeatureStatusMap.put(facePreviewInfoList.get(i).getTrackId(), CompareResult.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).getTrackId());
                        }
                    }
                }

            }

            @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 ArcCameraHelper.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(arcCameraListener)
                .build();
        cameraHelper.init();
        cameraHelper.start();

    }
  • 匹配查找人脸
private void searchFace(final FaceFeature frFace, final Integer requestId) {
        Observable
                .create(new ObservableOnSubscribe() {
                    @Override
                    public void subscribe(ObservableEmitter emitter) {
                        Log.i(TAG, "subscribe: fr search start = " + System.currentTimeMillis() + " trackId = " + requestId);
                        Log.i(TAG, "frFace: " + frFace);
                        CompareResult compareResult = FaceServer.getInstance().getTopOfFaceLib(frFace);
                        Log.i(TAG, "searchFace: " + compareResult);
                        Log.i(TAG, "subscribe: fr search end = " + System.currentTimeMillis() + " trackId = " + requestId);
                        if (compareResult == null) {
                            emitter.onError(null);
                        } else {
                            emitter.onNext(compareResult);
                        }
                    }
                })
                .subscribeOn(Schedulers.computation())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(CompareResult compareResult) {//循环录过的所有人脸

                        if (compareResult == null || compareResult.getUserName() == null) {
                            requestFeatureStatusMap.put(requestId, CompareResult.FAILED);
                            faceHelper.addName(requestId, "VISITOR " + requestId);
                            return;
                        }

                        Log.i(TAG, "onNext: fr search get result  = " + System.currentTimeMillis() + " trackId = " + requestId + "  similar = " + compareResult.getSimilar());
                        if (compareResult.getSimilar() > SIMILAR_THRESHOLD) {//在录入过的人脸中对比找出当前人脸
                            boolean isAdded = false;
                            if (compareResultList == null) {
                                requestFeatureStatusMap.put(requestId, CompareResult.FAILED);
                                faceHelper.addName(requestId, "VISITOR " + requestId);
                                return;
                            }
                            for (CompareResult compareResult1 : compareResultList) {
                                if (compareResult1.getTrackId() == requestId) {
                                    isAdded = true;
                                    break;
                                }
                            }
                            if (!isAdded) {
                                //对于多人脸搜索,假如最大显示数量为 MAX_DETECT_NUM 且有新的人脸进入,则以队列的形式移除
                                if (compareResultList.size() >= MAX_DETECT_NUM) {
                                    compareResultList.remove(0);
                                    //adapter.notifyItemRemoved(0);
                                }
                                //添加显示人员时,保存其trackId
                                compareResult.setTrackId(requestId);
                                compareResultList.add(compareResult);
                                //adapter.notifyItemInserted(compareResultList.size() - 1);
                            }
                            requestFeatureStatusMap.put(requestId, CompareResult.SUCCEED);
                            faceHelper.addName(requestId, compareResult.getUserName());

                            sign(compareResult.getUserName(),"name");

                        } else {
                            requestFeatureStatusMap.put(requestId, CompareResult.FAILED);
                            faceHelper.addName(requestId, "VISITOR " + requestId);
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        requestFeatureStatusMap.put(requestId, CompareResult.FAILED);
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }
  • 以上就是人脸识别的核心代码了,我本人也是Android 小白一枚,这也算是我在集成过程中一点小心得而已,本人在集成过程中也遇到了很多的问题,也查找了很多的资料,当然还是觉得的文章最靠谱了,也希望越来越好

你可能感兴趣的:(Android 集成虹软人脸识别SDK的问题)