From c5325f6ad6fe6f2184e5f3ac94f035f9ed9a32dd Mon Sep 17 00:00:00 2001 From: mazengfei <331023091@qq.com> Date: Mon, 2 Feb 2026 16:36:24 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=B5=81=E7=A8=8B=EF=BC=8C?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E4=B8=8D=E5=86=8D=E9=AA=8C=E8=AF=81=E6=B4=BB?= =?UTF-8?q?=E4=BD=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../activity/LoginByFaceActivity.kt | 113 ++++++++++++++---- .../arcface/viewmodel/RecognizeViewModel.java | 6 +- 2 files changed, 95 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt b/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt index 57728fa..efa27b6 100644 --- a/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt +++ b/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt @@ -55,6 +55,7 @@ import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode import org.json.JSONObject import timber.log.Timber +import java.util.concurrent.atomic.AtomicBoolean /** * 人脸识别 @@ -193,6 +194,7 @@ class LoginByFaceActivity : BaseActivity(), recognizeViewModel.updateRegisterStatus(RecognizeViewModel.REGISTER_STATUS_DONE) this.userFaceInfo = userFaceInfo getFaceDataBlock { faceData -> + isCollecting.set(false) isCollectFace = false Thread { saveFaceInfo(faceData) @@ -267,7 +269,7 @@ class LoginByFaceActivity : BaseActivity(), /** * 识别失败最大次数 */ - private val maxFailCount = 2 + private val maxFailCount = 5 /** * 人脸失败阈值 @@ -280,6 +282,9 @@ class LoginByFaceActivity : BaseActivity(), private val faceSuccessThreshold by lazy { ConfigUtil.getRecognizeThreshold(this) } + private val openPlateDebouncer = Debouncer(5000) + private val isCollecting = AtomicBoolean(false) + /** * 根据相似度similar>设定阈值0.8作为识别成功判断, * 如果similar<0.3作为识别失败判断, @@ -287,36 +292,99 @@ class LoginByFaceActivity : BaseActivity(), */ private fun loadFaceRecognizeResult2(result: CompareResult?) { - if(isCollectFace){ + // 无有效结果直接忽略 + val similar = result?.similar ?: return + + binding.tvSimilarValue.text = "$similar,${retryFailCount}次" + loadLogInfo( + "collectFace,recognizeUserId 阈值 success=$faceSuccessThreshold, " + + "fail=$faceFailThreshold, similar=$similar, retry=$retryFailCount" + ) + + if (similar >= faceSuccessThreshold) { + + val userId = result.faceEntity?.userName + if (userId.isNullOrBlank()) { + loadLogInfo("collectFace,recognizeUserId 识别成功但 userId 为空,忽略") + return + } + + loadLogInfo( + "collectFace,recognizeUserId 识别成功 userId=$userId, time=${DateTimeUtils.getDateTimeString()}" + ) + + // 成功后必须重置状态 + retryFailCount = 0 + isCollecting.set(false) + isCollectFace = false + currentUserId = userId + + // 防抖,防止重复开闸 + openPlateDebouncer.debounce { + openPlate(userId) + } return } - val similar = result?.similar ?: 0f - binding.tvSimilarValue.text = "$similar,${retryFailCount}次" - loadLogInfo("collectFace,recognizeUserId 人脸识别配置阈值为:${faceSuccessThreshold},失败阈值为:${faceFailThreshold},相似度为:${similar},失败次数为:${retryFailCount}") - if (similar > faceSuccessThreshold) { - loadLogInfo("collectFace,recognizeUserId 相似度为:${similar},识别成功时间:${DateTimeUtils.getDateTimeString()}") - //大 于识别阈值,作为识别成功判断 - currentUserId = result?.faceEntity?.userName - Debouncer(5000).debounce { openPlate(currentUserId) } + if (isCollectFace) { + loadLogInfo("collectFace,recognizeUserId 正在采集中,忽略失败结果 similar=$similar") return } - loadLogInfo("collectFace,recognizeUserId 人脸识别相似度为:${similar},失败次数为:${retryFailCount}") - if (similar < faceFailThreshold || retryFailCount >= maxFailCount) { - //相似度低于识别错误阈值进行采集、识别失败次数大于等于最大失败次数,作为识别失败判断 - if (isCollectFace.not()) { - //非采集中 - loadLogInfo("collectFace,recognizeUserId 未识别到人脸信息,相似度为:${similar},开始采集时间:${DateTimeUtils.getDateTimeString()}") - isCollectFace = true - collectFace() + + if (similar <= faceFailThreshold || retryFailCount >= maxFailCount) { + + loadLogInfo( + "collectFace,recognizeUserId 识别失败,开始采集 similar=$similar, " + + "retry=$retryFailCount, time=${DateTimeUtils.getDateTimeString()}" + ) + if (!isCollecting.compareAndSet(false, true)) { + loadLogInfo("collectFace 已在采集中,忽略重复触发") return } + + + retryFailCount = 0 + isCollectFace = true + collectFace()//采集人脸 + return } - //满足similar >= faceFailThreshold && similar <= successThreshold时进行重试 + retryFailCount++ - loadLogInfo("collectFace,recognizeUserId 人脸识别失败次数为:${retryFailCount}") + loadLogInfo("collectFace,recognizeUserId 中间态重试,retryFailCount=$retryFailCount") } +// private fun loadFaceRecognizeResult2(result: CompareResult?) { +// +// if(isCollectFace){ +// return +// } +// +// val similar = result?.similar ?: 0f +// binding.tvSimilarValue.text = "$similar,${retryFailCount}次" +// loadLogInfo("collectFace,recognizeUserId 人脸识别配置阈值为:${faceSuccessThreshold},失败阈值为:${faceFailThreshold},相似度为:${similar},失败次数为:${retryFailCount}") +// if (similar > faceSuccessThreshold) { +// loadLogInfo("collectFace,recognizeUserId 相似度为:${similar},识别成功时间:${DateTimeUtils.getDateTimeString()}") +// //大 于识别阈值,作为识别成功判断 +// currentUserId = result?.faceEntity?.userName +// Debouncer(5000).debounce { openPlate(currentUserId) } +// return +// } +// loadLogInfo("collectFace,recognizeUserId 人脸识别相似度为:${similar},失败次数为:${retryFailCount}") +// if (similar < faceFailThreshold || retryFailCount >= maxFailCount) { +// //相似度低于识别错误阈值进行采集、识别失败次数大于等于最大失败次数,作为识别失败判断 +// if (isCollectFace.not()) { +// //非采集中 +// loadLogInfo("collectFace,recognizeUserId 未识别到人脸信息,相似度为:${similar},开始采集时间:${DateTimeUtils.getDateTimeString()}") +// isCollectFace = true +// collectFace() +// return +// } +// } +// //满足similar >= faceFailThreshold && similar <= successThreshold时进行重试 +// retryFailCount++ +// loadLogInfo("collectFace,recognizeUserId 人脸识别失败次数为:${retryFailCount}") +// } + /** * 根据相似度similar>设定阈值0.8作为识别是否成功来加载人脸识别结果 */ @@ -370,7 +438,7 @@ class LoginByFaceActivity : BaseActivity(), return@getPlateData } // if (tempUserId != currentUserId) { - SoundPoolUtil.getInstance().play(RECOGNIZE_SUCCESS, 0) + SoundPoolUtil.getInstance().play(RECOGNIZE_SUCCESS, 0) // } else { // SoundPoolUtil.getInstance().play(COLLECT_SUCCESS, 0) // } @@ -631,6 +699,7 @@ class LoginByFaceActivity : BaseActivity(), } retryFailCount = 0 binding.tvSimilarValue.text = "" + isCollecting.set(false) isCollectFace = false plateEnable = true collectCount = 0 @@ -687,7 +756,7 @@ class LoginByFaceActivity : BaseActivity(), private fun collectFace() { loadLogInfo("collectFace: -----------1,开始采集人脸,开始时间:${DateTimeUtils.getDateTimeString()}----------") -// if (isFirstOpen) return + if (isFirstOpen) return loadLogInfo("collectFace: ----------2,isFirstOpen=false-----------") loadLogInfo("collectFace: ----------4,检测到人脸信息-----------") currentUserId = null diff --git a/lib_face/src/main/java/com/sw/plate/utils/arcface/viewmodel/RecognizeViewModel.java b/lib_face/src/main/java/com/sw/plate/utils/arcface/viewmodel/RecognizeViewModel.java index dd01899..5e0c7c9 100644 --- a/lib_face/src/main/java/com/sw/plate/utils/arcface/viewmodel/RecognizeViewModel.java +++ b/lib_face/src/main/java/com/sw/plate/utils/arcface/viewmodel/RecognizeViewModel.java @@ -280,6 +280,8 @@ public class RecognizeViewModel extends ViewModel implements RecognizeCallback { // 填入在设置界面设置好的配置信息 boolean enableLive = !ConfigUtil.getLivenessDetectType(context).equals(context.getString(R.string.value_liveness_type_disable)); + enableLive = false; + boolean enableFaceQualityDetect = ConfigUtil.isEnableImageQualityDetect(context); boolean enableFaceMoveLimit = ConfigUtil.isEnableFaceMoveLimit(context); boolean enableFaceSizeLimit = ConfigUtil.isEnableFaceSizeLimit(context); @@ -469,7 +471,7 @@ public class RecognizeViewModel extends ViewModel implements RecognizeCallback { } } - private String getUserId(CompareResult result){ + private String getUserId(CompareResult result) { if (result != null && result.getFaceEntity() != null) { return result.getFaceEntity().getUserName(); } @@ -480,7 +482,7 @@ public class RecognizeViewModel extends ViewModel implements RecognizeCallback { public void onRecognized(CompareResult compareResult, Integer live, boolean similarPass) { // TODO: 2026/1/21 测试使用 Observable.just(similarPass)代替Observable.just(true)--- Observable.just(similarPass).observeOn(AndroidSchedulers.mainThread()).subscribe(aBoolean -> { - Log.d(TAG, "collectFace,onRecognized: similarPass="+similarPass+",live="+live+",userId="+getUserId(compareResult)); + Log.d(TAG, "collectFace,onRecognized: similarPass=" + similarPass + ",live=" + live + ",userId=" + getUserId(compareResult)); if (similarPass) { recognizeUserId.postValue(compareResult); boolean isAdded = false;