weimingfei
昨天 ba92b976c7fb9f8bbe4a1bf9d06fa8468d26be58
keyCabinet-android/datalibrary/src/main/java/com/example/datalibrary/manager/FaceSDKManager.java
@@ -55,6 +55,7 @@
    private int mLastFaceId;
    private float threholdScore;
    private String groupId;
    public static volatile int initStatus = SDK_UNACTIVATION;
    public static volatile boolean initModelSuccess = false;
@@ -87,6 +88,14 @@
        faceAuth.setCoreConfigure(BDFaceSDKCommon.BDFaceCoreRunMode.BDFACE_LITE_POWER_NO_BIND, 2);
    }
    public String getGroupId() {
        return groupId;
    }
    public void setGroupId(String groupId) {
        this.groupId = groupId;
    }
    public void setActiveLog(boolean isLog) {
        if (faceAuth != null) {
            if (isLog) {
@@ -96,7 +105,11 @@
            }
        }
    }
    public void destroy(){
        /*if(rgbInstance!=null){
            rgbInstance = null;
        }*/
    }
    public void setCheckMouthMask(boolean checkMouthMask) {
        this.checkMouthMask = checkMouthMask;
    }
@@ -118,7 +131,7 @@
    }
    public void initModel(
        final Context context, BDFaceSDKConfig config, boolean isLog, final SdkInitListener listener) {
            final Context context, BDFaceSDKConfig config, boolean isLog, final SdkInitListener listener) {
        setActiveLog(isLog);
        initModel(context, config, listener);
    }
@@ -144,12 +157,6 @@
        startInitModelTime = System.currentTimeMillis();
    }
    public void destroy(){
        if(rgbInstance!=null){
            rgbInstance = null;
        }
    }
    public FaceCrop getFaceCrop() {
        return faceModel.getFaceCrop();
    }
@@ -168,7 +175,7 @@
    public void initDataBases(Context context) {
        if (FaceApi.getInstance().getmUserNum() != 0) {
            //ToastUtils.toast(context, "人脸库加载中");
            ToastUtils.toast(context, "人脸库加载中");
        }
        emptyFrame();
        // 初始化数据库
@@ -187,23 +194,23 @@
        }
        future3 =
            es3.submit(
                new Runnable() {
                    @Override
                    public void run() {
                        faceModel.getFaceSearch().featureClear();
                        synchronized (faceModel.getFaceSearch()) {
                            List<User> users = FaceApi.getInstance().getAllUserList();
                            for (int i = 0; i < users.size(); i++) {
                                User user = users.get(i);
                                faceModel.getFaceSearch().pushPersonById(user.getId(), user.getFeature());
                es3.submit(
                        new Runnable() {
                            @Override
                            public void run() {
                                faceModel.getFaceSearch().featureClear();
                                synchronized (faceModel.getFaceSearch()) {
                                    List<User> users = FaceApi.getInstance().getAllUserList();
                                    for (int i = 0; i < users.size(); i++) {
                                        User user = users.get(i);
                                        faceModel.getFaceSearch().pushPersonById(user.getId(), user.getFeature());
                                    }
                                    if (FaceApi.getInstance().getmUserNum() != 0) {
                                        ToastUtils.toast(context, "人脸库加载成功");
                                    }
                                }
                            }
                            if (FaceApi.getInstance().getmUserNum() != 0) {
                                //ToastUtils.toast(context, "人脸库加载成功");
                            }
                        }
                    }
                });
                        });
    }
    private void setFail(LivenessModel livenessModel) {
@@ -235,12 +242,12 @@
        // 快速检测获取人脸信息,仅用于绘制人脸框,详细人脸数据后续获取
        FaceInfo[] faceInfos =
            faceModel
                .getFaceTrack()
                .track(
                    BDFaceSDKCommon.DetectType.DETECT_VIS,
                    BDFaceSDKCommon.AlignType.BDFACE_ALIGN_TYPE_RGB_FAST,
                    rgbInstance);
                faceModel
                        .getFaceTrack()
                        .track(
                                BDFaceSDKCommon.DetectType.DETECT_VIS,
                                BDFaceSDKCommon.AlignType.BDFACE_ALIGN_TYPE_RGB_FAST,
                                rgbInstance);
        return faceInfos;
    }
