人脸识别+采集分开处理
This commit is contained in:
@@ -39,6 +39,9 @@ import com.sw.platecabinet.MyApp
|
||||
import com.sw.platecabinet.R
|
||||
import com.sw.platecabinet.databinding.ActivityLoginFaceBinding
|
||||
import com.sw.platecabinet.databinding.ItemTitleTimeBinding
|
||||
import com.sw.platecabinet.ext.clickWithDebounce
|
||||
import com.sw.platecabinet.ext.gone
|
||||
import com.sw.platecabinet.ext.visible
|
||||
import com.sw.platecabinet.model.response.EquipmentUserInfo
|
||||
import com.sw.platecabinet.model.response.UserFaceModel
|
||||
import com.sw.platecabinet.utils.BitmapSaver
|
||||
@@ -148,7 +151,21 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
|
||||
soundMap[COLLECT_SUCCESS] = R.raw.collect_success
|
||||
soundMap[RECOGNIZE_SUCCESS] = R.raw.recognize_success
|
||||
soundMap[NO_PLATE_REMIND] = R.raw.no_plate_remind
|
||||
SoundPoolUtil.getInstance().loadR(this, soundMap);
|
||||
SoundPoolUtil.getInstance().loadR(this, soundMap)
|
||||
|
||||
binding.btnCollect.clickWithDebounce {
|
||||
//先重置,后采集
|
||||
resetRecognizeState()
|
||||
//采集数据按钮
|
||||
retryFailCount = 0
|
||||
isCollectFace = true
|
||||
collectFace()
|
||||
}
|
||||
|
||||
binding.btnRetry.clickWithDebounce {
|
||||
//重新识别按钮
|
||||
resetRecognizeState()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -187,6 +204,17 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
|
||||
private val regDebouncer = Debouncer(3000)
|
||||
private var registerHandler: RegisterCallbackHandler? = null
|
||||
|
||||
private fun isFitData(userFaceInfo: UserFaceInfo?): Boolean {
|
||||
if (userFaceInfo == null) return false
|
||||
val headBmp = userFaceInfo.headBmp
|
||||
if (headBmp == null) return false
|
||||
if (headBmp.width <= 200 || headBmp.height <= 200) {
|
||||
loadLogInfo("collectFace,isFitData:拿到人脸提取特征数据照片过小-----------")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun initArcViewModel() {
|
||||
recognizeViewModel.setLiveType(livenessType)
|
||||
recognizeViewModel.prepareRegister()
|
||||
@@ -195,14 +223,10 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
|
||||
if (!isCollectFace) {
|
||||
return@setCallback
|
||||
}
|
||||
if (this.userFaceInfo == null && userFaceInfo != null) {
|
||||
if (this.userFaceInfo == null && isFitData(userFaceInfo)) {
|
||||
recognizeViewModel.updateRegisterStatus(RecognizeViewModel.REGISTER_STATUS_DONE)
|
||||
this.userFaceInfo = userFaceInfo
|
||||
getFaceDataBlock { faceData, headBmp ->
|
||||
isCollecting.set(false)
|
||||
isCollectFace = false
|
||||
sendFaceData(faceData, headBmp)
|
||||
}
|
||||
getFaceDataBlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -247,11 +271,7 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
|
||||
|
||||
recognizeViewModel.recognizeUserId.observe(this, Observer { result: CompareResult? ->
|
||||
loadLogInfo("collectFace,recognizeUserId observe userId = ${result?.faceEntity?.userName}")
|
||||
if (faceUseSwitch) {
|
||||
loadFaceRecognizeResult2(result)
|
||||
return@Observer
|
||||
}
|
||||
loadFaceRecognizeResult(result)
|
||||
loadFaceRecognizeResult3(result)
|
||||
})
|
||||
|
||||
recognizeViewModel.drawRectInfoText.observe(this, Observer { info ->
|
||||
@@ -288,6 +308,81 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
|
||||
private val openPlateDebouncer = Debouncer(5000)
|
||||
private val isCollecting = AtomicBoolean(false)
|
||||
|
||||
private fun loadFaceRecognizeResult3(result: CompareResult?) {
|
||||
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
|
||||
}
|
||||
|
||||
if (isCollectFace) {
|
||||
loadLogInfo("collectFace,recognizeUserId 正在采集中,忽略失败结果 similar=$similar")
|
||||
return
|
||||
}
|
||||
|
||||
// if (similar <= faceFailThreshold || retryFailCount >= maxFailCount) {
|
||||
if (retryFailCount >= maxFailCount) {
|
||||
loadLogInfo(
|
||||
"collectFace,recognizeUserId 识别失败,开始采集 similar=$similar, " +
|
||||
"retry=$retryFailCount, time=${DateTimeUtils.getDateTimeString()}"
|
||||
)
|
||||
if (!isCollecting.compareAndSet(false, true)) {
|
||||
loadLogInfo("collectFace 已在采集中,忽略重复触发")
|
||||
return
|
||||
}
|
||||
|
||||
recognizeFail()
|
||||
return
|
||||
}
|
||||
|
||||
retryFailCount++
|
||||
loadLogInfo("collectFace,recognizeUserId 中间态重试,retryFailCount=$retryFailCount")
|
||||
}
|
||||
|
||||
private fun recognizeFail() {
|
||||
countDownTimer?.cancel()
|
||||
binding.tvToInit.text = ""
|
||||
binding.tvSimilarValue.text = ""
|
||||
binding.llCollectButton.visible()
|
||||
binding.btnCollect.run {
|
||||
visible()
|
||||
if (tag == "1") {
|
||||
binding.btnRetry.gone()
|
||||
text = "重新采集"
|
||||
tag = "1"
|
||||
} else {
|
||||
binding.btnRetry.visible()
|
||||
"新用户采集"
|
||||
tag = "1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据相似度similar>设定阈值0.8作为识别成功判断,
|
||||
* 如果similar<0.3作为识别失败判断,
|
||||
@@ -352,38 +447,6 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
|
||||
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作为识别是否成功来加载人脸识别结果
|
||||
*/
|
||||
@@ -449,6 +512,9 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
|
||||
Debouncer(5000).debounce {
|
||||
//打开柜子
|
||||
PlateUtils.open(this, item.equipmentBoxCode, false)
|
||||
|
||||
countDownTimer?.cancel()
|
||||
goInitActivity()
|
||||
}
|
||||
currentPlateInfo = item
|
||||
MyApp.plateList = items
|
||||
@@ -600,6 +666,9 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
|
||||
currentPlateInfo = null
|
||||
currentUserId = null
|
||||
userFaceInfo = null
|
||||
binding.btnCollect.tag = ""
|
||||
binding.tvSimilarValue.text = ""
|
||||
retryFailCount = 0
|
||||
}
|
||||
recognizeViewModel.clearLeftFace(facePreviewInfoList)
|
||||
}
|
||||
@@ -680,13 +749,13 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 临时用户id
|
||||
*/
|
||||
private var tempUserId: String = ""
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
registerHandler = RegisterCallbackHandler()
|
||||
try {
|
||||
if (isFirstOpen) {
|
||||
goInitActivity()
|
||||
@@ -695,26 +764,32 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
|
||||
}, 1000)
|
||||
return
|
||||
}
|
||||
retryFailCount = 0
|
||||
binding.tvSimilarValue.text = ""
|
||||
isCollecting.set(false)
|
||||
isCollectFace = false
|
||||
plateEnable = true
|
||||
collectCount = 0
|
||||
tempUserId = "${System.currentTimeMillis()}"
|
||||
resumeCamera()
|
||||
userViewModel.resetUserInfo()
|
||||
countDownTimer?.let {
|
||||
it.cancel()
|
||||
it.start()
|
||||
}
|
||||
// initFaceScheduler()
|
||||
// checkFaceState()
|
||||
resetRecognizeState()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置识别状态
|
||||
*/
|
||||
private fun resetRecognizeState() {
|
||||
binding.llCollectButton.gone()
|
||||
retryFailCount = 0
|
||||
binding.tvSimilarValue.text = ""
|
||||
isCollecting.set(false)
|
||||
isCollectFace = false
|
||||
plateEnable = true
|
||||
collectCount = 0
|
||||
tempUserId = "${System.currentTimeMillis()}"
|
||||
resumeCamera()
|
||||
registerHandler = RegisterCallbackHandler()
|
||||
countDownTimer?.let {
|
||||
it.cancel()
|
||||
it.start()
|
||||
}
|
||||
}
|
||||
|
||||
private var isFirstOpen = true
|
||||
|
||||
protected override fun onPause() {
|
||||
@@ -742,7 +817,11 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
|
||||
}
|
||||
|
||||
override fun onFinish() {
|
||||
goInitActivity()
|
||||
if (facePreviewInfoList.isNullOrEmpty()) {
|
||||
goInitActivity()
|
||||
} else {
|
||||
recognizeFail()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -813,16 +892,22 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFaceDataBlock(block: (String, Bitmap) -> Unit) {
|
||||
if (userFaceInfo == null || userFaceInfo?.faceFeature?.featureData == null) {
|
||||
private fun getFaceDataBlock() {
|
||||
if (userFaceInfo?.faceFeature?.featureData == null) {
|
||||
loadLogInfo("collectFace,getFaceData: ----------7,拿到人脸提取特征数据为null-----------")
|
||||
return
|
||||
}
|
||||
val faceData: String? = Base64.encode(userFaceInfo?.faceFeature?.featureData)
|
||||
if (faceData.isNullOrBlank()) {
|
||||
loadLogInfo("collectFace,getFaceData: ----------7,拿到人脸提取特征数据Base64编码为空")
|
||||
return
|
||||
}
|
||||
loadLogInfo("collectFace,getFaceData: ----------7,拿到人脸提取特征数据时间:${DateTimeUtils.getDateTimeString()}-----------")
|
||||
block(faceData, userFaceInfo!!.headBmp)
|
||||
val headBmp = userFaceInfo!!.headBmp
|
||||
//block(faceData, headBmp)
|
||||
isCollecting.set(false)
|
||||
isCollectFace = false
|
||||
sendFaceData(faceData, headBmp)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user