From 855a84684cf917a8d6fa2db7fe3e2f1d998cdeb2 Mon Sep 17 00:00:00 2001 From: lvmeng <848755140@qq.com> Date: Thu, 22 Jan 2026 10:30:57 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=BA=E8=84=B8=E8=AF=86=E5=88=AB=E5=B0=8F?= =?UTF-8?q?=E4=BA=8E=E9=98=88=E5=80=BC=E6=97=B6=E5=A2=9E=E5=8A=A0=E9=87=8D?= =?UTF-8?q?=E8=AF=95=E6=AC=A1=E6=95=B0=EF=BC=8C=E9=99=8D=E4=BD=8E=E8=AF=86?= =?UTF-8?q?=E5=88=AB=E9=94=99=E8=AF=AF=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../activity/LoginByFaceActivity.kt | 115 +++++++++++++----- 1 file changed, 83 insertions(+), 32 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 8392492..6117ac3 100644 --- a/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt +++ b/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt @@ -1,27 +1,21 @@ package com.sw.platecabinet.activity import android.Manifest -import android.annotation.SuppressLint import android.content.Intent import android.graphics.Point import android.hardware.Camera import android.os.Build import android.os.CountDownTimer import android.util.DisplayMetrics -import android.util.Log import android.view.View import android.view.ViewGroup import android.view.ViewTreeObserver -import androidx.activity.viewModels import androidx.annotation.RequiresApi import androidx.lifecycle.Observer -import androidx.lifecycle.lifecycleScope -import androidx.recyclerview.widget.LinearLayoutManager import com.arcsoft.face.ErrorInfo import com.google.gson.Gson import com.sw.platecabinet.socket.TcpClientListenerImpl import com.sw.inbound.utils.DateTimeUtils -import com.sw.plate.App import com.sw.plate.utils.Base64 import com.sw.plate.utils.ToastUtils import com.sw.plate.utils.arcface.ConfigUtil @@ -44,34 +38,22 @@ import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel.REGISTER_STATUS_R import com.sw.platecabinet.GlobalData import com.sw.platecabinet.MyApp import com.sw.platecabinet.R -import com.sw.platecabinet.adapter.LogAdapter import com.sw.platecabinet.databinding.ActivityLoginFaceBinding import com.sw.platecabinet.databinding.ItemTitleTimeBinding -import com.sw.platecabinet.ext.gone -import com.sw.platecabinet.ext.invisible -import com.sw.platecabinet.ext.visible import com.sw.platecabinet.model.response.EquipmentUserInfo import com.sw.platecabinet.socket.LanServer import com.sw.platecabinet.socket.LanServerListenerImpl import com.sw.platecabinet.socket.TcpClient import com.sw.platecabinet.utils.Debouncer -import com.sw.platecabinet.utils.IntervalExecutor import com.sw.platecabinet.utils.PermissionHelper import com.sw.platecabinet.utils.PlateUtils import com.sw.platecabinet.utils.SoundPoolUtil import com.sw.platecabinet.utils.SpTool -import com.sw.platecabinet.utils.countDownByFlow -import kotlinx.coroutines.Job -import kotlinx.coroutines.runBlocking import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode import org.json.JSONObject import timber.log.Timber -import java.util.concurrent.Executors -import java.util.concurrent.ScheduledExecutorService -import java.util.concurrent.TimeUnit -import kotlin.math.log /** * 人脸识别 @@ -252,21 +234,11 @@ class LoginByFaceActivity : BaseActivity(), recognizeViewModel.recognizeUserId.observe(this, Observer { result: CompareResult? -> loadLogInfo("collectFace,recognizeUserId observe userId = ${result?.faceEntity?.userName}") - val similar = result?.similar?:0f - binding.tvSimilarValue.text="$similar" - val similarPass = result?.isSimilarPass?:false - if (similarPass.not()) { - loadLogInfo("collectFace,recognizeUserId 未识别到人脸信息,开始采集") - isCollectFace = true - collectFace() + if (faceUseSwitch) { + loadFaceRecognizeResult2(result) return@Observer } - currentUserId = result?.faceEntity?.userName - if (tempUserId != currentUserId) { - SoundPoolUtil.getInstance().play("success", 0) - } -// plateEnable = true - openPlate(currentUserId) + loadFaceRecognizeResult(result) }) recognizeViewModel.drawRectInfoText.observe(this, Observer { info -> @@ -274,6 +246,84 @@ class LoginByFaceActivity : BaseActivity(), }) } + /** + * 人脸识别开关,true-loadFaceRecognizeResult2,false-loadFaceRecognizeResult + */ + private var faceUseSwitch = true + + /** + * 识别失败重试次数 + */ + private var retryFailCount = 0 + + /** + * 识别失败最大次数 + */ + private val maxFailCount = 5 + + /** + * 人脸失败阈值 + */ + private val faceFailThreshold = 0.3 + + /** + * 配置阈值,默认值为0.8 + */ + private val faceSuccessThreshold by lazy { ConfigUtil.getRecognizeThreshold(this) } + + + /** + * 根据相似度similar>设定阈值0.8作为识别成功判断, + * 如果similar<0.3作为识别失败判断, + * 如果similar>=0.3&&similar<=0.8时,暂时不作为失败情况,再识别5次如果similar<0.8则作为识别失败处理 + */ + private fun loadFaceRecognizeResult2(result: CompareResult?) { + val similar = result?.similar?:0f + binding.tvSimilarValue.text="$similar" + loadLogInfo("collectFace,recognizeUserId 人脸识别配置阈值为:${faceSuccessThreshold},失败阈值为:${faceFailThreshold},相似度为:${similar},失败次数为:${retryFailCount}") + if (similar > faceSuccessThreshold) { + //大于识别阈值,作为识别成功判断 + currentUserId = result?.faceEntity?.userName + if (tempUserId != currentUserId) { + SoundPoolUtil.getInstance().play("success", 0) + } + openPlate(currentUserId) + return + } + loadLogInfo("collectFace,recognizeUserId 人脸识别相似度为:${similar},失败次数为:${retryFailCount}") + if (similar < faceFailThreshold || retryFailCount >= maxFailCount) { + //小于识别错误阈值,或者识别失败次数大于等于最大失败次数,作为识别失败判断 + loadLogInfo("collectFace,recognizeUserId 未识别到人脸信息,开始采集") + isCollectFace = true + collectFace() + return + } + //满足similar >= faceFailThreshold && similar <= successThreshold时进行重试 + retryFailCount++ + loadLogInfo("collectFace,recognizeUserId 人脸识别失败次数为:${retryFailCount}") + } + + /** + * 根据相似度similar>设定阈值0.8作为识别是否成功来加载人脸识别结果 + */ + private fun loadFaceRecognizeResult(result: CompareResult?) { + val similar = result?.similar?:0f + binding.tvSimilarValue.text="$similar" + val similarPass = result?.isSimilarPass?:false + if (similarPass.not()) { + loadLogInfo("collectFace,recognizeUserId 未识别到人脸信息,开始采集") + isCollectFace = true + collectFace() + return + } + currentUserId = result?.faceEntity?.userName + if (tempUserId != currentUserId) { + SoundPoolUtil.getInstance().play("success", 0) + } +// plateEnable = true + openPlate(currentUserId) + } + /** * 查询餐盘数据 */ @@ -559,6 +609,7 @@ class LoginByFaceActivity : BaseActivity(), }, 1000) return } + retryFailCount = 0 binding.tvSimilarValue.text="" isCollectFace = false plateEnable = true @@ -595,7 +646,7 @@ class LoginByFaceActivity : BaseActivity(), // goInitActivity() } - private val totalTimeInMillis = 10 * 1000L + private val totalTimeInMillis = 15 * 1000L fun initCountTime() { countDownTimer = object : CountDownTimer(totalTimeInMillis, 1000) { override fun onTick(millisUntilFinished: Long) {