@@ -254,18 +261,18 @@
    private BDFaceImageInstance getBdImage(BDFaceImageConfig bdFaceImageConfig, boolean darkEnhance) {
        BDFaceImageInstance rgbInstance =
            new BDFaceImageInstance(
                bdFaceImageConfig.data,
                bdFaceImageConfig.srcHeight,
                bdFaceImageConfig.srcWidth,
                bdFaceImageConfig.bdFaceImageType,
                bdFaceImageConfig.direction,
                bdFaceImageConfig.mirror);
                new BDFaceImageInstance(
                        bdFaceImageConfig.data,
                        bdFaceImageConfig.srcHeight,
                        bdFaceImageConfig.srcWidth,
                        bdFaceImageConfig.bdFaceImageType,
                        bdFaceImageConfig.direction,
                        bdFaceImageConfig.mirror);
        BDFaceImageInstance rgbInstanceOne;
        // 判断暗光恢复
        if (darkEnhance) {
            rgbInstanceOne = faceModel.getDark().faceDarkEnhance(rgbInstance);
            rgbInstance.destory();
        } else {
            rgbInstanceOne = rgbInstance;
        }
@@ -303,21 +310,10 @@
        }
        AtomicInteger isOutoBoundary = new AtomicInteger();
        BDFaceImageInstance cropInstance =
            faceModel.getFaceCrop().cropFaceByLandmark(imageInstance, landmarks, 2.0f, false, isOutoBoundary);
                faceModel.getFaceCrop().cropFaceByLandmark(imageInstance, landmarks, 2.0f, false, isOutoBoundary);
        return cropInstance;
    }
    private static BDFaceImageInstance rgbInstance =null;
    private LivenessModel livenessModel;
    private String groupId;
    /**
     * 0:管理员,1:用户
     * @param groupId
     */
    public void setGroupId(String groupId){
        this.groupId = groupId;
    }
    /**
     * 检测-活体-特征-人脸检索流程
     *
@@ -328,101 +324,98 @@
     * @param faceDetectCallBack
     */
    public void onDetectCheck(
        final BDFaceImageConfig bdFaceImageConfig,
        final BDFaceImageConfig bdNirFaceImageConfig,
        final BDFaceImageConfig bdDepthFaceImageConfig,
        final BDFaceCheckConfig bdFaceCheckConfig,
        final FaceDetectCallBack faceDetectCallBack) {
            final BDFaceImageConfig bdFaceImageConfig,
            final BDFaceImageConfig bdNirFaceImageConfig,
            final BDFaceImageConfig bdDepthFaceImageConfig,
            final BDFaceCheckConfig bdFaceCheckConfig,
            final FaceDetectCallBack faceDetectCallBack) {
        if (!FaceSDKManager.initModelSuccess) {
            return;
        }
        long startTime = System.currentTimeMillis();
        // 创建检测结果存储数据
        livenessModel = new LivenessModel();
        LivenessModel livenessModel = new LivenessModel();
        // 创建检测对象,如果原始数据YUV,转为算法检测的图片BGR
        // TODO: 用户调整旋转角度和是否镜像,手机和开发版需要动态适配
        //System.out.println("==rgbInstance==>初始化");
        if(rgbInstance!=null){
            rgbInstance.destory();
        }
        rgbInstance = getBdImage(bdFaceImageConfig, bdFaceCheckConfig.darkEnhance);
        BDFaceImageInstance rgbInstance = getBdImage(bdFaceImageConfig, bdFaceCheckConfig.darkEnhance);
        livenessModel.setTestBDFaceImageInstanceDuration(System.currentTimeMillis() - startTime);
        onTrack(
            rgbInstance,
            livenessModel,
            new DetectListener() {
                @Override
                public void onDetectSuccess(FaceInfo[] faceInfos, BDFaceImageInstance rgbInstance) {
                    // 多帧判断
                    if (!frameSelect(faceInfos[0])) {
                        livenessModel.setBdFaceImageInstance(rgbInstance.getImage());
                        if (faceDetectCallBack != null && faceAdoptModel != null) {
                            //System.out.println("==isOk==>多帧判断");
                            faceDetectCallBack.onFaceDetectDarwCallback(livenessModel);
                            faceDetectCallBack.onFaceDetectCallback(faceAdoptModel);
                        }
                rgbInstance,
                livenessModel,
                new DetectListener() {
                    @Override
                    public void onDetectSuccess(FaceInfo[] faceInfos, BDFaceImageInstance rgbInstance) {
                        // 多帧判断
                        if (!frameSelect(faceInfos[0])) {
                            livenessModel.setBdFaceImageInstance(rgbInstance.getImage());
                            if (faceDetectCallBack != null && faceAdoptModel != null) {
                                faceDetectCallBack.onFaceDetectDarwCallback(livenessModel);
                                faceDetectCallBack.onFaceDetectCallback(faceAdoptModel);
                            }
                            rgbInstance.destory();
                        return;
                    }
                    // 保存人脸特征点
                    livenessModel.setLandmarks(faceInfos[0].landmarks);
                    // 保存人脸图片
                    livenessModel.setBdFaceImageInstance(rgbInstance.getImage());
                    // 口罩检测数据
                    if (checkMouthMask) {
                        FaceMouthMask mouthMask = getFaceMouthMask();
                        if (mouthMask != null) {
                            float[] maskScores = mouthMask.checkMask(rgbInstance, faceInfos);
                            if (maskScores != null && maskScores.length > 0) {
                                float maskResult = maskScores[0];
                                Log.d("mouth_mask", "mask_score:" + maskResult);
                                if (livenessModel != null) {
                                    livenessModel.setMouthMaskArray(maskScores);
                            return;
                        }
                        // 保存人脸特征点
                        livenessModel.setLandmarks(faceInfos[0].landmarks);
                        // 保存人脸图片
                        livenessModel.setBdFaceImageInstance(rgbInstance.getImage());
                        // 口罩检测数据
                        if (checkMouthMask) {
                            FaceMouthMask mouthMask = getFaceMouthMask();
                            if (mouthMask != null) {
                                float[] maskScores = mouthMask.checkMask(rgbInstance, faceInfos);
                                if (maskScores != null && maskScores.length > 0) {
                                    float maskResult = maskScores[0];
                                    Log.d("mouth_mask", "mask_score:" + maskResult);
                                    if (livenessModel != null) {
                                        livenessModel.setMouthMaskArray(maskScores);
                                    }
                                }
                            }
                        }
                        // 调用绘制人脸框接口
                        if (faceDetectCallBack != null) {
                            faceDetectCallBack.onFaceDetectDarwCallback(livenessModel);
                        }
                        // 送检识别
                        onLivenessCheck(
                                rgbInstance,
                                bdNirFaceImageConfig,
                                bdDepthFaceImageConfig,
                                bdFaceCheckConfig,
                                livenessModel,
                                startTime,
                                faceDetectCallBack,
                                faceInfos);
                    }
                    // 调用绘制人脸框接口
                    if (faceDetectCallBack != null) {
                        faceDetectCallBack.onFaceDetectDarwCallback(livenessModel);
                    }
                    @Override
                    public void onDetectFail() {
                    // 送检识别
                    onLivenessCheck(
                        rgbInstance,
                        bdNirFaceImageConfig,
                        bdDepthFaceImageConfig,
                        bdFaceCheckConfig,
                        livenessModel,
                        startTime,
                        faceDetectCallBack,
                        faceInfos);
                }
                        emptyFrame();
                        // 流程结束销毁图片,开始下一帧图片检测,否着内存泄露
                        if (faceDetectCallBack != null) {
                            faceDetectCallBack.onFaceDetectCallback(null);
                            livenessModel.setBdFaceImageInstance(rgbInstance.getImage());
                @Override
                public void onDetectFail() {
                    emptyFrame();
                    // 流程结束销毁图片,开始下一帧图片检测,否着内存泄露
                    if (faceDetectCallBack != null) {
                        faceDetectCallBack.onFaceDetectCallback(null);
                        livenessModel.setBdFaceImageInstance(rgbInstance.getImage());
                        //System.out.println("==isOk==>流程结束");
//                        SaveImageManager.getInstance().saveImage(livenessModel, bdFaceCheckConfig.bdLiveConfig);
                        faceDetectCallBack.onFaceDetectDarwCallback(livenessModel);
                        faceDetectCallBack.onTip(0, "未检测到人脸");
                            faceDetectCallBack.onFaceDetectDarwCallback(livenessModel);
                            faceDetectCallBack.onTip(0, "未检测到人脸");
                        }
                        rgbInstance.destory();
                    }
                }
            });
                });
    }
    private float silentLive(
        BDFaceImageInstance rgbInstance,
        BDFaceSDKCommon.LiveType type,
        float[] landmarks,
        List<Boolean> list,
        float liveScore) {
            BDFaceImageInstance rgbInstance,
            BDFaceSDKCommon.LiveType type,
            float[] landmarks,
            List<Boolean> list,
            float liveScore) {
        float score = 0;
        if (landmarks != null) {
            synchronized (faceModel.getFaceLive()) {
@@ -465,11 +458,11 @@
     * @return
     */
    private float[] silentLives(
        BDFaceImageInstance rgbInstance,
        BDFaceSDKCommon.LiveType type,
        FaceInfo[] faceInfos,
        List<Boolean> list,
        float liveScore) {
            BDFaceImageInstance rgbInstance,
            BDFaceSDKCommon.LiveType type,
            FaceInfo[] faceInfos,
            List<Boolean> list,
            float liveScore) {
        float[] scores = {0, 0, 0}; // 最多检测3个人脸
        if (faceInfos != null) {
            synchronized (faceModel.getFaceLive()) {
@@ -478,7 +471,7 @@
                for (int i = 0; i < size; i++) {
                    scores[i] =
                        faceModel.getFaceLive().silentLive(type, rgbInstance, faceInfos[i].landmarks, liveScore);
                            faceModel.getFaceLive().silentLive(type, rgbInstance, faceInfos[i].landmarks, liveScore);
                }
            }
        }
@@ -486,11 +479,11 @@
    }
    private void onDetect(
        BDFaceCheckConfig bdFaceCheckConfig,
        BDFaceImageInstance rgbInstance,
        FaceInfo[] fastFaceInfos,
        LivenessModel livenessModel,
        DetectListener detectListener) {
            BDFaceCheckConfig bdFaceCheckConfig,
            BDFaceImageInstance rgbInstance,
            FaceInfo[] fastFaceInfos,
            LivenessModel livenessModel,
            DetectListener detectListener) {
        long accurateTime = System.currentTimeMillis();
        FaceInfo[] faceInfos;
@@ -498,14 +491,14 @@
        if (bdFaceCheckConfig != null) {
            bdFaceCheckConfig.bdFaceDetectListConfig.usingQuality = true;
            faceInfos =
                faceModel
                    .getFaceDetect()
                    .detect(
                        BDFaceSDKCommon.DetectType.DETECT_VIS,
                        BDFaceSDKCommon.AlignType.BDFACE_ALIGN_TYPE_RGB_ACCURATE,
                        rgbInstance,
                        fastFaceInfos,
                        bdFaceCheckConfig.bdFaceDetectListConfig);
                    faceModel
                            .getFaceDetect()
                            .detect(
                                    BDFaceSDKCommon.DetectType.DETECT_VIS,
                                    BDFaceSDKCommon.AlignType.BDFACE_ALIGN_TYPE_RGB_ACCURATE,
                                    rgbInstance,
                                    fastFaceInfos,
                                    bdFaceCheckConfig.bdFaceDetectListConfig);
        } else {
            faceInfos = faceModel.getFaceDetect().detect(BDFaceSDKCommon.DetectType.DETECT_VIS, rgbInstance);
@@ -514,7 +507,7 @@
        livenessModel.setAccurateTime(System.currentTimeMillis() - accurateTime);
        if (faceInfos == null || faceInfos.length <= 0) {
            rgbInstance.destory();
            detectListener.onDetectFail();
            return;
        }
@@ -543,100 +536,101 @@
     * @param faceDetectCallBack
     */
    public void onLivenessCheck(
        final BDFaceImageInstance rgbInstance,
        final BDFaceImageConfig nirBDFaceImageConfig,
        final BDFaceImageConfig depthBDFaceImageConfig,
        final BDFaceCheckConfig bdFaceCheckConfig,
        final LivenessModel livenessModel,
        final long startTime,
        final FaceDetectCallBack faceDetectCallBack,
        final FaceInfo[] fastFaceInfos) {
            final BDFaceImageInstance rgbInstance,
            final BDFaceImageConfig nirBDFaceImageConfig,
            final BDFaceImageConfig depthBDFaceImageConfig,
            final BDFaceCheckConfig bdFaceCheckConfig,
            final LivenessModel livenessModel,
            final long startTime,
            final FaceDetectCallBack faceDetectCallBack,
            final FaceInfo[] fastFaceInfos) {
        if (future2 != null && !future2.isDone()) {
            // 流程结束销毁图片,开始下一帧图片检测,否着内存泄露
            //future2.cancel(true);
            //System.out.println("==isOk==>之前没结束");
            rgbInstance.destory();
            return;
        }
        future2 =
            es2.submit(
                new Runnable() {
                es2.submit(
                        new Runnable() {
                    @Override
                    public void run() {
                            @Override
                            public void run() {
                        // 获取BDFaceCheckConfig配置信息
                        if (bdFaceCheckConfig == null) {
                                // 获取BDFaceCheckConfig配置信息
                                if (bdFaceCheckConfig == null) {
                                    rgbInstance.destory();
                            return;
                        }
                        onDetect(
                            bdFaceCheckConfig,
                            rgbInstance,
                            fastFaceInfos,
                            livenessModel,
                            new DetectListener() {
                                    return;
                                }
                                onDetect(
                                        bdFaceCheckConfig,
                                        rgbInstance,
                                        fastFaceInfos,
                                        livenessModel,
                                        new DetectListener() {
                                @Override
                                public void onDetectSuccess(FaceInfo[] faceInfos, BDFaceImageInstance rgbInstance) {
                                            @Override
                                            public void onDetectSuccess(FaceInfo[] faceInfos, BDFaceImageInstance rgbInstance) {
                                    // 人脸id赋值
                                    if (mLastFaceId != fastFaceInfos[0].faceID) {
                                        mLastFaceId = fastFaceInfos[0].faceID;
                                        mRgbLiveList.clear();
                                        mNirLiveList.clear();
                                    }
                                                // 人脸id赋值
                                                if (mLastFaceId != fastFaceInfos[0].faceID) {
                                                    mLastFaceId = fastFaceInfos[0].faceID;
                                                    mRgbLiveList.clear();
                                                    mNirLiveList.clear();
                                                }
                                    if (bdFaceCheckConfig == null) {
                                                if (bdFaceCheckConfig == null) {
                                                    rgbInstance.destory();
                                                    livenessModel.clearIdentifyResults();
                                                    if (faceDetectCallBack != null) {
                                                        faceDetectCallBack.onFaceDetectCallback(livenessModel);
                                                    }
                                                    return;
                                                }
                                        livenessModel.clearIdentifyResults();
                                        if (faceDetectCallBack != null) {
                                            faceDetectCallBack.onFaceDetectCallback(livenessModel);
                                        }
                                        return;
                                    }
                                                // 最优人脸控制
                                                if (!onBestImageCheck(livenessModel, bdFaceCheckConfig, faceDetectCallBack)) {
                                                    livenessModel.setQualityCheck(true);
                                                    livenessModel.clearIdentifyResults();
                                                    rgbInstance.destory();
                                                    if (faceDetectCallBack != null) {
                                                        faceDetectCallBack.onFaceDetectCallback(livenessModel);
                                                    }
                                                    return;
                                                }
                                    // 最优人脸控制
                                    if (!onBestImageCheck(livenessModel, bdFaceCheckConfig, faceDetectCallBack)) {
                                        livenessModel.setQualityCheck(true);
                                        livenessModel.clearIdentifyResults();
                                                // 质量检测未通过,销毁BDFaceImageInstance,结束函数
                                        if (faceDetectCallBack != null) {
                                            faceDetectCallBack.onFaceDetectCallback(livenessModel);
                                        }
                                        return;
                                    }
                                                if (!onQualityCheck(
                                                        faceInfos, bdFaceCheckConfig.bdQualityConfig, faceDetectCallBack)) {
                                                    livenessModel.setQualityCheck(true);
                                                    livenessModel.clearIdentifyResults();
                                                    rgbInstance.destory();
                                                    if (faceDetectCallBack != null) {
                                                        faceDetectCallBack.onFaceDetectCallback(livenessModel);
                                                    }
                                    // 质量检测未通过,销毁BDFaceImageInstance,结束函数
                                                    return;
                                                }
                                    if (!onQualityCheck(
                                            faceInfos, bdFaceCheckConfig.bdQualityConfig, faceDetectCallBack)) {
                                        livenessModel.setQualityCheck(true);
                                        livenessModel.clearIdentifyResults();
                                                livenessModel.setQualityCheck(false);
                                                // 获取LivenessConfig liveCheckMode 配置选项:【不使用活体:0】;【RGB活体:1】;【RGB+NIR活体:2】;【RGB+Depth活体:3】;【RGB+NIR+Depth活体:4】
                                                // TODO 活体检测
                                                float[] rgbScores = {-1};
                                                BDLiveConfig bdLiveConfig = bdFaceCheckConfig.bdLiveConfig;
                                                boolean isLiveCheck = bdFaceCheckConfig.bdLiveConfig != null;
                                        if (faceDetectCallBack != null) {
                                            faceDetectCallBack.onFaceDetectCallback(livenessModel);
                                        }
                                        return;
                                    }
                                    livenessModel.setQualityCheck(false);
                                    // 获取LivenessConfig liveCheckMode 配置选项:【不使用活体:0】;【RGB活体:1】;【RGB+NIR活体:2】;【RGB+Depth活体:3】;【RGB+NIR+Depth活体:4】
                                    // TODO 活体检测
                                    float[] rgbScores = {-1};
                                    BDLiveConfig bdLiveConfig = bdFaceCheckConfig.bdLiveConfig;
                                    boolean isLiveCheck = bdFaceCheckConfig.bdLiveConfig != null;
                                    if (isLiveCheck) {
                                        long startRgbTime = System.currentTimeMillis();
                                        rgbScores =
                                            silentLives(
                                                rgbInstance,
                                                BDFaceSDKCommon.LiveType.BDFACE_SILENT_LIVE_TYPE_RGB,
                                                faceInfos,
                                                mRgbLiveList,
                                                bdLiveConfig.rgbLiveScore);
                                                if (isLiveCheck) {
                                                    long startRgbTime = System.currentTimeMillis();
                                                    rgbScores =
                                                            silentLives(
                                                                    rgbInstance,
                                                                    BDFaceSDKCommon.LiveType.BDFACE_SILENT_LIVE_TYPE_RGB,
                                                                    faceInfos,
                                                                    mRgbLiveList,
                                                                    bdLiveConfig.rgbLiveScore);
                                        /* if (rgbScores != null){
                                            int size = rgbScores.length;
                                            Log.d("Attend", "score size:" + size);
@@ -645,222 +639,223 @@
                                            }
                                        } */
                                        if (faceInfos.length == 1) {
                                            livenessModel.setRgbLivenessScore(rgbScores[0]);
                                        }
                                        livenessModel.setRgbLivenessScores(rgbScores);
                                        livenessModel.setRgbLivenessDuration(System.currentTimeMillis() - startRgbTime);
                                    }
                                                    if (faceInfos.length == 1) {
                                                        livenessModel.setRgbLivenessScore(rgbScores[0]);
                                                    }
                                                    livenessModel.setRgbLivenessScores(rgbScores);
                                                    livenessModel.setRgbLivenessDuration(System.currentTimeMillis() - startRgbTime);
                                                }
                                    // TODO nir活体检测
                                    float nirScore = -1;
                                    FaceInfo[] faceInfosIr = null;
                                    BDFaceImageInstance nirInstance = null;
                                    boolean isHaveNirImage = nirBDFaceImageConfig != null && isLiveCheck;
                                    if (isHaveNirImage) {
                                        // 创建检测对象,如果原始数据YUV-IR,转为算法检测的图片BGR
                                        // TODO: 用户调整旋转角度和是否镜像,手机和开发版需要动态适配
                                        long nirInstanceTime = System.currentTimeMillis();
                                        nirInstance = getBdImage(nirBDFaceImageConfig, false);
                                                // TODO nir活体检测
                                                float nirScore = -1;
                                                FaceInfo[] faceInfosIr = null;
                                                BDFaceImageInstance nirInstance = null;
                                                boolean isHaveNirImage = nirBDFaceImageConfig != null && isLiveCheck;
                                                if (isHaveNirImage) {
                                                    // 创建检测对象,如果原始数据YUV-IR,转为算法检测的图片BGR
                                                    // TODO: 用户调整旋转角度和是否镜像,手机和开发版需要动态适配
                                                    long nirInstanceTime = System.currentTimeMillis();
                                                    nirInstance = getBdImage(nirBDFaceImageConfig, false);
                                        livenessModel.setBdNirFaceImageInstance(nirInstance.getImage());
                                        livenessModel.setNirInstanceTime(System.currentTimeMillis() - nirInstanceTime);
                                                    livenessModel.setBdNirFaceImageInstance(nirInstance.getImage());
                                                    livenessModel.setNirInstanceTime(System.currentTimeMillis() - nirInstanceTime);
                                        // 避免RGB检测关键点在IR对齐活体稳定,增加红外检测
                                        long startIrDetectTime = System.currentTimeMillis();
                                        BDFaceDetectListConf bdFaceDetectListConf = new BDFaceDetectListConf();
                                        bdFaceDetectListConf.usingDetect = true;
                                        faceInfosIr =
                                            faceModel
                                                .getFaceNirDetect()
                                                .detect(
                                                    BDFaceSDKCommon.DetectType.DETECT_NIR,
                                                    BDFaceSDKCommon.AlignType.BDFACE_ALIGN_TYPE_NIR_ACCURATE,
                                                    nirInstance,
                                                    null,
                                                    bdFaceDetectListConf);
                                        livenessModel.setIrLivenessDuration(
                                            System.currentTimeMillis() - startIrDetectTime);
                                        //                    LogUtils.e(TIME_TAG, "detect ir time = " + livenessModel.getIrLivenessDuration());
                                        if (faceInfosIr != null && faceInfosIr.length > 0) {
                                            FaceInfo faceInfoIr = faceInfosIr[0];
                                            nirScore =
                                                silentLive(
                                                    nirInstance,
                                                    BDFaceSDKCommon.LiveType.BDFACE_SILENT_LIVE_TYPE_NIR,
                                                    faceInfoIr.landmarks,
                                                    mNirLiveList,
                                                    bdLiveConfig.nirLiveScore);
                                            livenessModel.setIrLivenessScore(nirScore);
                                            //                        LogUtils.e(TIME_TAG, "live ir time = " + livenessModel.getIrLivenessDuration());
                                        }
                                    }
                                                    // 避免RGB检测关键点在IR对齐活体稳定,增加红外检测
                                                    long startIrDetectTime = System.currentTimeMillis();
                                                    BDFaceDetectListConf bdFaceDetectListConf = new BDFaceDetectListConf();
                                                    bdFaceDetectListConf.usingDetect = true;
                                                    faceInfosIr =
                                                            faceModel
                                                                    .getFaceNirDetect()
                                                                    .detect(
                                                                            BDFaceSDKCommon.DetectType.DETECT_NIR,
                                                                            BDFaceSDKCommon.AlignType.BDFACE_ALIGN_TYPE_NIR_ACCURATE,
                                                                            nirInstance,
                                                                            null,
                                                                            bdFaceDetectListConf);
                                                    livenessModel.setIrLivenessDuration(
                                                            System.currentTimeMillis() - startIrDetectTime);
                                                    //                    LogUtils.e(TIME_TAG, "detect ir time = " + livenessModel.getIrLivenessDuration());
                                                    if (faceInfosIr != null && faceInfosIr.length > 0) {
                                                        FaceInfo faceInfoIr = faceInfosIr[0];
                                                        nirScore =
                                                                silentLive(
                                                                        nirInstance,
                                                                        BDFaceSDKCommon.LiveType.BDFACE_SILENT_LIVE_TYPE_NIR,
                                                                        faceInfoIr.landmarks,
                                                                        mNirLiveList,
                                                                        bdLiveConfig.nirLiveScore);
                                                        livenessModel.setIrLivenessScore(nirScore);
                                                        //                        LogUtils.e(TIME_TAG, "live ir time = " + livenessModel.getIrLivenessDuration());
                                                    }
                                                }
                                    // TODO depth活体检测
                                    float depthScore = -1;
                                    boolean isHaveDepthImage = depthBDFaceImageConfig != null && isLiveCheck;
                                    if (depthBDFaceImageConfig != null) {
                                        // TODO: 用户调整旋转角度和是否镜像,适配Atlas 镜头,目前宽和高400*640,其他摄像头需要动态调整,人脸72 个关键点x 坐标向左移动80个像素点
                                        float[] depthLandmark = new float[faceInfos[0].landmarks.length];
                                        BDFaceImageInstance depthInstance;
                                        if (bdFaceCheckConfig.cameraType == 1) {
                                            System.arraycopy(
                                                faceInfos[0].landmarks,
                                                0,
                                                depthLandmark,
                                                0,
                                                faceInfos[0].landmarks.length);
                                            for (int i = 0; i < 144; i = i + 2) {
                                                depthLandmark[i] -= 80;
                                            }
                                        } else {
                                            depthLandmark = faceInfos[0].landmarks;
                                        }
                                        depthInstance = getBdImage(depthBDFaceImageConfig, false);
                                        livenessModel.setBdDepthFaceImageInstance(depthInstance.getImage());
                                        // 创建检测对象,如果原始数据Depth
                                        long startDepthTime = System.currentTimeMillis();
                                        depthScore =
                                            faceModel
                                                .getFaceLive()
                                                .silentLive(
                                                    BDFaceSDKCommon.LiveType.BDFACE_SILENT_LIVE_TYPE_DEPTH,
                                                    depthInstance,
                                                    depthLandmark);
                                        livenessModel.setDepthLivenessScore(depthScore);
                                        livenessModel.setDepthtLivenessDuration(
                                            System.currentTimeMillis() - startDepthTime);
                                        //                    LogUtils.e(TIME_TAG, "live depth time = " + livenessModel.getDepthtLivenessDuration());
                                        depthInstance.destory();
                                    }
                                                // TODO depth活体检测
                                                float depthScore = -1;
                                                boolean isHaveDepthImage = depthBDFaceImageConfig != null && isLiveCheck;
                                                if (depthBDFaceImageConfig != null) {
                                                    // TODO: 用户调整旋转角度和是否镜像,适配Atlas 镜头,目前宽和高400*640,其他摄像头需要动态调整,人脸72 个关键点x 坐标向左移动80个像素点
                                                    float[] depthLandmark = new float[faceInfos[0].landmarks.length];
                                                    BDFaceImageInstance depthInstance;
                                                    if (bdFaceCheckConfig.cameraType == 1) {
                                                        System.arraycopy(
                                                                faceInfos[0].landmarks,
                                                                0,
                                                                depthLandmark,
                                                                0,
                                                                faceInfos[0].landmarks.length);
                                                        for (int i = 0; i < 144; i = i + 2) {
                                                            depthLandmark[i] -= 80;
                                                        }
                                                    } else {
                                                        depthLandmark = faceInfos[0].landmarks;
                                                    }
                                                    depthInstance = getBdImage(depthBDFaceImageConfig, false);
                                                    livenessModel.setBdDepthFaceImageInstance(depthInstance.getImage());
                                                    // 创建检测对象,如果原始数据Depth
                                                    long startDepthTime = System.currentTimeMillis();
                                                    depthScore =
                                                            faceModel
                                                                    .getFaceLive()
                                                                    .silentLive(
                                                                            BDFaceSDKCommon.LiveType.BDFACE_SILENT_LIVE_TYPE_DEPTH,
                                                                            depthInstance,
                                                                            depthLandmark);
                                                    livenessModel.setDepthLivenessScore(depthScore);
                                                    livenessModel.setDepthtLivenessDuration(
                                                            System.currentTimeMillis() - startDepthTime);
                                                    //                    LogUtils.e(TIME_TAG, "live depth time = " + livenessModel.getDepthtLivenessDuration());
                                                    depthInstance.destory();
                                                }
                                    boolean isRgbScoreCheck = false;
                                    boolean isNirScoreCheck = false;
                                    boolean isDepthScoreCheck = false;
                                    if (isLiveCheck) {
                                        int size = rgbScores.length;
                                        for (int i = 0; i < size; i++) {
                                            if (rgbScores[i] > bdLiveConfig.rgbLiveScore) {
                                                isRgbScoreCheck = true;
                                            }
                                        }
                                        // isRgbScoreCheck = true; // liujinhui for test
                                        //   isRgbScoreCheck = (rgbScores[0] > bdLiveConfig.rgbLiveScore);
                                        isNirScoreCheck =
                                            (isHaveNirImage ? nirScore > bdLiveConfig.nirLiveScore : true);
                                        isDepthScoreCheck =
                                            (isHaveDepthImage ? depthScore > bdLiveConfig.depthLiveScore : true);
                                    }
                                                boolean isRgbScoreCheck = false;
                                                boolean isNirScoreCheck = false;
                                                boolean isDepthScoreCheck = false;
                                                if (isLiveCheck) {
                                                    int size = rgbScores.length;
                                                    for (int i = 0; i < size; i++) {
                                                        if (rgbScores[i] > bdLiveConfig.rgbLiveScore) {
                                                            isRgbScoreCheck = true;
                                                        }
                                                    }
                                                    // isRgbScoreCheck = true; // liujinhui for test
                                                    //   isRgbScoreCheck = (rgbScores[0] > bdLiveConfig.rgbLiveScore);
                                                    isNirScoreCheck =
                                                            (isHaveNirImage ? nirScore > bdLiveConfig.nirLiveScore : true);
                                                    isDepthScoreCheck =
                                                            (isHaveDepthImage ? depthScore > bdLiveConfig.depthLiveScore : true);
                                                }
                                    // 如果设置为不进行活体检测
                                    int liveCheckMode = livenessModel.getLiveType();
                                    if (liveCheckMode == 0){
                                        isRgbScoreCheck = true;
                                    }
                                    // TODO 特征提取+人脸检索
                                    if (!isLiveCheck || (isRgbScoreCheck && isNirScoreCheck && isDepthScoreCheck)) {
                                        if (livenessModel != null) {
                                            livenessModel.clearIdentifyResults();
                                            livenessModel.setUser(null);
                                        }
                                        synchronized (faceModel.getFaceSearch()) {
                                            if (faceInfos != null) {
                                                int size = faceInfos.length;
                                                for (int i = 0; i < size; i++) {
                                                    // 特征提取
                                                    // 模糊结果过滤,戴口罩时候,不进行过滤
                                                    if (!checkMouthMask) {
                                                        float blur = faceInfos[i].bluriness;
                                                        BDFaceOcclusion occlusion = faceInfos[i].occlusion;
                                                        float leftEye = occlusion.leftEye;
                                                        // "左眼遮挡"
                                                        float rightEye = occlusion.rightEye;
                                                        // "右眼遮挡"
                                                        float nose = occlusion.nose;
                                                        // "鼻子遮挡置信度"
                                                        float mouth = occlusion.mouth;
                                                        // "嘴巴遮挡置信度"
                                                        float leftCheek = occlusion.leftCheek;
                                                        // "左脸遮挡"
                                                        float rightCheek = occlusion.rightCheek;
                                                        // "右脸遮挡"
                                                        float chin = occlusion.chin;
                                                        // 动态底库限制
                                                        faceModel
                                                                .getFaceSearch()
                                                                .setNeedJoinDB(
                                                                        selectQuality(
                                                                                blur,
                                                                                leftEye,
                                                                                rightEye,
                                                                                nose,
                                                                                mouth,
                                                                                leftCheek,
                                                                                rightCheek,
                                                                                chin));
                                                // 如果设置为不进行活体检测
                                                int liveCheckMode = livenessModel.getLiveType();
                                                if (liveCheckMode == 0){
                                                    isRgbScoreCheck = true;
                                                }
                                                // TODO 特征提取+人脸检索
                                                if (!isLiveCheck || (isRgbScoreCheck && isNirScoreCheck && isDepthScoreCheck)) {
                                                    if (livenessModel != null) {
                                                        livenessModel.clearIdentifyResults();
                                                        livenessModel.setUser(null);
                                                    }
                                                    if (bdLiveConfig != null){
                                                        onFeatureChecks(
                                                                i,
                                                                rgbInstance,
                                                                bdFaceCheckConfig,
                                                                faceInfos,
                                                                faceInfosIr,
                                                                nirInstance,
                                                                livenessModel,
                                                                bdFaceCheckConfig.secondFeature,
                                                                bdFaceCheckConfig.featureCheckMode,
                                                                bdFaceCheckConfig.activeModel,
                                                                rgbScores,
                                                                bdLiveConfig.rgbLiveScore);
                                                    } else{
                                                        onFeatureChecks(
                                                                i,
                                                                rgbInstance,
                                                                bdFaceCheckConfig,
                                                                faceInfos,
                                                                faceInfosIr,
                                                                nirInstance,
                                                                livenessModel,
                                                                bdFaceCheckConfig.secondFeature,
                                                                bdFaceCheckConfig.featureCheckMode,
                                                                bdFaceCheckConfig.activeModel,
                                                                rgbScores,
                                                                -1);
                                                    }
                                                    synchronized (faceModel.getFaceSearch()) {
                                                        if (faceInfos != null) {
                                                            int size = faceInfos.length;
                                                            for (int i = 0; i < size; i++) {
                                                                // 特征提取
                                                                // 模糊结果过滤,戴口罩时候,不进行过滤
                                                                if (!checkMouthMask) {
                                                                    float blur = faceInfos[i].bluriness;
                                                                    BDFaceOcclusion occlusion = faceInfos[i].occlusion;
                                                                    float leftEye = occlusion.leftEye;
                                                                    // "左眼遮挡"
                                                                    float rightEye = occlusion.rightEye;
                                                                    // "右眼遮挡"
                                                                    float nose = occlusion.nose;
                                                                    // "鼻子遮挡置信度"
                                                                    float mouth = occlusion.mouth;
                                                                    // "嘴巴遮挡置信度"
                                                                    float leftCheek = occlusion.leftCheek;
                                                                    // "左脸遮挡"
                                                                    float rightCheek = occlusion.rightCheek;
                                                                    // "右脸遮挡"
                                                                    float chin = occlusion.chin;
                                                                    // 动态底库限制
                                                                    faceModel
                                                                            .getFaceSearch()
                                                                            .setNeedJoinDB(
                                                                                    selectQuality(
                                                                                            blur,
                                                                                            leftEye,
                                                                                            rightEye,
                                                                                            nose,
                                                                                            mouth,
                                                                                            leftCheek,
                                                                                            rightCheek,
                                                                                            chin));
                                                                }
                                                                if (bdLiveConfig != null){
                                                                    onFeatureChecks(
                                                                            i,
                                                                            rgbInstance,
                                                                            bdFaceCheckConfig,
                                                                            faceInfos,
                                                                            faceInfosIr,
                                                                            nirInstance,
                                                                            livenessModel,
                                                                            bdFaceCheckConfig.secondFeature,
                                                                            bdFaceCheckConfig.featureCheckMode,
                                                                            bdFaceCheckConfig.activeModel,
                                                                            rgbScores,
                                                                            bdLiveConfig.rgbLiveScore);
                                                                }
                                                                else{
                                                                    onFeatureChecks(
                                                                            i,
                                                                            rgbInstance,
                                                                            bdFaceCheckConfig,
                                                                            faceInfos,
                                                                            faceInfosIr,
                                                                            nirInstance,
                                                                            livenessModel,
                                                                            bdFaceCheckConfig.secondFeature,
                                                                            bdFaceCheckConfig.featureCheckMode,
                                                                            bdFaceCheckConfig.activeModel,
                                                                            rgbScores,
                                                                            -1);
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                                // 流程结束,记录最终时间
                                                livenessModel.setAllDetectDuration(System.currentTimeMillis() - startTime);
                                                //                LogUtils.e(TIME_TAG, "all process time = " + livenessModel.getAllDetectDuration());
                                                // 流程结束销毁图片,开始下一帧图片检测,否着内存泄露
                                                rgbInstance.destory();
                                                if (nirInstance != null) {
                                                    nirInstance.destory();
                                                }
                                                // 显示最终结果提示
                                                if (faceDetectCallBack != null) {
                                                    faceDetectCallBack.onFaceDetectCallback(livenessModel);
                                                }
                                            }
                                        }
                                    }
                                    // 流程结束,记录最终时间
                                    livenessModel.setAllDetectDuration(System.currentTimeMillis() - startTime);
                                    //                LogUtils.e(TIME_TAG, "all process time = " + livenessModel.getAllDetectDuration());
                                    // 流程结束销毁图片,开始下一帧图片检测,否着内存泄露
                                            @Override
                                            public void onDetectFail() {
                                    if (nirInstance != null) {
                                        nirInstance.destory();
                                    }
                                    // 显示最终结果提示
                                    if (faceDetectCallBack != null) {
                                        faceDetectCallBack.onFaceDetectCallback(livenessModel);
                                    }
                                }
                                @Override
                                public void onDetectFail() {
                                    if (faceDetectCallBack != null) {
                                        faceDetectCallBack.onFaceDetectCallback(livenessModel);
                                    }
                                }
                            });
                    }
                });
                                                if (faceDetectCallBack != null) {
                                                    faceDetectCallBack.onFaceDetectCallback(livenessModel);
                                                }
                                            }
                                        });
                            }
                        });
    }
    /**
@@ -871,7 +866,7 @@
     * @return
     */
    public boolean onBestImageCheck(
        LivenessModel livenessModel, BDFaceCheckConfig bdFaceCheckConfig, FaceDetectCallBack faceDetectCallBack) {
            LivenessModel livenessModel, BDFaceCheckConfig bdFaceCheckConfig, FaceDetectCallBack faceDetectCallBack) {
        boolean isBestImageCheck = false;
        if (livenessModel != null && livenessModel.getFaceInfos() != null) {
            FaceInfo[] faceInfos = livenessModel.getFaceInfos();
@@ -898,15 +893,15 @@
     * @param featureType      特征抽取模态执行 【生活照:1】;【证件照:2】;【混合模态:3】;
     */
    private void onFeatureCheck(
        BDFaceImageInstance rgbInstance,
        BDFaceCheckConfig bdFaceCheckConfig,
        float[] landmark,
        FaceInfo[] faceInfos,
        BDFaceImageInstance nirInstance,
        LivenessModel livenessModel,
        byte[] secondFeature,
        final int featureCheckMode,
        final int featureType) {
            BDFaceImageInstance rgbInstance,
            BDFaceCheckConfig bdFaceCheckConfig,
            float[] landmark,
            FaceInfo[] faceInfos,
            BDFaceImageInstance nirInstance,
            LivenessModel livenessModel,
            byte[] secondFeature,
            final int featureCheckMode,
            final int featureType) {
        // 如果不抽取特征,直接返回
        if (featureCheckMode == 1) {
            return;
@@ -920,9 +915,9 @@
            BDQualityConfig bdQualityConfig = bdFaceCheckConfig.bdQualityConfig;
            boolean isIllum = bdQualityConfig != null ? illumScore < bdQualityConfig.illum : false;
            BDFaceSDKCommon.FeatureType type =
                isIllum
                    ? BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_NIR
                    : BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO;
                    isIllum
                            ? BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_NIR
                            : BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO;
            BDFaceImageInstance bdFaceImageInstance = isIllum ? nirInstance : rgbInstance;
            float[] landmarks = isIllum ? faceInfos[0].landmarks : landmark;
@@ -932,33 +927,33 @@
            livenessModel.setFeature(feature);
            // 人脸检索
            featureSearch(
                featureCheckMode,
                livenessModel,
                bdFaceCheckConfig,
                feature,
                secondFeature,
                featureSize,
                BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO);
                    featureCheckMode,
                    livenessModel,
                    bdFaceCheckConfig,
                    feature,
                    secondFeature,
                    featureSize,
                    BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO);
        } else {
            // 生活照检索
            long startFeatureTime = System.currentTimeMillis();
            float featureSize =
                faceModel
                    .getFaceFeature()
                    .feature(
                        BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO, rgbInstance, landmark, feature);
                    faceModel
                            .getFaceFeature()
                            .feature(
                                    BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO, rgbInstance, landmark, feature);
            livenessModel.setFeatureDuration(System.currentTimeMillis() - startFeatureTime);
            livenessModel.setFeature(feature);
            livenessModel.setFeatureDuration(System.currentTimeMillis() - startFeatureTime);
            // 人脸检索
            featureSearch(
                featureCheckMode,
                livenessModel,
                bdFaceCheckConfig,
                feature,
                secondFeature,
                featureSize,
                BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO);
                    featureCheckMode,
                    livenessModel,
                    bdFaceCheckConfig,
                    feature,
                    secondFeature,
                    featureSize,
                    BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO);
        }
    }
@@ -976,21 +971,22 @@
     * @param liveScore 可见光活体阈值
     */
    private void onFeatureChecks(
        int index,
        BDFaceImageInstance rgbInstance,
        BDFaceCheckConfig bdFaceCheckConfig,
        FaceInfo[] rgbFaceInfos,
        FaceInfo[] faceInfos,
        BDFaceImageInstance nirInstance,
        LivenessModel livenessModel,
        byte[] secondFeature,
        final int featureCheckMode,
        final int featureType,
        float[] rgbScores,
        float liveScore) {
            int index,
            BDFaceImageInstance rgbInstance,
            BDFaceCheckConfig bdFaceCheckConfig,
            FaceInfo[] rgbFaceInfos,
            FaceInfo[] faceInfos,
            BDFaceImageInstance nirInstance,
            LivenessModel livenessModel,
            byte[] secondFeature,
            final int featureCheckMode,
            final int featureType,
            float[] rgbScores,
            float liveScore) {
        // 如果不抽取特征,直接返回
        if (featureCheckMode == 1) {
            return;
        }
        byte[] feature = new byte[512];
@@ -1003,9 +999,9 @@
            BDQualityConfig bdQualityConfig = bdFaceCheckConfig.bdQualityConfig;
            boolean isIllum = bdQualityConfig != null ? illumScore < bdQualityConfig.illum : false;
            BDFaceSDKCommon.FeatureType type =
                isIllum
                    ? BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_NIR
                    : BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO;
                    isIllum
                            ? BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_NIR
                            : BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO;
            BDFaceImageInstance bdFaceImageInstance = isIllum ? nirInstance : rgbInstance;
            if (rgbFaceInfos == null) {
@@ -1032,19 +1028,20 @@
            livenessModel.setFeature(feature);
            // 人脸检索
            featureSearchs(
                index,
                featureCheckMode,
                livenessModel,
                bdFaceCheckConfig,
                feature,
                secondFeature,
                featureSize,
                BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO);
                    index,
                    featureCheckMode,
                    livenessModel,
                    bdFaceCheckConfig,
                    feature,
                    secondFeature,
                    featureSize,
                    BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO);
        } else {
            // 生活照检索
            long startFeatureTime = System.currentTimeMillis();
            if (rgbFaceInfos == null) {
                return;
            }
@@ -1062,27 +1059,28 @@
            }
            float featureSize =
                faceModel
                    .getFaceFeature()
                    .feature(
                        BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO,
                        rgbInstance,
                        rgbFaceInfos[index].landmarks,
                        feature);
                    faceModel
                            .getFaceFeature()
                            .feature(
                                    BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO,
                                    rgbInstance,
                                    rgbFaceInfos[index].landmarks,
                                    feature);
            livenessModel.setFeatureDuration(System.currentTimeMillis() - startFeatureTime);
            livenessModel.setFeature(feature);
            livenessModel.setFeatureDuration(System.currentTimeMillis() - startFeatureTime);
            // 人脸检索
            featureSearchs(
                index,
                featureCheckMode,
                livenessModel,
                bdFaceCheckConfig,
                feature,
                secondFeature,
                featureSize,
                BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO);
                    index,
                    featureCheckMode,
                    livenessModel,
                    bdFaceCheckConfig,
                    feature,
                    secondFeature,
                    featureSize,
                    BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO);
        }
    }
@@ -1097,13 +1095,13 @@
     * @param type             特征提取类型
     */
    private void featureSearch(
        final int featureCheckMode,
        LivenessModel livenessModel,
        BDFaceCheckConfig bdFaceCheckConfig,
        byte[] feature,
        byte[] secondFeature,
        float featureSize,
        BDFaceSDKCommon.FeatureType type) {
            final int featureCheckMode,
            LivenessModel livenessModel,
            BDFaceCheckConfig bdFaceCheckConfig,
            byte[] feature,
            byte[] secondFeature,
            float featureSize,
            BDFaceSDKCommon.FeatureType type) {
        // 如果只提去特征,不做检索,此处返回
        if (featureCheckMode == 2) {
@@ -1117,7 +1115,7 @@
            // TODO 阈值可以根据不同模型调整
            if (featureCheckMode == 3) {
                List<? extends Feature> featureResult =
                    faceModel.getFaceSearch().search(type, bdFaceCheckConfig.scoreThreshold, 1, feature, false);
                        faceModel.getFaceSearch().search(type, bdFaceCheckConfig.scoreThreshold, 1, feature, false);
                // TODO 返回top num = 1 个数据集合,此处可以任意设置,会返回比对从大到小排序的num 个数据集合
                if (featureResult != null && featureResult.size() > 0) {
@@ -1150,13 +1148,13 @@
            } else if (featureCheckMode == 4) {
                // 目前仅支持
                float score =
                    faceModel
                        .getFaceSearch()
                        .compare(
                            BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_ID_PHOTO,
                            livenessModel.getFeature(),
                            secondFeature,
                            true);
                        faceModel
                                .getFaceSearch()
                                .compare(
                                        BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_ID_PHOTO,
                                        livenessModel.getFeature(),
                                        secondFeature,
                                        true);
                livenessModel.setScore(score);
                if (score > threholdScore) {
                    /*faceId = livenessModel.getFaceInfo().faceID;
@@ -1184,14 +1182,14 @@
     * @param type             特征提取类型
     */
    private void featureSearchs(
        final int index,
        final int featureCheckMode,
        LivenessModel livenessModel,
        BDFaceCheckConfig bdFaceCheckConfig,
        byte[] feature,
        byte[] secondFeature,
        float featureSize,
        BDFaceSDKCommon.FeatureType type) {
            final int index,
            final int featureCheckMode,
            LivenessModel livenessModel,
            BDFaceCheckConfig bdFaceCheckConfig,
            byte[] feature,
            byte[] secondFeature,
            float featureSize,
            BDFaceSDKCommon.FeatureType type) {
        // 如果只提去特征,不做检索,此处返回
@@ -1199,40 +1197,46 @@
            livenessModel.setFeatureCode(featureSize);
            return;
        }
        // 如果提取特征+检索,调用search 方法
        if (featureSize == FEATURE_SIZE / 4) {
            long startFeature = System.currentTimeMillis();
            // 特征提取成功
            // TODO 阈值可以根据不同模型调整
            if (featureCheckMode == 3) {
                //System.out.println("==isOk==>44");
                List<? extends Feature> featureResult =
                    faceModel.getFaceSearch().search(type, bdFaceCheckConfig.scoreThreshold, 5, feature, false);
                //System.out.println("==isOk==>45");
                        faceModel.getFaceSearch().search(type, bdFaceCheckConfig.scoreThreshold, 2, feature, false);
                // TODO 返回top num = 1 个数据集合,此处可以任意设置,会返回比对从大到小排序的num 个数据集合
                if (featureResult != null && featureResult.size() > 0) {
                    //System.out.println("==isOk==>匹配到数量"+featureResult.size());
                    User user = null;
                    Feature topFeature = null;
                    if(TextUtils.isEmpty(groupId)){
                        //为空,需要排序,优先取会员
                        for(Feature feat:featureResult) {
                            threholdScore = bdFaceCheckConfig.scoreThreshold;
                            if (feat != null && feat.getScore() > threholdScore) {
                                User userOld = FaceApi.getInstance().getUserListById(feat.getId());
                                //System.out.println("==isOk==>匹配到类型:"+userOld.getUserName());
                                if("1".equals(userOld.getGroupId())){
                                    user = userOld;
                                    topFeature = feat;
                                    break;
                                }else if(user==null){
                                    user = userOld;
                                    topFeature = feat;
                                }
                        // 获取第一个数据
                        Feature topFeature = featureResult.get(0);
                        // 判断第一个阈值是否大于设定阈值,如果大于,检索成功
                        threholdScore = bdFaceCheckConfig.scoreThreshold;
                        if (topFeature != null && topFeature.getScore() > threholdScore) {
                            // 当前featureEntity 只有id+feature 索引,在数据库中查到完整信息
                            User user = FaceApi.getInstance().getUserListById(topFeature.getId());
                            if (user != null) {
                                IdentifyResult idResult = new IdentifyResult(user, index, topFeature.getScore());
                                // Log.d("Attend", "add user:" + user.getUserInfo() + " index:" + index);
                                livenessModel.addIdentifyResult(idResult);
                                livenessModel.setUser(user);
                                livenessModel.setFeatureScore(topFeature.getScore());
                                setFail(livenessModel);
                            } else {
                                setFail(livenessModel);
                            }
                        } else {
                            setFail(livenessModel);
                        }
                    }else {
                        //只取该类型用户
                        User user = null;
                        Feature topFeature = null;
                        for(Feature feat:featureResult) {
                            // 获取数据
                            // 判断阈值是否大于设定阈值,如果大于,检索成功
@@ -1248,17 +1252,16 @@
                                }
                            }
                        }
                    }
                    if (user != null) {
                        //System.out.println("==isOk==>匹配到");
                        IdentifyResult idResult = new IdentifyResult(user, index, topFeature.getScore());
                        livenessModel.addIdentifyResult(idResult);
                        livenessModel.setUser(user);
                        livenessModel.setFeatureScore(topFeature.getScore());
                        setFail(livenessModel);
                    } else {
                        //IdentifyResult idResult = new IdentifyResult(user, index, topFeature.getScore());
                        setFail(livenessModel);
                        if (user != null&&topFeature!=null) {
                            //System.out.println("==isOk==>匹配到");
                            IdentifyResult idResult = new IdentifyResult(user, index, topFeature.getScore());
                            livenessModel.addIdentifyResult(idResult);
                            livenessModel.setUser(user);
                            livenessModel.setFeatureScore(topFeature.getScore());
                            setFail(livenessModel);
                        } else {
                            setFail(livenessModel);
                        }
                    }
                } else {
                    setFail(livenessModel);
@@ -1266,13 +1269,13 @@
            } else if (featureCheckMode == 4) {
                // 目前仅支持
                float score =
                    faceModel
                        .getFaceSearch()
                        .compare(
                            BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_ID_PHOTO,
                            livenessModel.getFeature(),
                            secondFeature,
                            true);
                        faceModel
                                .getFaceSearch()
                                .compare(
                                        BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_ID_PHOTO,
                                        livenessModel.getFeature(),
                                        secondFeature,
                                        true);
                livenessModel.setScore(score);
                if (score > threholdScore) {
                    /*faceId = livenessModel.getFaceInfo().faceID;
@@ -1299,11 +1302,11 @@
     * @param faceDetectCallBack
     */
    public void onDetectSilentLiveCheck(
        final BDFaceImageConfig bdFaceImageConfig,
        final BDFaceImageConfig bdNirFaceImageConfig,
        final BDFaceImageConfig bdDepthFaceImageConfig,
        final BDFaceCheckConfig bdFaceCheckConfig,
        final FaceDetectCallBack faceDetectCallBack) {
            final BDFaceImageConfig bdFaceImageConfig,
            final BDFaceImageConfig bdNirFaceImageConfig,
            final BDFaceImageConfig bdDepthFaceImageConfig,
            final BDFaceCheckConfig bdFaceCheckConfig,
            final FaceDetectCallBack faceDetectCallBack) {
        long startTime = System.currentTimeMillis();
        // 创建检测结果存储数据
        LivenessModel livenessModel = new LivenessModel();
@@ -1312,44 +1315,44 @@
        BDFaceImageInstance rgbInstance = getBdImage(bdFaceImageConfig, bdFaceCheckConfig.darkEnhance);
        livenessModel.setTestBDFaceImageInstanceDuration(System.currentTimeMillis() - startTime);
        onTrack(
            rgbInstance,
            livenessModel,
            new DetectListener() {
                @Override
                public void onDetectSuccess(FaceInfo[] faceInfos, BDFaceImageInstance rgbInstance) {
                rgbInstance,
                livenessModel,
                new DetectListener() {
                    @Override
                    public void onDetectSuccess(FaceInfo[] faceInfos, BDFaceImageInstance rgbInstance) {
                    // 保存人脸特征点
                    livenessModel.setLandmarks(faceInfos[0].landmarks);
                    // 保存人脸图片
                    livenessModel.setBdFaceImageInstance(rgbInstance.getImage());
                    // 调用绘制人脸框接口
                    if (faceDetectCallBack != null) {
                        faceDetectCallBack.onFaceDetectDarwCallback(livenessModel);
                    }
                    // 送检识别
                    onSilentLivenessCheck(
                        rgbInstance,
                        bdNirFaceImageConfig,
                        bdDepthFaceImageConfig,
                        bdFaceCheckConfig,
                        livenessModel,
                        startTime,
                        faceDetectCallBack,
                        faceInfos);
                }
                @Override
                public void onDetectFail() {
                    // 流程结束销毁图片,开始下一帧图片检测,否着内存泄露
                    if (faceDetectCallBack != null) {
                        faceDetectCallBack.onFaceDetectCallback(null);
                        // 保存人脸特征点
                        livenessModel.setLandmarks(faceInfos[0].landmarks);
                        // 保存人脸图片
                        livenessModel.setBdFaceImageInstance(rgbInstance.getImage());
                        faceDetectCallBack.onFaceDetectDarwCallback(livenessModel);
                        faceDetectCallBack.onTip(0, "未检测到人脸");
                        // 调用绘制人脸框接口
                        if (faceDetectCallBack != null) {
                            faceDetectCallBack.onFaceDetectDarwCallback(livenessModel);
                        }
                        // 送检识别
                        onSilentLivenessCheck(
                                rgbInstance,
                                bdNirFaceImageConfig,
                                bdDepthFaceImageConfig,
                                bdFaceCheckConfig,
                                livenessModel,
                                startTime,
                                faceDetectCallBack,
                                faceInfos);
                    }
                }
            });
                    @Override
                    public void onDetectFail() {
                        // 流程结束销毁图片,开始下一帧图片检测,否着内存泄露
                        if (faceDetectCallBack != null) {
                            faceDetectCallBack.onFaceDetectCallback(null);
                            livenessModel.setBdFaceImageInstance(rgbInstance.getImage());
                            faceDetectCallBack.onFaceDetectDarwCallback(livenessModel);
                            faceDetectCallBack.onTip(0, "未检测到人脸");
                        }
                        rgbInstance.destory();
                    }
                });
    }
    /**
@@ -1363,206 +1366,206 @@
     * @param faceDetectCallBack
     */
    public void onSilentLivenessCheck(
        final BDFaceImageInstance rgbInstance,
        final BDFaceImageConfig nirBDFaceImageConfig,
        final BDFaceImageConfig depthBDFaceImageConfig,
        final BDFaceCheckConfig bdFaceCheckConfig,
        final LivenessModel livenessModel,
        final long startTime,
        final FaceDetectCallBack faceDetectCallBack,
        final FaceInfo[] fastFaceInfos) {
            final BDFaceImageInstance rgbInstance,
            final BDFaceImageConfig nirBDFaceImageConfig,
            final BDFaceImageConfig depthBDFaceImageConfig,
            final BDFaceCheckConfig bdFaceCheckConfig,
            final LivenessModel livenessModel,
            final long startTime,
            final FaceDetectCallBack faceDetectCallBack,
            final FaceInfo[] fastFaceInfos) {
        if (future2 != null && !future2.isDone()) {
            // 流程结束销毁图片,开始下一帧图片检测,否着内存泄露
            rgbInstance.destory();
            return;
        }
        future2 =
            es2.submit(
                new Runnable() {
                es2.submit(
                        new Runnable() {
                    @Override
                    public void run() {
                        onDetect(
                            bdFaceCheckConfig,
                            rgbInstance,
                            fastFaceInfos,
                            livenessModel,
                            new DetectListener() {
                                @Override
                                public void onDetectSuccess(FaceInfo[] faceInfos, BDFaceImageInstance rgbInstance) {
                                    // 人脸id赋值
                                    if (mLastFaceId != fastFaceInfos[0].faceID) {
                                        mLastFaceId = fastFaceInfos[0].faceID;
                                        mRgbLiveList.clear();
                                        mNirLiveList.clear();
                                    }
                                    if (bdFaceCheckConfig == null) {
                                        if (faceDetectCallBack != null) {
                                            faceDetectCallBack.onFaceDetectCallback(livenessModel);
                                        }
                                        return;
                                    }
                                    // 最优人脸控制
                                    if (!onBestImageCheck(livenessModel, bdFaceCheckConfig, faceDetectCallBack)) {
                                        livenessModel.setQualityCheck(true);
                                        if (faceDetectCallBack != null) {
                                            faceDetectCallBack.onFaceDetectCallback(livenessModel);
                                        }
                                        return;
                                    }
                                    onQualityCheck(
                                        faceInfos,
                                        bdFaceCheckConfig.bdQualityConfig,
                                        faceDetectCallBack,
                                        new QualityListener() {
                            @Override
                            public void run() {
                                onDetect(
                                        bdFaceCheckConfig,
                                        rgbInstance,
                                        fastFaceInfos,
                                        livenessModel,
                                        new DetectListener() {
                                            @Override
                                            public void onQualitySuccess() {
                                                livenessModel.setQualityCheck(false);
                                                // 获取LivenessConfig liveCheckMode 配置选项:【不使用活体:0】;【RGB活体:1】;【RGB+NIR活体:2】;【RGB+Depth活体:3】;【RGB+NIR+Depth活体:4】
                                                // TODO 活体检测
                                                BDLiveConfig bdLiveConfig = bdFaceCheckConfig.bdLiveConfig;
                                                boolean isLiveCheck = bdFaceCheckConfig.bdLiveConfig != null;
                                                if (isLiveCheck) {
                                                    long startRgbTime = System.currentTimeMillis();
                                                    boolean rgbLiveStatus =
                                                        faceModel
                                                            .getFaceLive()
                                                            .strategySilentLive(
                                                                BDFaceSDKCommon.LiveType.BDFACE_SILENT_LIVE_TYPE_RGB,
                                                                rgbInstance,
                                                                faceInfos[0],
                                                                bdLiveConfig.framesThreshold,
                                                                bdLiveConfig.rgbLiveScore);
                                                    livenessModel.setRGBLiveStatus(rgbLiveStatus);
                                                    livenessModel.setRgbLivenessDuration(
                                                        System.currentTimeMillis() - startRgbTime);
                                            public void onDetectSuccess(FaceInfo[] faceInfos, BDFaceImageInstance rgbInstance) {
                                                // 人脸id赋值
                                                if (mLastFaceId != fastFaceInfos[0].faceID) {
                                                    mLastFaceId = fastFaceInfos[0].faceID;
                                                    mRgbLiveList.clear();
                                                    mNirLiveList.clear();
                                                }
                                                // TODO nir活体检测
                                                BDFaceImageInstance nirInstance = null;
                                                boolean isHaveNirImage = nirBDFaceImageConfig != null && isLiveCheck;
                                                if (isHaveNirImage) {
                                                    // 创建检测对象,如果原始数据YUV-IR,转为算法检测的图片BGR
                                                    // TODO: 用户调整旋转角度和是否镜像,手机和开发版需要动态适配
                                                    nirInstance = getBdImage(nirBDFaceImageConfig, false);
                                                    livenessModel.setBdNirFaceImageInstance(nirInstance.getImage());
                                                    // 避免RGB检测关键点在IR对齐活体稳定,增加红外检测
                                                    long startIrDetectTime = System.currentTimeMillis();
                                                    BDFaceDetectListConf bdFaceDetectListConf =
                                                        new BDFaceDetectListConf();
                                                    bdFaceDetectListConf.usingDetect = true;
                                                    FaceInfo[] faceInfosIr =
                                                        faceModel
                                                            .getFaceNirDetect()
                                                            .detect(
                                                                BDFaceSDKCommon.DetectType.DETECT_NIR,
                                                                BDFaceSDKCommon.AlignType
                                                                    .BDFACE_ALIGN_TYPE_NIR_ACCURATE,
                                                                nirInstance,
                                                                null,
                                                                bdFaceDetectListConf);
                                                    bdFaceDetectListConf.usingDetect = false;
                                                    livenessModel.setIrLivenessDuration(
                                                        System.currentTimeMillis() - startIrDetectTime);
                                                    //                    LogUtils.e(TIME_TAG, "detect ir time = " + livenessModel.getIrLivenessDuration());
                                                    if (faceInfosIr != null && faceInfosIr.length > 0) {
                                                        FaceInfo faceInfoIr = faceInfosIr[0];
                                                        long startNirTime = System.currentTimeMillis();
                                                        boolean nirLiveStatus =
                                                            faceModel
                                                                .getFaceLive()
                                                                .strategySilentLive(
                                                                    BDFaceSDKCommon.LiveType
                                                                        .BDFACE_SILENT_LIVE_TYPE_NIR,
                                                                    nirInstance,
                                                                    faceInfoIr,
                                                                    bdLiveConfig.framesThreshold,
                                                                    bdLiveConfig.nirLiveScore);
                                                        livenessModel.setNIRLiveStatus(nirLiveStatus);
                                                        livenessModel.setIrLivenessDuration(
                                                            System.currentTimeMillis() - startNirTime);
                                                if (bdFaceCheckConfig == null) {
                                                    rgbInstance.destory();
                                                    if (faceDetectCallBack != null) {
                                                        faceDetectCallBack.onFaceDetectCallback(livenessModel);
                                                    }
                                                    nirInstance.destory();
                                                    return;
                                                }
                                                // TODO depth活体检测
                                                if (depthBDFaceImageConfig != null) {
                                                    fastFaceInfos[0].landmarks = faceInfos[0].landmarks;
                                                    // TODO: 用户调整旋转角度和是否镜像,适配Atlas 镜头,目前宽和高400*640,其他摄像头需要动态调整,人脸72 个关键点x 坐标向左移动80个像素点
                                                    float[] depthLandmark = new float[faceInfos[0].landmarks.length];
                                                    BDFaceImageInstance depthInstance;
                                                    if (bdFaceCheckConfig.cameraType == 1) {
                                                        System.arraycopy(
                                                            faceInfos[0].landmarks,
                                                            0,
                                                            depthLandmark,
                                                            0,
                                                            faceInfos[0].landmarks.length);
                                                        for (int i = 0; i < 144; i = i + 2) {
                                                            depthLandmark[i] -= 80;
                                                        }
                                                        fastFaceInfos[0].landmarks = depthLandmark;
                                                // 最优人脸控制
                                                if (!onBestImageCheck(livenessModel, bdFaceCheckConfig, faceDetectCallBack)) {
                                                    livenessModel.setQualityCheck(true);
                                                    rgbInstance.destory();
                                                    if (faceDetectCallBack != null) {
                                                        faceDetectCallBack.onFaceDetectCallback(livenessModel);
                                                    }
                                                    depthInstance = getBdImage(depthBDFaceImageConfig, false);
                                                    livenessModel.setBdDepthFaceImageInstance(depthInstance.getImage());
                                                    // 创建检测对象,如果原始数据Depth
                                                    long startDepthTime = System.currentTimeMillis();
                                                    boolean depthLiveStatus =
                                                        faceModel
                                                            .getFaceLive()
                                                            .strategySilentLive(
                                                                BDFaceSDKCommon.LiveType.BDFACE_SILENT_LIVE_TYPE_DEPTH,
                                                                depthInstance,
                                                                fastFaceInfos[0],
                                                                bdLiveConfig.framesThreshold,
                                                                bdLiveConfig.nirLiveScore);
                                                    livenessModel.setDepthLiveStatus(depthLiveStatus);
                                                    livenessModel.setDepthtLivenessDuration(
                                                        System.currentTimeMillis() - startDepthTime);
                                                    depthInstance.destory();
                                                    return;
                                                }
                                                // 流程结束,记录最终时间
                                                livenessModel.setAllDetectDuration(
                                                    System.currentTimeMillis() - startTime);
                                                //                LogUtils.e(TIME_TAG, "all process time = " + livenessModel.getAllDetectDuration());
                                                // 流程结束销毁图片,开始下一帧图片检测,否着内存泄露
                                                onQualityCheck(
                                                        faceInfos,
                                                        bdFaceCheckConfig.bdQualityConfig,
                                                        faceDetectCallBack,
                                                        new QualityListener() {
                                                            @Override
                                                            public void onQualitySuccess() {
                                                                livenessModel.setQualityCheck(false);
                                                                // 获取LivenessConfig liveCheckMode 配置选项:【不使用活体:0】;【RGB活体:1】;【RGB+NIR活体:2】;【RGB+Depth活体:3】;【RGB+NIR+Depth活体:4】
                                                                // TODO 活体检测
                                                                BDLiveConfig bdLiveConfig = bdFaceCheckConfig.bdLiveConfig;
                                                                boolean isLiveCheck = bdFaceCheckConfig.bdLiveConfig != null;
                                                                if (isLiveCheck) {
                                                                    long startRgbTime = System.currentTimeMillis();
                                                                    boolean rgbLiveStatus =
                                                                            faceModel
                                                                                    .getFaceLive()
                                                                                    .strategySilentLive(
                                                                                            BDFaceSDKCommon.LiveType.BDFACE_SILENT_LIVE_TYPE_RGB,
                                                                                            rgbInstance,
                                                                                            faceInfos[0],
                                                                                            bdLiveConfig.framesThreshold,
                                                                                            bdLiveConfig.rgbLiveScore);
                                                                    livenessModel.setRGBLiveStatus(rgbLiveStatus);
                                                                    livenessModel.setRgbLivenessDuration(
                                                                            System.currentTimeMillis() - startRgbTime);
                                                                }
                                                                // TODO nir活体检测
                                                                BDFaceImageInstance nirInstance = null;
                                                                boolean isHaveNirImage = nirBDFaceImageConfig != null && isLiveCheck;
                                                                if (isHaveNirImage) {
                                                // 显示最终结果提示
                                                if (faceDetectCallBack != null) {
                                                    faceDetectCallBack.onFaceDetectCallback(livenessModel);
                                                }
                                                                    // 创建检测对象,如果原始数据YUV-IR,转为算法检测的图片BGR
                                                                    // TODO: 用户调整旋转角度和是否镜像,手机和开发版需要动态适配
                                                                    nirInstance = getBdImage(nirBDFaceImageConfig, false);
                                                                    livenessModel.setBdNirFaceImageInstance(nirInstance.getImage());
                                                                    // 避免RGB检测关键点在IR对齐活体稳定,增加红外检测
                                                                    long startIrDetectTime = System.currentTimeMillis();
                                                                    BDFaceDetectListConf bdFaceDetectListConf =
                                                                            new BDFaceDetectListConf();
                                                                    bdFaceDetectListConf.usingDetect = true;
                                                                    FaceInfo[] faceInfosIr =
                                                                            faceModel
                                                                                    .getFaceNirDetect()
                                                                                    .detect(
                                                                                            BDFaceSDKCommon.DetectType.DETECT_NIR,
                                                                                            BDFaceSDKCommon.AlignType
                                                                                                    .BDFACE_ALIGN_TYPE_NIR_ACCURATE,
                                                                                            nirInstance,
                                                                                            null,
                                                                                            bdFaceDetectListConf);
                                                                    bdFaceDetectListConf.usingDetect = false;
                                                                    livenessModel.setIrLivenessDuration(
                                                                            System.currentTimeMillis() - startIrDetectTime);
                                                                    //                    LogUtils.e(TIME_TAG, "detect ir time = " + livenessModel.getIrLivenessDuration());
                                                                    if (faceInfosIr != null && faceInfosIr.length > 0) {
                                                                        FaceInfo faceInfoIr = faceInfosIr[0];
                                                                        long startNirTime = System.currentTimeMillis();
                                                                        boolean nirLiveStatus =
                                                                                faceModel
                                                                                        .getFaceLive()
                                                                                        .strategySilentLive(
                                                                                                BDFaceSDKCommon.LiveType
                                                                                                        .BDFACE_SILENT_LIVE_TYPE_NIR,
                                                                                                nirInstance,
                                                                                                faceInfoIr,
                                                                                                bdLiveConfig.framesThreshold,
                                                                                                bdLiveConfig.nirLiveScore);
                                                                        livenessModel.setNIRLiveStatus(nirLiveStatus);
                                                                        livenessModel.setIrLivenessDuration(
                                                                                System.currentTimeMillis() - startNirTime);
                                                                    }
                                                                    nirInstance.destory();
                                                                }
                                                                // TODO depth活体检测
                                                                if (depthBDFaceImageConfig != null) {
                                                                    fastFaceInfos[0].landmarks = faceInfos[0].landmarks;
                                                                    // TODO: 用户调整旋转角度和是否镜像,适配Atlas 镜头,目前宽和高400*640,其他摄像头需要动态调整,人脸72 个关键点x 坐标向左移动80个像素点
                                                                    float[] depthLandmark = new float[faceInfos[0].landmarks.length];
                                                                    BDFaceImageInstance depthInstance;
                                                                    if (bdFaceCheckConfig.cameraType == 1) {
                                                                        System.arraycopy(
                                                                                faceInfos[0].landmarks,
                                                                                0,
                                                                                depthLandmark,
                                                                                0,
                                                                                faceInfos[0].landmarks.length);
                                                                        for (int i = 0; i < 144; i = i + 2) {
                                                                            depthLandmark[i] -= 80;
                                                                        }
                                                                        fastFaceInfos[0].landmarks = depthLandmark;
                                                                    }
                                                                    depthInstance = getBdImage(depthBDFaceImageConfig, false);
                                                                    livenessModel.setBdDepthFaceImageInstance(depthInstance.getImage());
                                                                    // 创建检测对象,如果原始数据Depth
                                                                    long startDepthTime = System.currentTimeMillis();
                                                                    boolean depthLiveStatus =
                                                                            faceModel
                                                                                    .getFaceLive()
                                                                                    .strategySilentLive(
                                                                                            BDFaceSDKCommon.LiveType.BDFACE_SILENT_LIVE_TYPE_DEPTH,
                                                                                            depthInstance,
                                                                                            fastFaceInfos[0],
                                                                                            bdLiveConfig.framesThreshold,
                                                                                            bdLiveConfig.nirLiveScore);
                                                                    livenessModel.setDepthLiveStatus(depthLiveStatus);
                                                                    livenessModel.setDepthtLivenessDuration(
                                                                            System.currentTimeMillis() - startDepthTime);
                                                                    depthInstance.destory();
                                                                }
                                                                // 流程结束,记录最终时间
                                                                livenessModel.setAllDetectDuration(
                                                                        System.currentTimeMillis() - startTime);
                                                                //                LogUtils.e(TIME_TAG, "all process time = " + livenessModel.getAllDetectDuration());
                                                                // 流程结束销毁图片,开始下一帧图片检测,否着内存泄露
                                                                rgbInstance.destory();
                                                                // 显示最终结果提示
                                                                if (faceDetectCallBack != null) {
                                                                    faceDetectCallBack.onFaceDetectCallback(livenessModel);
                                                                }
                                                            }
                                                            @Override
                                                            public void onQualityFail(String detectFail, String occlusionFail) {
                                                                livenessModel.setQualityOcclusion(occlusionFail);
                                                                livenessModel.setQualityDetect(detectFail);
                                                                livenessModel.setQualityCheck(true);
                                                                rgbInstance.destory();
                                                                if (faceDetectCallBack != null) {
                                                                    faceDetectCallBack.onFaceDetectCallback(livenessModel);
                                                                }
                                                            }
                                                        });
                                            }
                                            @Override
                                            public void onQualityFail(String detectFail, String occlusionFail) {
                                                livenessModel.setQualityOcclusion(occlusionFail);
                                                livenessModel.setQualityDetect(detectFail);
                                                livenessModel.setQualityCheck(true);
                                            public void onDetectFail() {
                                                if (faceDetectCallBack != null) {
                                                    faceDetectCallBack.onFaceDetectCallback(livenessModel);
                                                }
                                            }
                                        });
                                }
                                @Override
                                public void onDetectFail() {
                                    if (faceDetectCallBack != null) {
                                        faceDetectCallBack.onFaceDetectCallback(livenessModel);
                                    }
                                }
                            });
                    }
                });
                            }
                        });
    }
    private void onTrack(BDFaceImageInstance rgbInstance, LivenessModel livenessModel, DetectListener detectListener) {
@@ -1631,10 +1634,10 @@
     * @return
     */
    public void onQualityCheck(
        final FaceInfo[] faceInfos,
        final BDQualityConfig bdQualityConfig,
        final FaceDetectCallBack faceDetectCallBack,
        final QualityListener qualityListener) {
            final FaceInfo[] faceInfos,
            final BDQualityConfig bdQualityConfig,
            final FaceDetectCallBack faceDetectCallBack,
            final QualityListener qualityListener) {
        if (bdQualityConfig == null) {
            qualityListener.onQualitySuccess();
@@ -1719,7 +1722,7 @@
                    }
                }
                if (!TextUtils.isEmpty(stringBufferDetected.toString())
                    || !TextUtils.isEmpty(stringBufferOcclusion.toString())) {
                        || !TextUtils.isEmpty(stringBufferOcclusion.toString())) {
                    if (!TextUtils.isEmpty(stringBufferDetected.toString())) {
                        detectFail = stringBufferDetected.toString();
                    }
@@ -1747,9 +1750,9 @@
     * @return
     */
    public boolean onQualityCheck(
        final FaceInfo[] faceInfos,
        final BDQualityConfig bdQualityConfig,
        final FaceDetectCallBack faceDetectCallBack) {
            final FaceInfo[] faceInfos,
            final BDQualityConfig bdQualityConfig,
            final FaceDetectCallBack faceDetectCallBack) {
        if (bdQualityConfig == null) {
            return true;
@@ -1847,7 +1850,7 @@
     * @return
     */
    public boolean onPersonQualityCheck(
        final FaceInfo faceInfo, final BDQualityConfig bdQualityConfig, final FaceDetectCallBack faceDetectCallBack) {
            final FaceInfo faceInfo, final BDQualityConfig bdQualityConfig, final FaceDetectCallBack faceDetectCallBack) {
        if (bdQualityConfig == null) {
            return true;
@@ -1929,31 +1932,28 @@
     * rightCheek 右臉遮擋得分
     */
    private boolean selectQuality(
        float bluriness,
        float leftEye,
        float rightEye,
        float nose,
        float mouth,
        float leftCheek,
        float rightCheek,
        float chin) {
            float bluriness,
            float leftEye,
            float rightEye,
            float nose,
            float mouth,
            float leftCheek,
            float rightCheek,
            float chin) {
        return bluriness < 0.5
            && leftEye < 0.75
            && rightEye < 0.75
            && nose < 0.75
            && mouth < 0.75
            && leftCheek < 0.75
            && rightCheek < 0.75
            && chin < 0.7;
                && leftEye < 0.75
                && rightEye < 0.75
                && nose < 0.75
                && mouth < 0.75
                && leftCheek < 0.75
                && rightCheek < 0.75
                && chin < 0.7;
    }
    // 人证核验特征提取
    public float personDetect(
        final Bitmap bitmap, final byte[] feature, final BDFaceCheckConfig bdFaceCheckConfig, Context context) {
        if(bitmap==null||bitmap.isRecycled()){
            return -1;
        }
            final Bitmap bitmap, final byte[] feature, final BDFaceCheckConfig bdFaceCheckConfig, Context context) {
        BDFaceImageInstance rgbInstance = new BDFaceImageInstance(bitmap);
        float ret = -1;
        FaceInfo[] faceInfos;
@@ -1961,14 +1961,14 @@
        if (bdFaceCheckConfig != null) {
            bdFaceCheckConfig.bdFaceDetectListConfig.usingDetect = true;
            faceInfos =
                faceModel
                    .getFaceDetectPerson()
                    .detect(
                        BDFaceSDKCommon.DetectType.DETECT_VIS,
                        BDFaceSDKCommon.AlignType.BDFACE_ALIGN_TYPE_RGB_ACCURATE,
                        rgbInstance,
                        null,
                        bdFaceCheckConfig.bdFaceDetectListConfig);
                    faceModel
                            .getFaceDetectPerson()
                            .detect(
                                    BDFaceSDKCommon.DetectType.DETECT_VIS,
                                    BDFaceSDKCommon.AlignType.BDFACE_ALIGN_TYPE_RGB_ACCURATE,
                                    rgbInstance,
                                    null,
                                    bdFaceCheckConfig.bdFaceDetectListConfig);
        } else {
            faceInfos = faceModel.getFaceDetectPerson().detect(BDFaceSDKCommon.DetectType.DETECT_VIS, rgbInstance);
        }
@@ -1976,19 +1976,19 @@
            // 判断质量检测,针对模糊度、遮挡、角度
            if (onPersonQualityCheck(faceInfos[0], bdQualityConfig, new FaceQualityBack(context))) {
                ret =
                    faceModel
                        .getFacePersonFeature()
                        .feature(
                            BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO,
                            rgbInstance,
                            faceInfos[0].landmarks,
                            feature);
                        faceModel
                                .getFacePersonFeature()
                                .feature(
                                        BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO,
                                        rgbInstance,
                                        faceInfos[0].landmarks,
                                        feature);
            }
        } else {
            rgbInstance.destory();
            return -1;
        }
        rgbInstance.destory();
        return ret;
    }
}