| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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); |
| | | } |
| | | |
| | | /** |
| | | * æ°æ®åºåç°ååæ¶åï¼éæ°ææ°æ®åºä¸ç人è¸ä¿¡æ¯æ·»å å°å
åä¸ï¼id+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 å¯è§å
YUV æ°æ®æµ |
| | | * @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()); |
| | | // å£ç½©æ£æµæ°æ® |
| | | 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; |
| | | } |
| | | |
| | | // è´¨éæ£æµæªéè¿,鿝BDFaceImageInstanceï¼ç»æå½æ° |
| | | |
| | | if (!onQualityCheck( |
| | | faceInfos, bdFaceCheckConfig.bdQualityConfig, faceDetectCallBack)) { |
| | | livenessModel.setQualityCheck(true); |
| | | livenessModel.clearIdentifyResults(); |
| | | |
| | | if (faceDetectCallBack != null) { |
| | | faceDetectCallBack.onFaceDetectCallback(livenessModel); |
| | | } |
| | | return; |
| | | } |
| | | |
| | | livenessModel.setQualityCheck(false); |
| | | // è·åLivenessConfig liveCheckMode é
ç½®é项ï¼ãä¸ä½¿ç¨æ´»ä½ï¼0ãï¼ãRGBæ´»ä½ï¼1ãï¼ãRGB+NIRæ´»ä½ï¼2ãï¼ãRGB+Depthæ´»ä½ï¼3ãï¼ãRGB+NIR+Depthæ´»ä½ï¼4ã |
| | | // TODO æ´»ä½æ£æµ |
| | | float[] rgbScores = {-1}; |
| | | BDLiveConfig bdLiveConfig = bdFaceCheckConfig.bdLiveConfig; |
| | | boolean isLiveCheck = bdFaceCheckConfig.bdLiveConfig != null; |
| | | |
| | | if (isLiveCheck) { |
| | | long startRgbTime = System.currentTimeMillis(); |
| | | rgbScores = |
| | | silentLives( |
| | | rgbInstance, |
| | | BDFaceSDKCommon.LiveType.BDFACE_SILENT_LIVE_TYPE_RGB, |
| | | faceInfos, |
| | | mRgbLiveList, |
| | | bdLiveConfig.rgbLiveScore); |
| | | /* if (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æ£æµå
³é®ç¹å¨IR坹齿´»ä½ç¨³å®ï¼å¢å çº¢å¤æ£æµ |
| | | long startIrDetectTime = System.currentTimeMillis(); |
| | | BDFaceDetectListConf bdFaceDetectListConf = new BDFaceDetectListConf(); |
| | | bdFaceDetectListConf.usingDetect = true; |
| | | faceInfosIr = |
| | | faceModel |
| | | .getFaceNirDetect() |
| | | .detect( |
| | | BDFaceSDKCommon.DetectType.DETECT_NIR, |
| | | BDFaceSDKCommon.AlignType.BDFACE_ALIGN_TYPE_NIR_ACCURATE, |
| | | nirInstance, |
| | | null, |
| | | bdFaceDetectListConf); |
| | | livenessModel.setIrLivenessDuration( |
| | | System.currentTimeMillis() - startIrDetectTime); |
| | | // LogUtils.e(TIME_TAG, "detect ir time = " + livenessModel.getIrLivenessDuration()); |
| | | if (faceInfosIr != null && faceInfosIr.length > 0) { |
| | | FaceInfo faceInfoIr = faceInfosIr[0]; |
| | | nirScore = |
| | | silentLive( |
| | | nirInstance, |
| | | BDFaceSDKCommon.LiveType.BDFACE_SILENT_LIVE_TYPE_NIR, |
| | | faceInfoIr.landmarks, |
| | | mNirLiveList, |
| | | bdLiveConfig.nirLiveScore); |
| | | livenessModel.setIrLivenessScore(nirScore); |
| | | // LogUtils.e(TIME_TAG, "live ir time = " + livenessModel.getIrLivenessDuration()); |
| | | } |
| | | } |
| | | |
| | | // TODO depthæ´»ä½æ£æµ |
| | | float depthScore = -1; |
| | | boolean isHaveDepthImage = depthBDFaceImageConfig != null && isLiveCheck; |
| | | if (depthBDFaceImageConfig != null) { |
| | | // TODO: ç¨æ·è°æ´æè½¬è§åº¦åæ¯å¦éåï¼éé
Atlas é头ï¼ç®å宽åé«400*640ï¼å
¶ä»æå头éè¦å¨æè°æ´,人è¸72 个å
³é®ç¹x åæ å左移å¨80个åç´ ç¹ |
| | | float[] depthLandmark = new float[faceInfos[0].landmarks.length]; |
| | | BDFaceImageInstance depthInstance; |
| | | if (bdFaceCheckConfig.cameraType == 1) { |
| | | System.arraycopy( |
| | | faceInfos[0].landmarks, |
| | | 0, |
| | | depthLandmark, |
| | | 0, |
| | | faceInfos[0].landmarks.length); |
| | | for (int i = 0; i < 144; i = i + 2) { |
| | | depthLandmark[i] -= 80; |
| | | } |
| | | } else { |
| | | depthLandmark = faceInfos[0].landmarks; |
| | | } |
| | | depthInstance = getBdImage(depthBDFaceImageConfig, false); |
| | | livenessModel.setBdDepthFaceImageInstance(depthInstance.getImage()); |
| | | // åå»ºæ£æµå¯¹è±¡ï¼å¦æåå§æ°æ®Depth |
| | | long startDepthTime = System.currentTimeMillis(); |
| | | depthScore = |
| | | faceModel |
| | | .getFaceLive() |
| | | .silentLive( |
| | | BDFaceSDKCommon.LiveType.BDFACE_SILENT_LIVE_TYPE_DEPTH, |
| | | depthInstance, |
| | | depthLandmark); |
| | | livenessModel.setDepthLivenessScore(depthScore); |
| | | livenessModel.setDepthtLivenessDuration( |
| | | System.currentTimeMillis() - startDepthTime); |
| | | // LogUtils.e(TIME_TAG, "live depth time = " + livenessModel.getDepthtLivenessDuration()); |
| | | depthInstance.destory(); |
| | | } |
| | | |
| | | 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ï¼Næ£ç´¢ï¼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ï¼Næ£ç´¢ï¼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ï¼Næ£ç´¢ï¼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 ä¸ªæ°æ®éåï¼æ¤å¤å¯ä»¥ä»»æè®¾ç½®ï¼ä¼è¿åæ¯å¯¹ä»å¤§å°å°æåºçnum ä¸ªæ°æ®éå |
| | | 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ï¼Næ£ç´¢ï¼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 ä¸ªæ°æ®éåï¼æ¤å¤å¯ä»¥ä»»æè®¾ç½®ï¼ä¼è¿åæ¯å¯¹ä»å¤§å°å°æåºçnum ä¸ªæ°æ®éå |
| | | if (featureResult != null && featureResult.size() > 0) { |
| | | //System.out.println("==isOk==>å¹é
å°æ°é"+featureResult.size()); |
| | | User user = null; |
| | | Feature topFeature = null; |
| | | if(TextUtils.isEmpty(groupId)){ |
| | | //为空ï¼éè¦æåºï¼ä¼å
åä¼å |
| | | for(Feature feat:featureResult) { |
| | | threholdScore = bdFaceCheckConfig.scoreThreshold; |
| | | if (feat != null && feat.getScore() > threholdScore) { |
| | | User userOld = FaceApi.getInstance().getUserListById(feat.getId()); |
| | | //System.out.println("==isOk==>å¹é
å°ç±»å:"+userOld.getUserName()); |
| | | if("1".equals(userOld.getGroupId())){ |
| | | user = userOld; |
| | | topFeature = feat; |
| | | break; |
| | | }else if(user==null){ |
| | | user = userOld; |
| | | topFeature = feat; |
| | | } |
| | | } |
| | | } |
| | | }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 å¯è§å
YUV æ°æ®æµ |
| | | * @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ãï¼ãRGBæ´»ä½ï¼1ãï¼ãRGB+NIRæ´»ä½ï¼2ãï¼ãRGB+Depthæ´»ä½ï¼3ãï¼ãRGB+NIR+Depthæ´»ä½ï¼4ã |
| | | // TODO æ´»ä½æ£æµ |
| | | BDLiveConfig bdLiveConfig = bdFaceCheckConfig.bdLiveConfig; |
| | | boolean isLiveCheck = bdFaceCheckConfig.bdLiveConfig != null; |
| | | if (isLiveCheck) { |
| | | long startRgbTime = System.currentTimeMillis(); |
| | | boolean rgbLiveStatus = |
| | | faceModel |
| | | .getFaceLive() |
| | | .strategySilentLive( |
| | | BDFaceSDKCommon.LiveType.BDFACE_SILENT_LIVE_TYPE_RGB, |
| | | rgbInstance, |
| | | faceInfos[0], |
| | | bdLiveConfig.framesThreshold, |
| | | bdLiveConfig.rgbLiveScore); |
| | | livenessModel.setRGBLiveStatus(rgbLiveStatus); |
| | | livenessModel.setRgbLivenessDuration( |
| | | System.currentTimeMillis() - startRgbTime); |
| | | } |
| | | // TODO niræ´»ä½æ£æµ |
| | | BDFaceImageInstance nirInstance = null; |
| | | boolean isHaveNirImage = nirBDFaceImageConfig != null && isLiveCheck; |
| | | if (isHaveNirImage) { |
| | | |
| | | // åå»ºæ£æµå¯¹è±¡ï¼å¦æåå§æ°æ®YUV-IRï¼è½¬ä¸ºç®æ³æ£æµçå¾çBGR |
| | | // TODO: ç¨æ·è°æ´æè½¬è§åº¦åæ¯å¦éåï¼ææºåå¼åçéè¦å¨æéé
|
| | | nirInstance = getBdImage(nirBDFaceImageConfig, false); |
| | | livenessModel.setBdNirFaceImageInstance(nirInstance.getImage()); |
| | | |
| | | // é¿å
RGBæ£æµå
³é®ç¹å¨IR坹齿´»ä½ç¨³å®ï¼å¢å çº¢å¤æ£æµ |
| | | long startIrDetectTime = System.currentTimeMillis(); |
| | | BDFaceDetectListConf bdFaceDetectListConf = |
| | | new BDFaceDetectListConf(); |
| | | bdFaceDetectListConf.usingDetect = true; |
| | | FaceInfo[] faceInfosIr = |
| | | faceModel |
| | | .getFaceNirDetect() |
| | | .detect( |
| | | BDFaceSDKCommon.DetectType.DETECT_NIR, |
| | | BDFaceSDKCommon.AlignType |
| | | .BDFACE_ALIGN_TYPE_NIR_ACCURATE, |
| | | nirInstance, |
| | | null, |
| | | bdFaceDetectListConf); |
| | | bdFaceDetectListConf.usingDetect = false; |
| | | livenessModel.setIrLivenessDuration( |
| | | System.currentTimeMillis() - startIrDetectTime); |
| | | // LogUtils.e(TIME_TAG, "detect ir time = " + livenessModel.getIrLivenessDuration()); |
| | | |
| | | if (faceInfosIr != null && faceInfosIr.length > 0) { |
| | | FaceInfo faceInfoIr = faceInfosIr[0]; |
| | | long startNirTime = System.currentTimeMillis(); |
| | | boolean nirLiveStatus = |
| | | faceModel |
| | | .getFaceLive() |
| | | .strategySilentLive( |
| | | BDFaceSDKCommon.LiveType |
| | | .BDFACE_SILENT_LIVE_TYPE_NIR, |
| | | nirInstance, |
| | | faceInfoIr, |
| | | bdLiveConfig.framesThreshold, |
| | | bdLiveConfig.nirLiveScore); |
| | | livenessModel.setNIRLiveStatus(nirLiveStatus); |
| | | livenessModel.setIrLivenessDuration( |
| | | System.currentTimeMillis() - startNirTime); |
| | | } |
| | | |
| | | nirInstance.destory(); |
| | | } |
| | | // TODO depthæ´»ä½æ£æµ |
| | | if (depthBDFaceImageConfig != null) { |
| | | fastFaceInfos[0].landmarks = faceInfos[0].landmarks; |
| | | // TODO: ç¨æ·è°æ´æè½¬è§åº¦åæ¯å¦éåï¼éé
Atlas é头ï¼ç®å宽åé«400*640ï¼å
¶ä»æå头éè¦å¨æè°æ´,人è¸72 个å
³é®ç¹x åæ å左移å¨80个åç´ ç¹ |
| | | float[] depthLandmark = new float[faceInfos[0].landmarks.length]; |
| | | BDFaceImageInstance depthInstance; |
| | | if (bdFaceCheckConfig.cameraType == 1) { |
| | | System.arraycopy( |
| | | faceInfos[0].landmarks, |
| | | 0, |
| | | depthLandmark, |
| | | 0, |
| | | faceInfos[0].landmarks.length); |
| | | for (int i = 0; i < 144; i = i + 2) { |
| | | depthLandmark[i] -= 80; |
| | | } |
| | | fastFaceInfos[0].landmarks = depthLandmark; |
| | | } |
| | | |
| | | depthInstance = getBdImage(depthBDFaceImageConfig, false); |
| | | livenessModel.setBdDepthFaceImageInstance(depthInstance.getImage()); |
| | | // åå»ºæ£æµå¯¹è±¡ï¼å¦æåå§æ°æ®Depth |
| | | long startDepthTime = System.currentTimeMillis(); |
| | | boolean depthLiveStatus = |
| | | faceModel |
| | | .getFaceLive() |
| | | .strategySilentLive( |
| | | BDFaceSDKCommon.LiveType.BDFACE_SILENT_LIVE_TYPE_DEPTH, |
| | | depthInstance, |
| | | fastFaceInfos[0], |
| | | bdLiveConfig.framesThreshold, |
| | | bdLiveConfig.nirLiveScore); |
| | | livenessModel.setDepthLiveStatus(depthLiveStatus); |
| | | livenessModel.setDepthtLivenessDuration( |
| | | System.currentTimeMillis() - startDepthTime); |
| | | depthInstance.destory(); |
| | | } |
| | | // æµç¨ç»æ,è®°å½æç»æ¶é´ |
| | | livenessModel.setAllDetectDuration( |
| | | System.currentTimeMillis() - startTime); |
| | | // LogUtils.e(TIME_TAG, "all process time = " + livenessModel.getAllDetectDuration()); |
| | | // æµç¨ç»æéæ¯å¾çï¼å¼å§ä¸ä¸å¸§å¾çæ£æµï¼å¦çå
åæ³é² |
| | | |
| | | // æ¾ç¤ºæç»ç»ææç¤º |
| | | 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);设置为trueï¼ |
| | | * åè°ç¨ 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);设置为trueï¼ |
| | | * åè°ç¨ 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; |
| | | } |
| | | |
| | | // å£ç½©è¯å«ä¸è¿è¡è´¨é夿 |
| | | 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);设置为trueï¼ |
| | | * åè°ç¨ 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; |
| | | } |
| | | |
| | | // å£ç½©è¯å«ä¸è¿è¡è´¨é夿 |
| | | 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; |
| | | } |
| | | } |