Эх сурвалжийг харах

refactor(人脸识别):
- `FaceUtil`: 在人脸比对逻辑中,增加置信度阈值(0.5)判断,只有当相似度高于阈值时才返回识别成功的用户,以提高识别准确率,并增加1秒的延迟以避免短时间内重复识别。
- `FaceUtil`: 调整人脸注册逻辑,移除原有的“先搜索再更新或注册”的复杂流程,统一改为直接执行注册(`registerFaceFeature`),简化了代码逻辑。
- `CheckFaceDialog`, `LoginDialog`: 统一处理人脸识别失败的场景,在未识别到人脸(`bitmap`或`userId`为空)时,通过发送`ToastEvent`来提示用户“人脸识别失败”,改善了用户交互。

fix(人脸):
- `SetFaceFragment`: 注释掉在保存用户人脸时调用`registerFaceFeature`的代码,该操作已在`FaceUtil`中处理,避免重复注册。

chore(数据库):
- `RoomBackupWorker`: 在数据库恢复失败和完成的`finally`块中,增加发送`LoadingEvent`事件,以确保在数据库操作结束后能及时关闭加载提示。

周文健 2 долоо хоног өмнө
parent
commit
fb8ed66b3a

+ 22 - 12
data/src/main/java/com/grkj/data/hardware/face/FaceUtil.kt

@@ -30,6 +30,7 @@ import com.grkj.shared.utils.extension.isInCenterArea
 import com.grkj.shared.utils.face.arcsoft.CameraHelper
 import com.grkj.shared.utils.face.arcsoft.CameraListener
 import com.grkj.shared.widget.FaceOverlayView
+import com.sik.sikcore.extension.toJson
 import com.sik.sikcore.thread.ThreadUtils
 import com.sik.sikimage.ImageConvertUtils
 import com.sik.sikimage.ImageUtils
@@ -456,9 +457,9 @@ object FaceUtil {
 
             override fun onPreview(nv21: ByteArray?, camera: Camera?) {
                 val p = previewSize ?: return
-                val bmp = ImageConvertUtils.nv21ToBitmap(nv21, p.width, p.height)
 
                 if (backend == FaceBackend.HLK) {
+                    val bmp = ImageConvertUtils.nv21ToBitmap(nv21, p.width, p.height)
                     callBack(bmp, registerUserIdAndLocalUserId[lastUserIdByHlk])
                     return
                 }
@@ -466,6 +467,7 @@ object FaceUtil {
                 // ARC:原流程
                 if (inDetecting) return
                 inDetecting = true
+                val bmp = ImageConvertUtils.nv21ToBitmap(nv21, p.width, p.height)
                 val fe = faceEngine ?: run { inDetecting = false; return }
                 val faces = mutableListOf<FaceInfo>()
                 var code = fe.detectFaces(nv21, p.width, p.height, FaceEngine.CP_PAF_NV21, faces)
@@ -498,8 +500,15 @@ object FaceUtil {
                 )
                 val searchResult =
                     runCatching { if (fe.faceCount > 0) fe.searchFaceFeature(ft) else null }.getOrNull()
-                callBack(bmp, searchResult?.faceFeatureInfo?.searchId?.toLong())
-                inDetecting = false
+                logger.info("人脸结果:${searchResult?.maxSimilar}")
+                if ((searchResult?.maxSimilar ?: 0f) > 0.5f) {
+                    callBack(bmp, searchResult?.faceFeatureInfo?.searchId?.toLong())
+                } else {
+                    callBack(null, null)
+                }
+                ThreadUtils.runOnMainDelayed(1000) {
+                    inDetecting = false
+                }
             }
 
             override fun onCameraClosed() {}
@@ -570,15 +579,16 @@ object FaceUtil {
                 faceFeature
             )
             val info = FaceFeatureInfo(uid.toInt(), faceFeature.featureData)
-            try {
-                if ((faceEngine?.searchFaceFeature(faceFeature)?.maxSimilar ?: 0f) > 0.5) {
-                    faceEngine?.updateFaceFeature(info)
-                } else {
-                    faceEngine?.registerFaceFeature(info)
-                }
-            } catch (_: Exception) {
-                faceEngine?.registerFaceFeature(info)
-            }
+            faceEngine?.registerFaceFeature(info)
+//            try {
+//                if ((faceEngine?.searchFaceFeature(faceFeature)?.maxSimilar ?: 0f) > 0.5) {
+//                    faceEngine?.updateFaceFeature(info)
+//                } else {
+//                    faceEngine?.registerFaceFeature(info)
+//                }
+//            } catch (_: Exception) {
+//                faceEngine?.registerFaceFeature(info)
+//            }
         }
     }
 

+ 3 - 0
data/src/main/java/com/grkj/data/local/database/RoomBackupWorker.kt

@@ -76,8 +76,11 @@ class RoomBackupWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker
             // 失败也尽量恢复 Room
             runCatching { ISCSDatabase.warmReopen() }
             BackupCompleteEvent.sendBackupCompleteEvent(false)
