From 3a154bdb0a5aaa2c0ac3eac95a6ba747068bd454 Mon Sep 17 00:00:00 2001
From: MrShi <1878285526@qq.com>
Date: 星期二, 13 一月 2026 10:00:37 +0800
Subject: [PATCH] 优化

---
 keyCabinet-android/datalibrary/src/main/java/com/example/datalibrary/manager/FaceSDKManager.java | 1994 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1,994 insertions(+), 0 deletions(-)

diff --git a/keyCabinet-android/datalibrary/src/main/java/com/example/datalibrary/manager/FaceSDKManager.java b/keyCabinet-android/datalibrary/src/main/java/com/example/datalibrary/manager/FaceSDKManager.java
new file mode 100644
index 0000000..fe9db72
--- /dev/null
+++ b/keyCabinet-android/datalibrary/src/main/java/com/example/datalibrary/manager/FaceSDKManager.java
@@ -0,0 +1,1994 @@
+package com.example.datalibrary.manager;
+
+import static com.example.datalibrary.model.GlobalSet.FEATURE_SIZE;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.os.Debug;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.baidu.idl.main.facesdk.FaceAuth;
+import com.baidu.idl.main.facesdk.FaceCrop;
+import com.baidu.idl.main.facesdk.FaceDetect;
+import com.baidu.idl.main.facesdk.FaceFeature;
+import com.baidu.idl.main.facesdk.FaceInfo;
+import com.baidu.idl.main.facesdk.FaceMouthMask;
+import com.baidu.idl.main.facesdk.ImageIllum;
+import com.baidu.idl.main.facesdk.model.BDFaceDetectListConf;
+import com.baidu.idl.main.facesdk.model.BDFaceImageInstance;
+import com.baidu.idl.main.facesdk.model.BDFaceOcclusion;
+import com.baidu.idl.main.facesdk.model.BDFaceSDKCommon;
+import com.baidu.idl.main.facesdk.model.BDFaceSDKConfig;
+import com.baidu.idl.main.facesdk.model.Feature;
+import com.example.datalibrary.api.FaceApi;
+import com.example.datalibrary.callback.FaceDetectCallBack;
+import com.example.datalibrary.callback.FaceQualityBack;
+import com.example.datalibrary.db.DBManager;
+import com.example.datalibrary.listener.DetectListener;
+import com.example.datalibrary.listener.QualityListener;
+import com.example.datalibrary.listener.SdkInitListener;
+import com.example.datalibrary.model.BDFaceCheckConfig;
+import com.example.datalibrary.model.BDFaceImageConfig;
+import com.example.datalibrary.model.BDLiveConfig;
+import com.example.datalibrary.model.BDQualityConfig;
+import com.example.datalibrary.model.LivenessModel;
+import com.example.datalibrary.model.User;
+import com.example.datalibrary.utils.ToastUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class FaceSDKManager {
+
+    public static final int SDK_MODEL_LOAD_SUCCESS = 0;
+    public static final int SDK_UNACTIVATION = 1;
+    private static final String TAG = "FaceSDKManager";
+
+    private List<Boolean> mRgbLiveList = new ArrayList<>();
+    private List<Boolean> mNirLiveList = new ArrayList<>();
+    private int mLastFaceId;
+
+    private float threholdScore;
+
+    public static volatile int initStatus = SDK_UNACTIVATION;
+    public static volatile boolean initModelSuccess = false;
+    private FaceAuth faceAuth;
+
+    private ExecutorService es = Executors.newSingleThreadExecutor();
+    private Future future;
+    private ExecutorService es2 = Executors.newSingleThreadExecutor();
+    private Future future2;
+    private ExecutorService es3 = Executors.newSingleThreadExecutor();
+    private Future future3;
+
+    private float[] scores;
+    private ImageIllum imageIllum;
+    private long startInitModelTime;
+
+    private static int failNumber = 0;
+    private static int faceId = 0;
+    private static int lastFaceId = 0;
+    private static LivenessModel faceAdoptModel;
+    private boolean isFail = false;
+    private long trackTime;
+    private FaceModel faceModel;
+
+    private boolean checkMouthMask = false;
+    private boolean isMultiIdentify = false;
+
+    private FaceSDKManager() {
+        faceAuth = new FaceAuth();
+        faceAuth.setCoreConfigure(BDFaceSDKCommon.BDFaceCoreRunMode.BDFACE_LITE_POWER_NO_BIND, 2);
+    }
+
+    public void setActiveLog(boolean isLog) {
+        if (faceAuth != null) {
+            if (isLog) {
+                faceAuth.setActiveLog(BDFaceSDKCommon.BDFaceLogInfo.BDFACE_LOG_TYPE_ALL, 1);
+            } else {
+                faceAuth.setActiveLog(BDFaceSDKCommon.BDFaceLogInfo.BDFACE_LOG_TYPE_ALL, 0);
+            }
+        }
+    }
+
+    public void setCheckMouthMask(boolean checkMouthMask) {
+        this.checkMouthMask = checkMouthMask;
+    }
+
+    public void setMultiIdentify(boolean isMultiFaceIdentify) {
+        this.isMultiIdentify = isMultiFaceIdentify;
+    }
+
+    private static class HolderClass {
+        private static final FaceSDKManager INSTANCE = new FaceSDKManager();
+    }
+
+    public static FaceSDKManager getInstance() {
+        return HolderClass.INSTANCE;
+    }
+
+    public ImageIllum getImageIllum() {
+        return imageIllum;
+    }
+
+    public void initModel(
+        final Context context, BDFaceSDKConfig config, boolean isLog, final SdkInitListener listener) {
+        setActiveLog(isLog);
+        initModel(context, config, listener);
+    }
+
+    /**
+     * 鍒濆鍖栨ā鍨嬶紝鐩墠鍖呭惈妫�鏌ワ紝娲讳綋锛岃瘑鍒ā鍨嬶紱鍥犱负鍒濆鍖栨槸椤哄簭鎵ц锛屽彲浠ュ湪鏈�濂藉垵濮嬪寲鍥炴帀涓繑鍥炵姸鎬佺粨鏋�
+     *
+     * @param context
+     */
+    public void initModel(final Context context, BDFaceSDKConfig config, final SdkInitListener listener) {
+        // 鏇濆厜
+        if (imageIllum == null) {
+            imageIllum = new ImageIllum();
+        }
+        // 鍏朵粬妯″瀷鍒濆鍖�
+        if (faceModel == null) {
+            faceModel = new FaceModel(checkMouthMask);
+        }
+        faceModel.setListener(listener);
+
+        faceModel.init(config, context);
+
+        startInitModelTime = System.currentTimeMillis();
+    }
+
+    public void destroy(){
+        if(rgbInstance!=null){
+            rgbInstance = null;
+        }
+    }
+
+    public FaceCrop getFaceCrop() {
+        return faceModel.getFaceCrop();
+    }
+
+    public FaceDetect getFaceDetectPerson() {
+        return faceModel.getFaceDetectPerson();
+    }
+
+    public FaceFeature getFacePersonFeature() {
+        return faceModel.getFacePersonFeature();
+    }
+
+    public FaceMouthMask getFaceMouthMask() {
+        return faceModel.getFaceMoutMask();
+    }
+
+    public void initDataBases(Context context) {
+        if (FaceApi.getInstance().getmUserNum() != 0) {
+            //ToastUtils.toast(context, "浜鸿劯搴撳姞杞戒腑");
+        }
+        emptyFrame();
+        // 鍒濆鍖栨暟鎹簱
+        DBManager.getInstance().init(context);
+        // 鏁版嵁鍙樺寲锛屾洿鏂板唴瀛�
+        initPush(context);
+    }
+
+    /**
+     * 鏁版嵁搴撳彂鐜板彉鍖栨椂鍊欙紝閲嶆柊鎶婃暟鎹簱涓殑浜鸿劯淇℃伅娣诲姞鍒板唴瀛樹腑锛宨d+feature
+     */
+    public void initPush(final Context context) {
+
+        if (future3 != null && !future3.isDone()) {
+            future3.cancel(true);
+        }
+
+        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());
+                            }
+                            if (FaceApi.getInstance().getmUserNum() != 0) {
+                                //ToastUtils.toast(context, "浜鸿劯搴撳姞杞芥垚鍔�");
+                            }
+                        }
+                    }
+                });
+    }
+
+    private void setFail(LivenessModel livenessModel) {
+        Log.e("faceId", livenessModel.getFaceInfo().faceID + "");
+        if (failNumber >= 2) {
+            faceId = livenessModel.getFaceInfo().faceID;
+            faceAdoptModel = livenessModel;
+            trackTime = System.currentTimeMillis();
+            isFail = false;
+            faceAdoptModel.setMultiFrame(true);
+        } else {
+            failNumber += 1;
+            faceId = 0;
+            faceAdoptModel = null;
+            isFail = true;
+            livenessModel.setMultiFrame(true);
+        }
+    }
+
+    public void emptyFrame() {
+        failNumber = 0;
+        faceId = 0;
+        isFail = false;
+        trackTime = 0;
+        faceAdoptModel = null;
+    }
+
+    private FaceInfo[] getTrackCheck(BDFaceImageInstance rgbInstance) {
+
+        // 蹇�熸娴嬭幏鍙栦汉鑴镐俊鎭紝浠呯敤浜庣粯鍒朵汉鑴告锛岃缁嗕汉鑴告暟鎹悗缁幏鍙�
+        FaceInfo[] faceInfos =
+            faceModel
+                .getFaceTrack()
+                .track(
+                    BDFaceSDKCommon.DetectType.DETECT_VIS,
+                    BDFaceSDKCommon.AlignType.BDFACE_ALIGN_TYPE_RGB_FAST,
+                    rgbInstance);
+        return faceInfos;
+    }
+
+
+    private FaceInfo[] getDetectCheck(BDFaceImageInstance rgbInstance) {
+
+        // 蹇�熸娴嬭幏鍙栦汉鑴镐俊鎭紝浠呯敤浜庣粯鍒朵汉鑴告锛岃缁嗕汉鑴告暟鎹悗缁幏鍙�
+        FaceInfo[] faceInfos = faceModel.getFaceDetect().detect(BDFaceSDKCommon.DetectType.DETECT_VIS, rgbInstance);
+        return faceInfos;
+    }
+
+    private BDFaceImageInstance getBdImage(BDFaceImageConfig bdFaceImageConfig, boolean darkEnhance) {
+        BDFaceImageInstance rgbInstance =
+            new BDFaceImageInstance(
+                bdFaceImageConfig.data,
+                bdFaceImageConfig.srcHeight,
+                bdFaceImageConfig.srcWidth,
+                bdFaceImageConfig.bdFaceImageType,
+                bdFaceImageConfig.direction,
+                bdFaceImageConfig.mirror);
+        BDFaceImageInstance rgbInstanceOne;
+        // 鍒ゆ柇鏆楀厜鎭㈠
+        if (darkEnhance) {
+            rgbInstanceOne = faceModel.getDark().faceDarkEnhance(rgbInstance);
+
+        } else {
+            rgbInstanceOne = rgbInstance;
+        }
+        return rgbInstanceOne;
+    }
+
+    private boolean frameSelect(FaceInfo faceInfo) {
+        if (lastFaceId != faceInfo.faceID) {
+            lastFaceId = faceInfo.faceID;
+        }
+
+        if (System.currentTimeMillis() - trackTime < 0 && faceId == faceInfo.faceID) {
+            faceAdoptModel.setMultiFrame(true);
+
+            return false;
+        }
+        if (faceAdoptModel != null) {
+            faceAdoptModel.setMultiFrame(false);
+        }
+        faceId = 0;
+        faceAdoptModel = null;
+        if (!isFail /*&& failNumber != 0*/) {
+            failNumber = 0;
+        }
+        return true;
+    }
+
+    public BDFaceImageInstance getCopeFace(Bitmap bitmap, float[] landmarks, int initialValue) {
+        if (faceModel == null || faceModel.getFaceCrop() == null) {
+            return null;
+        }
+        BDFaceImageInstance imageInstance = new BDFaceImageInstance(bitmap);
+        if (!bitmap.isRecycled()) {
+            bitmap.recycle();
+        }
+        AtomicInteger isOutoBoundary = new AtomicInteger();
+        BDFaceImageInstance cropInstance =
+            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;
+    }
+    /**
+     * 妫�娴�-娲讳綋-鐗瑰緛-浜鸿劯妫�绱㈡祦绋�
+     *
+     * @param bdFaceImageConfig      鍙鍏塝UV 鏁版嵁娴�
+     * @param bdNirFaceImageConfig   绾㈠YUV 鏁版嵁娴�
+     * @param bdDepthFaceImageConfig 娣卞害depth 鏁版嵁娴�
+     * @param bdFaceCheckConfig      璇嗗埆鍙傛暟
+     * @param faceDetectCallBack
+     */
+    public void onDetectCheck(
+        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();
+        // 鍒涘缓妫�娴嬪璞★紝濡傛灉鍘熷鏁版嵁YUV锛岃浆涓虹畻娉曟娴嬬殑鍥剧墖BGR
+        // TODO: 鐢ㄦ埛璋冩暣鏃嬭浆瑙掑害鍜屾槸鍚﹂暅鍍忥紝鎵嬫満鍜屽紑鍙戠増闇�瑕佸姩鎬侀�傞厤
+        //System.out.println("==rgbInstance==>鍒濆鍖�");
+        if(rgbInstance!=null){
+            rgbInstance.destory();
+        }
+        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);
+                        }
+
+                        return;
+                    }
+                    // 淇濆瓨浜鸿劯鐗瑰緛鐐�
+                    livenessModel.setLandmarks(faceInfos[0].landmarks);
+                    // 淇濆瓨浜鸿劯鍥剧墖
+                    livenessModel.setBdFaceImageInstance(rgbInstance.getImage());
+                    // 鍙g僵妫�娴嬫暟鎹�
+                    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);
+                }
+
+                @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, "鏈娴嬪埌浜鸿劯");
+                    }
+                }
+            });
+    }
+
+    private float silentLive(
+        BDFaceImageInstance rgbInstance,
+        BDFaceSDKCommon.LiveType type,
+        float[] landmarks,
+        List<Boolean> list,
+        float liveScore) {
+        float score = 0;
+        if (landmarks != null) {
+            synchronized (faceModel.getFaceLive()) {
+                Log.e("test_camera", rgbInstance.getImage().data.length + "寮�濮�");
+                score = faceModel.getFaceLive().silentLive(type, rgbInstance, landmarks, liveScore);
+                Log.e("test_camera", "娲讳綋缁撴潫");
+            }
+            list.add(score > liveScore);
+        }
+        while (list.size() > 6) {
+            list.remove(0);
+        }
+        if (list.size() > 2) {
+            int rgbSum = 0;
+            for (Boolean b : list) {
+                if (b) {
+                    rgbSum++;
+                }
+            }
+            if (1.0 * rgbSum / list.size() > 0.6) {
+                if (score < liveScore) {
+                    score = liveScore + (1 - liveScore) * new Random().nextFloat();
+                }
+            } else {
+                if (score > liveScore) {
+                    score = new Random().nextFloat() * liveScore;
+                }
+            }
+        }
+        return score;
+    }
+
+    /**
+     *  娲讳綋妫�娴�
+     * @param rgbInstance
+     * @param type
+     * @param faceInfos
+     * @param list
+     * @param liveScore
+     * @return
+     */
+    private float[] silentLives(
+        BDFaceImageInstance rgbInstance,
+        BDFaceSDKCommon.LiveType type,
+        FaceInfo[] faceInfos,
+        List<Boolean> list,
+        float liveScore) {
+        float[] scores = {0, 0, 0}; // 鏈�澶氭娴�3涓汉鑴�
+        if (faceInfos != null) {
+            synchronized (faceModel.getFaceLive()) {
+                Log.e("test_camera", rgbInstance.getImage().data.length + "寮�濮�");
+                int size = faceInfos.length;
+
+                for (int i = 0; i < size; i++) {
+                    scores[i] =
+                        faceModel.getFaceLive().silentLive(type, rgbInstance, faceInfos[i].landmarks, liveScore);
+                }
+            }
+        }
+        return scores;
+    }
+
+    private void onDetect(
+        BDFaceCheckConfig bdFaceCheckConfig,
+        BDFaceImageInstance rgbInstance,
+        FaceInfo[] fastFaceInfos,
+        LivenessModel livenessModel,
+        DetectListener detectListener) {
+
+        long accurateTime = System.currentTimeMillis();
+        FaceInfo[] faceInfos;
+
+        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);
+
+        } else {
+            faceInfos = faceModel.getFaceDetect().detect(BDFaceSDKCommon.DetectType.DETECT_VIS, rgbInstance);
+        }
+
+        livenessModel.setAccurateTime(System.currentTimeMillis() - accurateTime);
+
+        if (faceInfos == null || faceInfos.length <= 0) {
+
+            detectListener.onDetectFail();
+            return;
+        }
+
+        // 閲嶆柊璧嬩簣璇︾粏浜鸿劯淇℃伅
+        if (livenessModel.getFaceInfo() != null) {
+            faceInfos[0].faceID = livenessModel.getFaceInfo().faceID;
+        }
+
+        livenessModel.setFaceInfos(faceInfos);
+        livenessModel.setFaceInfo(faceInfos[0]);
+        livenessModel.setTrackStatus(2);
+        // 淇濆瓨浜鸿劯鍏抽敭鐐�
+        livenessModel.setLandmarks(faceInfos[0].landmarks);
+        detectListener.onDetectSuccess(faceInfos, rgbInstance);
+    }
+
+    /**
+     * 娲讳綋-鐗瑰緛-浜鸿劯妫�绱㈠叏娴佺▼
+     *
+     * @param rgbInstance            鍙鍏夊簳灞傞�佹瀵硅薄
+     * @param nirBDFaceImageConfig   绾㈠YUV 鏁版嵁娴�
+     * @param depthBDFaceImageConfig 娣卞害depth 鏁版嵁娴�
+     * @param livenessModel          妫�娴嬬粨鏋滄暟鎹泦鍚�
+     * @param startTime              寮�濮嬫娴嬫椂闂�
+     * @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) {
+        if (future2 != null && !future2.isDone()) {
+            // 娴佺▼缁撴潫閿�姣佸浘鐗囷紝寮�濮嬩笅涓�甯у浘鐗囨娴嬶紝鍚︾潃鍐呭瓨娉勯湶
+            //future2.cancel(true);
+
+            //System.out.println("==isOk==>涔嬪墠娌$粨鏉�");
+            return;
+        }
+
+        future2 =
+            es2.submit(
+                new Runnable() {
+
+                    @Override
+                    public void run() {
+
+                        // 鑾峰彇BDFaceCheckConfig閰嶇疆淇℃伅
+                        if (bdFaceCheckConfig == null) {
+
+                            return;
+                        }
+                        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) {
+
+                                        livenessModel.clearIdentifyResults();
+                                        if (faceDetectCallBack != null) {
+                                            faceDetectCallBack.onFaceDetectCallback(livenessModel);
+                                        }
+                                        return;
+                                    }
+
+                                    // 鏈�浼樹汉鑴告帶鍒�
+                                    if (!onBestImageCheck(livenessModel, bdFaceCheckConfig, faceDetectCallBack)) {
+                                        livenessModel.setQualityCheck(true);
+                                        livenessModel.clearIdentifyResults();
+
+                                        if (faceDetectCallBack != null) {
+                                            faceDetectCallBack.onFaceDetectCallback(livenessModel);
+                                        }
+                                        return;
+                                    }
+
+                                    // 璐ㄩ噺妫�娴嬫湭閫氳繃,閿�姣丅DFaceImageInstance锛岀粨鏉熷嚱鏁�
+
+                                    if (!onQualityCheck(
+                                            faceInfos, bdFaceCheckConfig.bdQualityConfig, faceDetectCallBack)) {
+                                        livenessModel.setQualityCheck(true);
+                                        livenessModel.clearIdentifyResults();
+
+                                        if (faceDetectCallBack != null) {
+                                            faceDetectCallBack.onFaceDetectCallback(livenessModel);
+                                        }
+                                        return;
+                                    }
+
+                                    livenessModel.setQualityCheck(false);
+                                    // 鑾峰彇LivenessConfig liveCheckMode 閰嶇疆閫夐」锛氥�愪笉浣跨敤娲讳綋锛�0銆戯紱銆怰GB娲讳綋锛�1銆戯紱銆怰GB+NIR娲讳綋锛�2銆戯紱銆怰GB+Depth娲讳綋锛�3銆戯紱銆怰GB+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 (rgbScores != null){
+                                            int size = rgbScores.length;
+                                            Log.d("Attend", "score size:" + size);
+                                            for (int i = 0; i < size; i++) {
+                                                Log.d("Attend", "score:" + rgbScores[i]);
+                                            }
+                                        } */
+
+                                        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);
+
+                                        livenessModel.setBdNirFaceImageInstance(nirInstance.getImage());
+                                        livenessModel.setNirInstanceTime(System.currentTimeMillis() - nirInstanceTime);
+
+                                        // 閬垮厤RGB妫�娴嬪叧閿偣鍦↖R瀵归綈娲讳綋绋冲畾锛屽鍔犵孩澶栨娴�
+                                        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();
+                                    }
+
+                                    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));
+                                                    }
+
+                                                    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());
+                                    // 娴佺▼缁撴潫閿�姣佸浘鐗囷紝寮�濮嬩笅涓�甯у浘鐗囨娴嬶紝鍚︾潃鍐呭瓨娉勯湶
+
+                                    if (nirInstance != null) {
+                                        nirInstance.destory();
+                                    }
+                                    // 鏄剧ず鏈�缁堢粨鏋滄彁绀�
+                                    if (faceDetectCallBack != null) {
+                                        faceDetectCallBack.onFaceDetectCallback(livenessModel);
+                                    }
+                                }
+
+                                @Override
+                                public void onDetectFail() {
+
+                                    if (faceDetectCallBack != null) {
+                                        faceDetectCallBack.onFaceDetectCallback(livenessModel);
+                                    }
+                                }
+                            });
+                    }
+                });
+    }
+
+    /**
+     * 鏈�浼樹汉鑴告帶鍒�
+     *
+     * @param livenessModel
+     * @param faceDetectCallBack
+     * @return
+     */
+    public boolean onBestImageCheck(
+        LivenessModel livenessModel, BDFaceCheckConfig bdFaceCheckConfig, FaceDetectCallBack faceDetectCallBack) {
+        boolean isBestImageCheck = false;
+        if (livenessModel != null && livenessModel.getFaceInfos() != null) {
+            FaceInfo[] faceInfos = livenessModel.getFaceInfos();
+            int size = faceInfos.length;
+            for (int i = 0; i < size; i++) {
+                float bestImageScore = faceInfos[i].bestImageScore;
+                if (bestImageScore > 0.5) {
+                    isBestImageCheck = true;
+                }
+            }
+        }
+        return isBestImageCheck;
+    }
+
+    /**
+     * 鐗瑰緛鎻愬彇-浜鸿劯璇嗗埆姣斿
+     *
+     * @param rgbInstance      鍙鍏夊簳灞傞�佹瀵硅薄
+     * @param landmark         妫�娴嬬溂鐫涳紝鍢村反锛岄蓟瀛愶紝72涓叧閿偣
+     * @param faceInfos        nir浜鸿劯鏁版嵁
+     * @param nirInstance      nir 鍥惧儚鍙ユ焺
+     * @param livenessModel    妫�娴嬬粨鏋滄暟鎹泦鍚�
+     * @param featureCheckMode 鐗瑰緛鎶藉彇妯″紡銆愪笉鎻愬彇鐗瑰緛锛�1銆戯紱銆愭彁鍙栫壒寰侊細2銆戯紱銆愭彁鍙栫壒寰�+1锛歂妫�绱細3銆戯紱
+     * @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) {
+        // 濡傛灉涓嶆娊鍙栫壒寰侊紝鐩存帴杩斿洖
+        if (featureCheckMode == 1) {
+            return;
+        }
+        byte[] feature = new byte[512];
+        if (featureType == 3) {
+            // todo: 娣峰悎妯℃�佷娇鐢ㄦ柟寮忔槸鏍规嵁鍥剧墖鐨勬洕鍏夋潵閫夋嫨闇�瑕佷娇鐢ㄧ殑type锛屽厜鐓х殑鍙栧�艰寖鍥翠负锛�0~1涔嬮棿
+            AtomicInteger atomicInteger = new AtomicInteger();
+            FaceSDKManager.getInstance().getImageIllum().imageIllum(rgbInstance, atomicInteger);
+            int illumScore = atomicInteger.get();
+            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;
+            BDFaceImageInstance bdFaceImageInstance = isIllum ? nirInstance : rgbInstance;
+            float[] landmarks = isIllum ? faceInfos[0].landmarks : landmark;
+
+            long startFeatureTime = System.currentTimeMillis();
+            float featureSize = faceModel.getFaceFeature().feature(type, bdFaceImageInstance, landmarks, feature);
+            livenessModel.setFeatureDuration(System.currentTimeMillis() - startFeatureTime);
+            livenessModel.setFeature(feature);
+            // 浜鸿劯妫�绱�
+            featureSearch(
+                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);
+            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);
+        }
+    }
+
+    /**
+     * 鐗瑰緛鎻愬彇-浜鸿劯璇嗗埆姣斿
+     *
+     * @param rgbInstance      鍙鍏夊簳灞傞�佹瀵硅薄
+     * @param rgbFaceInfos     rgb浜鸿劯鏁版嵁
+     * @param faceInfos        nir浜鸿劯鏁版嵁
+     * @param nirInstance      nir 鍥惧儚鍙ユ焺
+     * @param livenessModel    妫�娴嬬粨鏋滄暟鎹泦鍚�
+     * @param featureCheckMode 鐗瑰緛鎶藉彇妯″紡銆愪笉鎻愬彇鐗瑰緛锛�1銆戯紱銆愭彁鍙栫壒寰侊細2銆戯紱銆愭彁鍙栫壒寰�+1锛歂妫�绱細3銆戯紱
+     * @param featureType      鐗瑰緛鎶藉彇妯℃�佹墽琛� 銆愮敓娲荤収锛�1銆戯紱銆愯瘉浠剁収锛�2銆戯紱銆愭贩鍚堟ā鎬侊細3銆戯紱
+     * @param rgbScores 鍙鍏夊緱鍒�
+     * @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) {
+        // 濡傛灉涓嶆娊鍙栫壒寰侊紝鐩存帴杩斿洖
+
+        if (featureCheckMode == 1) {
+            return;
+        }
+        byte[] feature = new byte[512];
+
+        if (featureType == 3) {
+            // todo: 娣峰悎妯℃�佷娇鐢ㄦ柟寮忔槸鏍规嵁鍥剧墖鐨勬洕鍏夋潵閫夋嫨闇�瑕佷娇鐢ㄧ殑type锛屽厜鐓х殑鍙栧�艰寖鍥翠负锛�0~1涔嬮棿
+            AtomicInteger atomicInteger = new AtomicInteger();
+            FaceSDKManager.getInstance().getImageIllum().imageIllum(rgbInstance, atomicInteger);
+            int illumScore = atomicInteger.get();
+            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;
+            BDFaceImageInstance bdFaceImageInstance = isIllum ? nirInstance : rgbInstance;
+
+            if (rgbFaceInfos == null) {
+                return;
+            }
+            int size = faceInfos.length;
+
+            if (rgbFaceInfos[index].landmarks == null) {
+                return;
+            }
+
+            if (rgbScores != null) {
+                float score = rgbScores[index];
+                if (score < liveScore) {
+                    return;
+                }
+            }
+
+            float[] landmarks = rgbFaceInfos[index].landmarks;
+
+            long startFeatureTime = System.currentTimeMillis();
+            float featureSize = faceModel.getFaceFeature().feature(type, bdFaceImageInstance, landmarks, feature);
+            livenessModel.setFeatureDuration(System.currentTimeMillis() - startFeatureTime);
+            livenessModel.setFeature(feature);
+            // 浜鸿劯妫�绱�
+            featureSearchs(
+                index,
+                featureCheckMode,
+                livenessModel,
+                bdFaceCheckConfig,
+                feature,
+                secondFeature,
+                featureSize,
+                BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO);
+
+        } else {
+            // 鐢熸椿鐓ф绱�
+            long startFeatureTime = System.currentTimeMillis();
+            if (rgbFaceInfos == null) {
+                return;
+            }
+
+            int size = rgbFaceInfos.length;
+
+            if (rgbFaceInfos[index].landmarks == null) {
+                return;
+            }
+
+            if (rgbScores != null) {
+                float score = rgbScores[index];
+                if (score < liveScore) {
+                    return;
+                }
+            }
+
+            float featureSize =
+                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);
+        }
+    }
+
+    /**
+     * 浜鸿劯搴撴绱�
+     *
+     * @param featureCheckMode 鐗瑰緛鎶藉彇妯″紡銆愪笉鎻愬彇鐗瑰緛锛�1銆戯紱銆愭彁鍙栫壒寰侊細2銆戯紱銆愭彁鍙栫壒寰�+1锛歂妫�绱細3銆戯紱
+     * @param livenessModel    妫�娴嬬粨鏋滄暟鎹泦鍚�
+     * @param feature          鐗瑰緛鐐�
+     * @param secondFeature    1:1 鐗瑰緛鐐�
+     * @param featureSize      鐗瑰緛鐐圭殑size
+     * @param type             鐗瑰緛鎻愬彇绫诲瀷
+     */
+    private void featureSearch(
+        final int featureCheckMode,
+        LivenessModel livenessModel,
+        BDFaceCheckConfig bdFaceCheckConfig,
+        byte[] feature,
+        byte[] secondFeature,
+        float featureSize,
+        BDFaceSDKCommon.FeatureType type) {
+
+        // 濡傛灉鍙彁鍘荤壒寰侊紝涓嶅仛妫�绱紝姝ゅ杩斿洖
+        if (featureCheckMode == 2) {
+            livenessModel.setFeatureCode(featureSize);
+            return;
+        }
+        // 濡傛灉鎻愬彇鐗瑰緛+妫�绱紝璋冪敤search 鏂规硶
+        if (featureSize == FEATURE_SIZE / 4) {
+            long startFeature = System.currentTimeMillis();
+            // 鐗瑰緛鎻愬彇鎴愬姛
+            // TODO 闃堝�煎彲浠ユ牴鎹笉鍚屾ā鍨嬭皟鏁�
+            if (featureCheckMode == 3) {
+                List<? extends Feature> featureResult =
+                    faceModel.getFaceSearch().search(type, bdFaceCheckConfig.scoreThreshold, 1, feature, false);
+
+                // TODO 杩斿洖top num = 1 涓暟鎹泦鍚堬紝姝ゅ鍙互浠绘剰璁剧疆锛屼細杩斿洖姣斿浠庡ぇ鍒板皬鎺掑簭鐨刵um 涓暟鎹泦鍚�
+                if (featureResult != null && featureResult.size() > 0) {
+
+                    // 鑾峰彇绗竴涓暟鎹�
+                    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) {
+                            livenessModel.setUser(user);
+                            livenessModel.setFeatureScore(topFeature.getScore());
+                            /*faceId = livenessModel.getFaceInfo().faceID;
+                            trackTime = System.currentTimeMillis();
+                            faceAdoptModel = livenessModel;
+                            failNumber = 0;
+                            isFail = false;*/
+                            setFail(livenessModel);
+                        } else {
+                            setFail(livenessModel);
+                        }
+                    } else {
+                        setFail(livenessModel);
+                    }
+                } else {
+                    setFail(livenessModel);
+                }
+            } else if (featureCheckMode == 4) {
+                // 鐩墠浠呮敮鎸�
+                float score =
+                    faceModel
+                        .getFaceSearch()
+                        .compare(
+                            BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_ID_PHOTO,
+                            livenessModel.getFeature(),
+                            secondFeature,
+                            true);
+                livenessModel.setScore(score);
+                if (score > threholdScore) {
+                    /*faceId = livenessModel.getFaceInfo().faceID;
+                    trackTime = System.currentTimeMillis();
+                    faceAdoptModel = livenessModel;
+                    failNumber = 0;
+                    isFail = false;*/
+                    setFail(livenessModel);
+                } else {
+                    setFail(livenessModel);
+                }
+            }
+            livenessModel.setCheckDuration(System.currentTimeMillis() - startFeature);
+        }
+    }
+
+    /**
+     * 浜鸿劯搴撴绱�
+     *
+     * @param featureCheckMode 鐗瑰緛鎶藉彇妯″紡銆愪笉鎻愬彇鐗瑰緛锛�1銆戯紱銆愭彁鍙栫壒寰侊細2銆戯紱銆愭彁鍙栫壒寰�+1锛歂妫�绱細3銆戯紱
+     * @param livenessModel    妫�娴嬬粨鏋滄暟鎹泦鍚�
+     * @param feature          鐗瑰緛鐐�
+     * @param secondFeature    1:1 鐗瑰緛鐐�
+     * @param featureSize      鐗瑰緛鐐圭殑size
+     * @param type             鐗瑰緛鎻愬彇绫诲瀷
+     */
+    private void featureSearchs(
+        final int index,
+        final int featureCheckMode,
+        LivenessModel livenessModel,
+        BDFaceCheckConfig bdFaceCheckConfig,
+        byte[] feature,
+        byte[] secondFeature,
+        float featureSize,
+        BDFaceSDKCommon.FeatureType type) {
+
+        // 濡傛灉鍙彁鍘荤壒寰侊紝涓嶅仛妫�绱紝姝ゅ杩斿洖
+
+        if (featureCheckMode == 2) {
+            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");
+                // TODO 杩斿洖top num = 1 涓暟鎹泦鍚堬紝姝ゅ鍙互浠绘剰璁剧疆锛屼細杩斿洖姣斿浠庡ぇ鍒板皬鎺掑簭鐨刵um 涓暟鎹泦鍚�
+                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;
+                                }
+                            }
+                        }
+                    }else {
+                        //鍙彇璇ョ被鍨嬬敤鎴�
+                        for(Feature feat:featureResult) {
+                            // 鑾峰彇鏁版嵁
+                            // 鍒ゆ柇闃堝�兼槸鍚﹀ぇ浜庤瀹氶槇鍊硷紝濡傛灉澶т簬锛屾绱㈡垚鍔�
+                            threholdScore = bdFaceCheckConfig.scoreThreshold;
+                            if (feat != null && feat.getScore() > threholdScore) {
+                                //System.out.println("==isOk==>50");
+                                // 褰撳墠featureEntity 鍙湁id+feature 绱㈠紩锛屽湪鏁版嵁搴撲腑鏌ュ埌瀹屾暣淇℃伅
+                                User userOld = FaceApi.getInstance().getUserListById(feat.getId());
+                                if(groupId.equals(userOld.getGroupId())){
+                                    user = userOld;
+                                    topFeature = feat;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                    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);
+                    }
+                } else {
+                    setFail(livenessModel);
+                }
+            } else if (featureCheckMode == 4) {
+                // 鐩墠浠呮敮鎸�
+                float score =
+                    faceModel
+                        .getFaceSearch()
+                        .compare(
+                            BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_ID_PHOTO,
+                            livenessModel.getFeature(),
+                            secondFeature,
+                            true);
+                livenessModel.setScore(score);
+                if (score > threholdScore) {
+                    /*faceId = livenessModel.getFaceInfo().faceID;
+                    trackTime = System.currentTimeMillis();
+                    faceAdoptModel = livenessModel;
+                    failNumber = 0;
+                    isFail = false;*/
+                    setFail(livenessModel);
+                } else {
+                    setFail(livenessModel);
+                }
+            }
+            livenessModel.setCheckDuration(System.currentTimeMillis() - startFeature);
+        }
+    }
+
+    /**
+     * 閲戣瀺娲绘-妫�娴�-娲讳綋
+     *
+     * @param bdFaceImageConfig      鍙鍏塝UV 鏁版嵁娴�
+     * @param bdNirFaceImageConfig   绾㈠YUV 鏁版嵁娴�
+     * @param bdDepthFaceImageConfig 娣卞害depth 鏁版嵁娴�
+     * @param bdFaceCheckConfig      璇嗗埆鍙傛暟
+     * @param faceDetectCallBack
+     */
+    public void onDetectSilentLiveCheck(
+        final BDFaceImageConfig bdFaceImageConfig,
+        final BDFaceImageConfig bdNirFaceImageConfig,
+        final BDFaceImageConfig bdDepthFaceImageConfig,
+        final BDFaceCheckConfig bdFaceCheckConfig,
+        final FaceDetectCallBack faceDetectCallBack) {
+        long startTime = System.currentTimeMillis();
+        // 鍒涘缓妫�娴嬬粨鏋滃瓨鍌ㄦ暟鎹�
+        LivenessModel livenessModel = new LivenessModel();
+        // 鍒涘缓妫�娴嬪璞★紝濡傛灉鍘熷鏁版嵁YUV锛岃浆涓虹畻娉曟娴嬬殑鍥剧墖BGR
+        // TODO: 鐢ㄦ埛璋冩暣鏃嬭浆瑙掑害鍜屾槸鍚﹂暅鍍忥紝鎵嬫満鍜屽紑鍙戠増闇�瑕佸姩鎬侀�傞厤
+        BDFaceImageInstance rgbInstance = getBdImage(bdFaceImageConfig, bdFaceCheckConfig.darkEnhance);
+        livenessModel.setTestBDFaceImageInstanceDuration(System.currentTimeMillis() - startTime);
+        onTrack(
+            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.setBdFaceImageInstance(rgbInstance.getImage());
+                        faceDetectCallBack.onFaceDetectDarwCallback(livenessModel);
+                        faceDetectCallBack.onTip(0, "鏈娴嬪埌浜鸿劯");
+                    }
+
+                }
+            });
+    }
+
+    /**
+     * 閲戣瀺娲绘-娲讳綋
+     *
+     * @param rgbInstance            鍙鍏夊簳灞傞�佹瀵硅薄
+     * @param nirBDFaceImageConfig   绾㈠YUV 鏁版嵁娴�
+     * @param depthBDFaceImageConfig 娣卞害depth 鏁版嵁娴�
+     * @param livenessModel          妫�娴嬬粨鏋滄暟鎹泦鍚�
+     * @param startTime              寮�濮嬫娴嬫椂闂�
+     * @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) {
+
+        if (future2 != null && !future2.isDone()) {
+            // 娴佺▼缁撴潫閿�姣佸浘鐗囷紝寮�濮嬩笅涓�甯у浘鐗囨娴嬶紝鍚︾潃鍐呭瓨娉勯湶
+
+            return;
+        }
+
+        future2 =
+            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 onQualitySuccess() {
+                                                livenessModel.setQualityCheck(false);
+                                                // 鑾峰彇LivenessConfig liveCheckMode 閰嶇疆閫夐」锛氥�愪笉浣跨敤娲讳綋锛�0銆戯紱銆怰GB娲讳綋锛�1銆戯紱銆怰GB+NIR娲讳綋锛�2銆戯紱銆怰GB+Depth娲讳綋锛�3銆戯紱銆怰GB+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) {
+
+                                                    // 鍒涘缓妫�娴嬪璞★紝濡傛灉鍘熷鏁版嵁YUV-IR锛岃浆涓虹畻娉曟娴嬬殑鍥剧墖BGR
+                                                    // TODO: 鐢ㄦ埛璋冩暣鏃嬭浆瑙掑害鍜屾槸鍚﹂暅鍍忥紝鎵嬫満鍜屽紑鍙戠増闇�瑕佸姩鎬侀�傞厤
+                                                    nirInstance = getBdImage(nirBDFaceImageConfig, false);
+                                                    livenessModel.setBdNirFaceImageInstance(nirInstance.getImage());
+
+                                                    // 閬垮厤RGB妫�娴嬪叧閿偣鍦↖R瀵归綈娲讳綋绋冲畾锛屽鍔犵孩澶栨娴�
+                                                    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());
+                                                // 娴佺▼缁撴潫閿�姣佸浘鐗囷紝寮�濮嬩笅涓�甯у浘鐗囨娴嬶紝鍚︾潃鍐呭瓨娉勯湶
+
+                                                // 鏄剧ず鏈�缁堢粨鏋滄彁绀�
+                                                if (faceDetectCallBack != null) {
+                                                    faceDetectCallBack.onFaceDetectCallback(livenessModel);
+                                                }
+                                            }
+
+                                            @Override
+                                            public void onQualityFail(String detectFail, String occlusionFail) {
+                                                livenessModel.setQualityOcclusion(occlusionFail);
+                                                livenessModel.setQualityDetect(detectFail);
+                                                livenessModel.setQualityCheck(true);
+
+                                                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) {
+
+        long startDetectTime = System.currentTimeMillis();
+
+        livenessModel.setRgbDetectDuration(System.currentTimeMillis() - startDetectTime);
+        // track
+        FaceInfo[] faceInfos = null;
+        // 澶氫汉閲囩敤妫�娴嬶紝涓嶈兘璺熻釜
+        if (isMultiIdentify){
+            faceInfos = getDetectCheck(rgbInstance);
+        }
+        else{
+            faceInfos = getTrackCheck(rgbInstance);
+        }
+
+        // 妫�娴嬬粨鏋滃垽鏂�
+        if (faceInfos == null || faceInfos.length == 0) {
+            detectListener.onDetectFail();
+            return;
+        }
+        livenessModel.setTrackFaceInfo(faceInfos);
+        //  livenessModel.setFaceInfo(faceInfos[0]);
+        // 淇敼涓鸿繑鍥炲浜鸿劯妗�
+        //  livenessModel.setFaceInfos(faceInfos);
+        livenessModel.setFaceInfos(faceInfos);
+        livenessModel.setTrackLandmarks(faceInfos[0].landmarks);
+
+        livenessModel.setTrackStatus(1);
+
+        //  detectListener.onDetectSuccess(faceInfos, rgbInstance);
+        detectListener.onDetectSuccess(faceInfos, rgbInstance);
+
+        /*  if (size > 0) {
+            byte[] featureArr1 = new byte[512];
+            byte[] featureArr2 = new byte[512];
+
+            float featureSize = faceModel.getFaceFeature().feature(
+                    BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO, rgbInstance, new_faceInfos[0].landmarks, featureArr1);
+
+            Log.d("Attend", "compare_score1111:" + featureSize);
+            featureSize = faceModel.getFaceFeature().feature(
+                    BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO, rgbInstance, new_faceInfos[0].landmarks, featureArr1);
+
+            Log.d("Attend", "compare_score2222:" + featureSize);
+            FaceSearch faceSearch = new FaceSearch();
+            float featureScore = faceSearch.compare(
+                    BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO,
+                    featureArr1,
+                    featureArr2,
+                    true);
+            Log.d("Attend", "compare_score:" + featureScore);
+        } */
+
+    }
+
+    /**
+     * 璐ㄩ噺妫�娴嬬粨鏋滆繃婊わ紝濡傛灉闇�瑕佽川閲忔娴嬶紝
+     * 闇�瑕佽皟鐢� SingleBaseConfig.getBaseConfig().setQualityControl(true);璁剧疆涓簍rue锛�
+     * 鍐嶈皟鐢�  FaceSDKManager.getInstance().initConfig() 鍔犺浇鍒板簳灞傞厤缃」涓�
+     *
+     * @param faceInfos
+     * @param faceInfos
+     * @param faceDetectCallBack
+     * @return
+     */
+    public void onQualityCheck(
+        final FaceInfo[] faceInfos,
+        final BDQualityConfig bdQualityConfig,
+        final FaceDetectCallBack faceDetectCallBack,
+        final QualityListener qualityListener) {
+
+        if (bdQualityConfig == null) {
+            qualityListener.onQualitySuccess();
+            return;
+        }
+        // 妫�娴嬬粨鏋滆繃婊�
+        // 瑙掑害杩囨护
+
+        boolean checkQualityOk = true;
+        String detectFail = "";
+        String occlusionFail = "";
+        if (faceInfos != null) {
+            int size = faceInfos.length;
+
+            for (int i = 0; i < size; i++) {
+                StringBuffer stringBufferDetected = new StringBuffer();
+                StringBuffer stringBufferOcclusion = new StringBuffer();
+
+                FaceInfo faceInfo = faceInfos[i];
+
+                // 瑙掑害杩囨护
+                if (Math.abs(faceInfo.yaw) > bdQualityConfig.gesture) {
+                    faceDetectCallBack.onTip(-1, "浜鸿劯宸﹀彸鍋忚浆瑙掕秴鍑洪檺鍒�");
+                    stringBufferDetected.append("浜鸿劯宸﹀彸鍋忚浆瑙掕秴鍑洪檺鍒�");
+                } else if (Math.abs(faceInfo.roll) > bdQualityConfig.gesture) {
+                    faceDetectCallBack.onTip(-1, "浜鸿劯骞宠骞抽潰鍐呯殑澶撮儴鏃嬭浆瑙掕秴鍑洪檺鍒�");
+                    stringBufferDetected.append("浜鸿劯骞宠骞抽潰鍐呯殑澶撮儴鏃嬭浆瑙掕秴鍑洪檺鍒�");
+                } else if (Math.abs(faceInfo.pitch) > bdQualityConfig.gesture) {
+                    faceDetectCallBack.onTip(-1, "浜鸿劯涓婁笅鍋忚浆瑙掕秴鍑洪檺鍒�");
+                    stringBufferDetected.append("浜鸿劯涓婁笅鍋忚浆瑙掕秴鍑洪檺鍒�");
+                }
+
+                // 妯$硦缁撴灉杩囨护
+                float blur = faceInfo.bluriness;
+                if (blur > bdQualityConfig.blur) {
+                    faceDetectCallBack.onTip(-1, "鍥剧墖妯$硦");
+                    stringBufferDetected.append("鍥剧墖妯$硦");
+                }
+
+                // 鍏夌収缁撴灉杩囨护
+                float illum = faceInfo.illum;
+                Log.e("illum", "illum = " + illum);
+                if (illum < bdQualityConfig.illum) {
+                    faceDetectCallBack.onTip(-1, "鍥剧墖鍏夌収涓嶉�氳繃");
+                    stringBufferDetected.append("鍥剧墖鍏夌収涓嶉�氳繃");
+                }
+
+                if (!checkMouthMask) {
+                    // 閬尅缁撴灉杩囨护
+                    if (faceInfo.occlusion != null) {
+                        BDFaceOcclusion occlusion = faceInfo.occlusion;
+
+                        if (occlusion.leftEye > bdQualityConfig.leftEye) {
+                            // 宸︾溂閬尅缃俊搴�
+                            faceDetectCallBack.onTip(-1, "宸︾溂閬尅");
+                            stringBufferOcclusion.append("宸︾溂閬尅");
+                        } else if (occlusion.rightEye > bdQualityConfig.rightEye) {
+                            // 鍙崇溂閬尅缃俊搴�
+                            faceDetectCallBack.onTip(-1, "鍙崇溂閬尅");
+                            stringBufferOcclusion.append("鍙崇溂閬尅");
+                        } else if (occlusion.nose > bdQualityConfig.nose) {
+                            // 榧诲瓙閬尅缃俊搴�
+                            faceDetectCallBack.onTip(-1, "榧诲瓙閬尅");
+                            stringBufferOcclusion.append("榧诲瓙閬尅");
+                        } else if (occlusion.mouth > bdQualityConfig.mouth) {
+                            // 鍢村反閬尅缃俊搴�
+                            faceDetectCallBack.onTip(-1, "鍢村反閬尅");
+                            stringBufferOcclusion.append("鍢村反閬尅");
+                        } else if (occlusion.leftCheek > bdQualityConfig.leftCheek) {
+                            // 宸﹁劯閬尅缃俊搴�
+                            faceDetectCallBack.onTip(-1, "宸﹁劯閬尅");
+                            stringBufferOcclusion.append("宸﹁劯閬尅");
+                        } else if (occlusion.rightCheek > bdQualityConfig.rightCheek) {
+                            // 鍙宠劯閬尅缃俊搴�
+                            faceDetectCallBack.onTip(-1, "鍙宠劯閬尅");
+                            stringBufferOcclusion.append("鍙宠劯閬尅");
+                        } else if (occlusion.chin > bdQualityConfig.chinContour) {
+                            // 涓嬪反閬尅缃俊搴�
+                            faceDetectCallBack.onTip(-1, "涓嬪反閬尅");
+                            stringBufferOcclusion.append("涓嬪反閬尅");
+                        }
+                    }
+                }
+                if (!TextUtils.isEmpty(stringBufferDetected.toString())
+                    || !TextUtils.isEmpty(stringBufferOcclusion.toString())) {
+                    if (!TextUtils.isEmpty(stringBufferDetected.toString())) {
+                        detectFail = stringBufferDetected.toString();
+                    }
+                    if (!TextUtils.isEmpty(stringBufferOcclusion.toString())) {
+                        occlusionFail = stringBufferOcclusion.toString();
+                    }
+                    checkQualityOk = false;
+                }
+            }
+        }
+        if (checkQualityOk) {
+            qualityListener.onQualitySuccess();
+            return;
+        }
+        qualityListener.onQualityFail(detectFail, occlusionFail);
+    }
+    /**
+     * 璐ㄩ噺妫�娴嬬粨鏋滆繃婊わ紝濡傛灉闇�瑕佽川閲忔娴嬶紝
+     * 闇�瑕佽皟鐢� SingleBaseConfig.getBaseConfig().setQualityControl(true);璁剧疆涓簍rue锛�
+     * 鍐嶈皟鐢�  FaceSDKManager.getInstance().initConfig() 鍔犺浇鍒板簳灞傞厤缃」涓�
+     *
+     * @param faceInfos
+     * @param faceInfos
+     * @param faceDetectCallBack
+     * @return
+     */
+    public boolean onQualityCheck(
+        final FaceInfo[] faceInfos,
+        final BDQualityConfig bdQualityConfig,
+        final FaceDetectCallBack faceDetectCallBack) {
+
+        if (bdQualityConfig == null) {
+            return true;
+        }
+        boolean qualityCheck = false;
+        if (faceInfos != null) {
+            int size = faceInfos.length;
+            for (int i = 0; i < size; ++i) {
+                FaceInfo faceInfo = faceInfos[i];
+                boolean checkItem = true;
+                // 瑙掑害杩囨护
+                if (Math.abs(faceInfo.yaw) > bdQualityConfig.gesture) {
+                    faceDetectCallBack.onTip(-1, "浜鸿劯宸﹀彸鍋忚浆瑙掕秴鍑洪檺鍒�");
+                    checkItem = false;
+                } else if (Math.abs(faceInfo.roll) > bdQualityConfig.gesture) {
+                    faceDetectCallBack.onTip(-1, "浜鸿劯骞宠骞抽潰鍐呯殑澶撮儴鏃嬭浆瑙掕秴鍑洪檺鍒�");
+                    checkItem = false;
+                } else if (Math.abs(faceInfo.pitch) > bdQualityConfig.gesture) {
+                    faceDetectCallBack.onTip(-1, "浜鸿劯涓婁笅鍋忚浆瑙掕秴鍑洪檺鍒�");
+                    checkItem = false;
+                }
+
+                // 妯$硦缁撴灉杩囨护
+                float blur = faceInfo.bluriness;
+                if (blur > bdQualityConfig.blur) {
+                    faceDetectCallBack.onTip(-1, "鍥剧墖妯$硦");
+                    checkItem = false;
+                }
+
+                // 鍏夌収缁撴灉杩囨护
+                float illum = faceInfo.illum;
+                Log.e("illum", "illum = " + illum);
+                if (illum < bdQualityConfig.illum) {
+                    faceDetectCallBack.onTip(-1, "鍥剧墖鍏夌収涓嶉�氳繃");
+                    checkItem = false;
+                }
+
+                // 鍙g僵璇嗗埆涓嶈繘琛岃川閲忓垽鏂�
+                if (!checkMouthMask) {
+                    // 閬尅缁撴灉杩囨护
+                    if (faceInfo.occlusion != null) {
+                        BDFaceOcclusion occlusion = faceInfo.occlusion;
+
+                        if (occlusion.leftEye > bdQualityConfig.leftEye) {
+                            // 宸︾溂閬尅缃俊搴�
+                            faceDetectCallBack.onTip(-1, "宸︾溂閬尅");
+                            checkItem = false;
+                        } else if (occlusion.rightEye > bdQualityConfig.rightEye) {
+                            // 鍙崇溂閬尅缃俊搴�
+                            faceDetectCallBack.onTip(-1, "鍙崇溂閬尅");
+                            checkItem = false;
+                        } else if (occlusion.nose > bdQualityConfig.nose) {
+                            // 榧诲瓙閬尅缃俊搴�
+                            faceDetectCallBack.onTip(-1, "榧诲瓙閬尅");
+                            checkItem = false;
+                        } else if (occlusion.mouth > bdQualityConfig.mouth) {
+                            // 鍢村反閬尅缃俊搴�
+                            faceDetectCallBack.onTip(-1, "鍢村反閬尅");
+                            checkItem = false;
+                        } else if (occlusion.leftCheek > bdQualityConfig.leftCheek) {
+                            // 宸﹁劯閬尅缃俊搴�
+                            faceDetectCallBack.onTip(-1, "宸﹁劯閬尅");
+                            checkItem = false;
+                        } else if (occlusion.rightCheek > bdQualityConfig.rightCheek) {
+                            // 鍙宠劯閬尅缃俊搴�
+                            faceDetectCallBack.onTip(-1, "鍙宠劯閬尅");
+                            checkItem = false;
+                        } else if (occlusion.chin > bdQualityConfig.chinContour) {
+                            // 涓嬪反閬尅缃俊搴�
+                            faceDetectCallBack.onTip(-1, "涓嬪反閬尅");
+                        }
+                    }
+                }
+                else{
+                    return true;
+                }
+
+                if (checkItem) {
+                    qualityCheck = true;
+                    return qualityCheck;
+                }
+            }
+        }
+        return qualityCheck;
+    }
+
+    /**
+     * 璐ㄩ噺妫�娴嬬粨鏋滆繃婊わ紝濡傛灉闇�瑕佽川閲忔娴嬶紝
+     * 闇�瑕佽皟鐢� SingleBaseConfig.getBaseConfig().setQualityControl(true);璁剧疆涓簍rue锛�
+     * 鍐嶈皟鐢�  FaceSDKManager.getInstance().initConfig() 鍔犺浇鍒板簳灞傞厤缃」涓�
+     *
+     * @param faceInfo
+     * @param faceInfo
+     * @param faceDetectCallBack
+     * @return
+     */
+    public boolean onPersonQualityCheck(
+        final FaceInfo faceInfo, final BDQualityConfig bdQualityConfig, final FaceDetectCallBack faceDetectCallBack) {
+
+        if (bdQualityConfig == null) {
+            return true;
+        }
+
+        if (faceInfo != null) {
+
+            // 瑙掑害杩囨护
+            if (Math.abs(faceInfo.yaw) > bdQualityConfig.gesture) {
+                faceDetectCallBack.onTip(-1, "浜鸿劯宸﹀彸鍋忚浆瑙掕秴鍑洪檺鍒�");
+                return false;
+            } else if (Math.abs(faceInfo.roll) > bdQualityConfig.gesture) {
+                faceDetectCallBack.onTip(-1, "浜鸿劯骞宠骞抽潰鍐呯殑澶撮儴鏃嬭浆瑙掕秴鍑洪檺鍒�");
+                return false;
+            } else if (Math.abs(faceInfo.pitch) > bdQualityConfig.gesture) {
+                faceDetectCallBack.onTip(-1, "浜鸿劯涓婁笅鍋忚浆瑙掕秴鍑洪檺鍒�");
+                return false;
+            }
+
+            // 妯$硦缁撴灉杩囨护
+            float blur = faceInfo.bluriness;
+            if (blur > bdQualityConfig.blur) {
+                faceDetectCallBack.onTip(-1, "鍥剧墖妯$硦");
+                return false;
+            }
+
+            // 鍏夌収缁撴灉杩囨护
+            float illum = faceInfo.illum;
+            Log.e("illum", "illum = " + illum);
+            if (illum < bdQualityConfig.illum) {
+                faceDetectCallBack.onTip(-1, "鍥剧墖鍏夌収涓嶉�氳繃");
+                return false;
+            }
+
+            // 鍙g僵璇嗗埆涓嶈繘琛岃川閲忓垽鏂�
+            if (!checkMouthMask) {
+                // 閬尅缁撴灉杩囨护
+                if (faceInfo.occlusion != null) {
+                    BDFaceOcclusion occlusion = faceInfo.occlusion;
+
+                    if (occlusion.leftEye > bdQualityConfig.leftEye) {
+                        // 宸︾溂閬尅缃俊搴�
+                        faceDetectCallBack.onTip(-1, "宸︾溂閬尅");
+                    } else if (occlusion.rightEye > bdQualityConfig.rightEye) {
+                        // 鍙崇溂閬尅缃俊搴�
+                        faceDetectCallBack.onTip(-1, "鍙崇溂閬尅");
+                    } else if (occlusion.nose > bdQualityConfig.nose) {
+                        // 榧诲瓙閬尅缃俊搴�
+                        faceDetectCallBack.onTip(-1, "榧诲瓙閬尅");
+                    } else if (occlusion.mouth > bdQualityConfig.mouth) {
+                        // 鍢村反閬尅缃俊搴�
+                        faceDetectCallBack.onTip(-1, "鍢村反閬尅");
+                    } else if (occlusion.leftCheek > bdQualityConfig.leftCheek) {
+                        // 宸﹁劯閬尅缃俊搴�
+                        faceDetectCallBack.onTip(-1, "宸﹁劯閬尅");
+                    } else if (occlusion.rightCheek > bdQualityConfig.rightCheek) {
+                        // 鍙宠劯閬尅缃俊搴�
+                        faceDetectCallBack.onTip(-1, "鍙宠劯閬尅");
+                    } else if (occlusion.chin > bdQualityConfig.chinContour) {
+                        // 涓嬪反閬尅缃俊搴�
+                        faceDetectCallBack.onTip(-1, "涓嬪反閬尅");
+                    } else {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 妫�娴�-娲讳綋-鐗瑰緛- 鍏ㄦ祦绋�
+     * bluriness 妯$硦寰楀垎
+     * leftEye  宸︾溂閬搵寰楀垎
+     * rightEye 鍙崇溂閬搵寰楀垎
+     * nose     榧诲瓙閬搵寰楀垎
+     * mouth    鍢村反閬搵寰楀垎
+     * leftCheek 宸﹁噳鐪奸伄鎿嬪緱鍒�
+     * rightCheek 鍙宠噳閬搵寰楀垎
+     */
+    private boolean selectQuality(
+        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;
+    }
+
+    // 浜鸿瘉鏍搁獙鐗瑰緛鎻愬彇
+    public float personDetect(
+        final Bitmap bitmap, final byte[] feature, final BDFaceCheckConfig bdFaceCheckConfig, Context context) {
+        if(bitmap==null||bitmap.isRecycled()){
+            return -1;
+        }
+        BDFaceImageInstance rgbInstance = new BDFaceImageInstance(bitmap);
+        float ret = -1;
+        FaceInfo[] faceInfos;
+        BDQualityConfig bdQualityConfig = bdFaceCheckConfig == null ? null : bdFaceCheckConfig.bdQualityConfig;
+        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);
+        } else {
+            faceInfos = faceModel.getFaceDetectPerson().detect(BDFaceSDKCommon.DetectType.DETECT_VIS, rgbInstance);
+        }
+        if (faceInfos != null && faceInfos.length > 0) {
+            // 鍒ゆ柇璐ㄩ噺妫�娴嬶紝閽堝妯$硦搴︺�侀伄鎸°�佽搴�
+            if (onPersonQualityCheck(faceInfos[0], bdQualityConfig, new FaceQualityBack(context))) {
+                ret =
+                    faceModel
+                        .getFacePersonFeature()
+                        .feature(
+                            BDFaceSDKCommon.FeatureType.BDFACE_FEATURE_TYPE_LIVE_PHOTO,
+                            rgbInstance,
+                            faceInfos[0].landmarks,
+                            feature);
+            }
+        } else {
+
+            return -1;
+        }
+
+        return ret;
+    }
+}

--
Gitblit v1.9.3