人脸识别小于阈值时增加重试次数,降低识别错误情况

This commit is contained in:
2026-01-22 10:30:57 +08:00
parent f2bedb7777
commit 855a84684c
@@ -1,27 +1,21 @@
package com.sw.platecabinet.activity package com.sw.platecabinet.activity
import android.Manifest import android.Manifest
import android.annotation.SuppressLint
import android.content.Intent import android.content.Intent
import android.graphics.Point import android.graphics.Point
import android.hardware.Camera import android.hardware.Camera
import android.os.Build import android.os.Build
import android.os.CountDownTimer import android.os.CountDownTimer
import android.util.DisplayMetrics import android.util.DisplayMetrics
import android.util.Log
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.ViewTreeObserver import android.view.ViewTreeObserver
import androidx.activity.viewModels
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.arcsoft.face.ErrorInfo import com.arcsoft.face.ErrorInfo
import com.google.gson.Gson import com.google.gson.Gson
import com.sw.platecabinet.socket.TcpClientListenerImpl import com.sw.platecabinet.socket.TcpClientListenerImpl
import com.sw.inbound.utils.DateTimeUtils import com.sw.inbound.utils.DateTimeUtils
import com.sw.plate.App
import com.sw.plate.utils.Base64 import com.sw.plate.utils.Base64
import com.sw.plate.utils.ToastUtils import com.sw.plate.utils.ToastUtils
import com.sw.plate.utils.arcface.ConfigUtil 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.GlobalData
import com.sw.platecabinet.MyApp import com.sw.platecabinet.MyApp
import com.sw.platecabinet.R import com.sw.platecabinet.R
import com.sw.platecabinet.adapter.LogAdapter
import com.sw.platecabinet.databinding.ActivityLoginFaceBinding import com.sw.platecabinet.databinding.ActivityLoginFaceBinding
import com.sw.platecabinet.databinding.ItemTitleTimeBinding 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.model.response.EquipmentUserInfo
import com.sw.platecabinet.socket.LanServer import com.sw.platecabinet.socket.LanServer
import com.sw.platecabinet.socket.LanServerListenerImpl import com.sw.platecabinet.socket.LanServerListenerImpl
import com.sw.platecabinet.socket.TcpClient import com.sw.platecabinet.socket.TcpClient
import com.sw.platecabinet.utils.Debouncer import com.sw.platecabinet.utils.Debouncer
import com.sw.platecabinet.utils.IntervalExecutor
import com.sw.platecabinet.utils.PermissionHelper import com.sw.platecabinet.utils.PermissionHelper
import com.sw.platecabinet.utils.PlateUtils import com.sw.platecabinet.utils.PlateUtils
import com.sw.platecabinet.utils.SoundPoolUtil import com.sw.platecabinet.utils.SoundPoolUtil
import com.sw.platecabinet.utils.SpTool 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.EventBus
import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode import org.greenrobot.eventbus.ThreadMode
import org.json.JSONObject import org.json.JSONObject
import timber.log.Timber 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<ActivityLoginFaceBinding>(),
recognizeViewModel.recognizeUserId.observe(this, Observer { result: CompareResult? -> recognizeViewModel.recognizeUserId.observe(this, Observer { result: CompareResult? ->
loadLogInfo("collectFace,recognizeUserId observe userId = ${result?.faceEntity?.userName}") loadLogInfo("collectFace,recognizeUserId observe userId = ${result?.faceEntity?.userName}")
val similar = result?.similar?:0f if (faceUseSwitch) {
binding.tvSimilarValue.text="$similar" loadFaceRecognizeResult2(result)
val similarPass = result?.isSimilarPass?:false
if (similarPass.not()) {
loadLogInfo("collectFace,recognizeUserId 未识别到人脸信息,开始采集")
isCollectFace = true
collectFace()
return@Observer return@Observer
} }
currentUserId = result?.faceEntity?.userName loadFaceRecognizeResult(result)
if (tempUserId != currentUserId) {
SoundPoolUtil.getInstance().play("success", 0)
}
// plateEnable = true
openPlate(currentUserId)
}) })
recognizeViewModel.drawRectInfoText.observe(this, Observer { info -> recognizeViewModel.drawRectInfoText.observe(this, Observer { info ->
@@ -274,6 +246,84 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
}) })
} }
/**
* 人脸识别开关,true-loadFaceRecognizeResult2false-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<ActivityLoginFaceBinding>(),
}, 1000) }, 1000)
return return
} }
retryFailCount = 0
binding.tvSimilarValue.text="" binding.tvSimilarValue.text=""
isCollectFace = false isCollectFace = false
plateEnable = true plateEnable = true
@@ -595,7 +646,7 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
// goInitActivity() // goInitActivity()
} }
private val totalTimeInMillis = 10 * 1000L private val totalTimeInMillis = 15 * 1000L
fun initCountTime() { fun initCountTime() {
countDownTimer = object : CountDownTimer(totalTimeInMillis, 1000) { countDownTimer = object : CountDownTimer(totalTimeInMillis, 1000) {
override fun onTick(millisUntilFinished: Long) { override fun onTick(millisUntilFinished: Long) {