+            LoadingEvent.sendLoadingEvent()
             DbReadyGate.open()
             Result.retry()
+        }finally {
+            LoadingEvent.sendLoadingEvent()
         }
     }
 

+ 6 - 1
iscs_lock/src/main/java/com/grkj/iscs/features/login/dialog/LoginDialog.kt

@@ -12,6 +12,8 @@ import com.grkj.data.hardware.face.FaceUtil.inDetecting
 import com.grkj.ui_base.skin.loadSkinIcon
 import com.grkj.ui_base.utils.CommonUtils
 import com.grkj.data.utils.event.LoadingEvent
+import com.grkj.data.utils.event.ToastEvent
+import com.grkj.ui_base.dialog.TipDialog
 import com.grkj.ui_base.utils.fingerprint.FingerprintUtil
 import com.kongzue.dialogx.dialogs.CustomDialog
 import com.kongzue.dialogx.dialogs.PopTip
@@ -184,7 +186,10 @@ class LoginDialog(
             FaceUtil.checkCamera(
                 mBinding.preview!!
             ) { bitmap, userId ->
-                if (bitmap == null || userId == null) return@checkCamera
+                if (bitmap == null || userId == null) {
+                    ToastEvent.sendToastEvent(CommonUtils.getStr(com.grkj.ui_base.R.string.face_login_failed))
+                    return@checkCamera
+                }
                 viewModel.loginWithUserId(userId).observe(lifecycleOwner) {
                     if (it == LoginResultEnum.FACE_VERIFY_FAILED) {
                         viewModel.loginWithFace(ImageConvertUtils.bitmapToBase64(bitmap).toString())

+ 21 - 23
iscs_lock/src/main/java/com/grkj/iscs/features/main/dialog/CheckFaceDialog.kt

@@ -12,6 +12,7 @@ import com.grkj.ui_base.base.BaseViewModel
 import com.grkj.ui_base.skin.loadSkinIcon
 import com.grkj.ui_base.utils.CommonUtils
 import com.grkj.data.utils.event.LoadingEvent
+import com.grkj.data.utils.event.ToastEvent
 import com.grkj.ui_base.utils.fingerprint.FingerprintUtil
 import com.kongzue.dialogx.dialogs.CustomDialog
 import com.kongzue.dialogx.dialogs.PopTip
@@ -161,30 +162,27 @@ class CheckFaceDialog(
             FaceUtil.checkCamera(
                 mBinding.preview!!,
             ) { bitmap, userId ->
-                if (bitmap == null || userId == null) return@checkCamera
-                bitmap?.let { itBitmap ->
-                    if (userId == null) {
-                        FaceUtil.inDetecting = false
-                        return@let
-                    }
-                    if (inFaceChecking) {
-                        FaceUtil.inDetecting = false
-                        return@let
-                    }
-                    inFaceChecking = true
-                    LoadingEvent.sendLoadingEvent()
-                    if (userId != this.userId) {
-                        FaceUtil.stop()
-                        dialog?.dismiss()
-                        callBack?.invoke(LoginResultEnum.FACE_VERIFY_FAILED)
-                        PopTip.tip(CommonUtils.getStr("face_login_failed"))
-                    } else {
-                        FaceUtil.stop()
-                        dialog?.dismiss()
-                        callBack?.invoke(LoginResultEnum.FACE_VERIFY_SUCCESS)
-                    }
-                    LoadingEvent.sendLoadingEvent(CommonUtils.getStr("doing_checking"))
+                if (bitmap == null || userId == null) {
+                    ToastEvent.sendToastEvent(CommonUtils.getStr(com.grkj.ui_base.R.string.face_login_failed))
+                    return@checkCamera
+                }
+                if (inFaceChecking) {
+                    FaceUtil.inDetecting = false
+                    return@checkCamera
+                }
+                inFaceChecking = true
+                LoadingEvent.sendLoadingEvent()
+                if (userId != this.userId) {
+                    FaceUtil.stop()
+                    dialog?.dismiss()
+                    callBack?.invoke(LoginResultEnum.FACE_VERIFY_FAILED)
+                    PopTip.tip(CommonUtils.getStr("face_login_failed"))
+                } else {
+                    FaceUtil.stop()
+                    dialog?.dismiss()
+                    callBack?.invoke(LoginResultEnum.FACE_VERIFY_SUCCESS)
                 }
+                LoadingEvent.sendLoadingEvent(CommonUtils.getStr("doing_checking"))
             }
         }
     }

+ 1 - 1
iscs_lock/src/main/java/com/grkj/iscs/features/main/fragment/user_info/SetFaceFragment.kt

@@ -97,7 +97,7 @@ class SetFaceFragment : BaseFragment<FragmentSetFaceBinding>() {
                 CommonConstants.FACE_FOLDER,
                 saveFileName
             )
-            viewModel.registerFaceFeature(imageData).observe(this) {}
+//            viewModel.registerFaceFeature(imageData).observe(this) {}
             viewModel.saveUserFace(savePath).observe(this) {
                 getData()
             }