Selaa lähdekoodia

refactor(更新)
- 人脸录入修改

周文健 4 kuukautta sitten
vanhempi
sitoutus
d549d5685e

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

@@ -181,6 +181,7 @@ class LoginDialog(
 
 
     private fun startFace() {
+        ArcSoftUtil.inDetecting = false
         ActivityTracker.getCurrentActivity()?.let { context ->
             ArcSoftUtil.initEngine(context)
             ArcSoftUtil.initCamera(

+ 1 - 0
app/src/main/java/com/grkj/iscs/features/main/dialog/CheckFaceDialog.kt

@@ -164,6 +164,7 @@ class CheckFaceDialog(
 
 
     private fun startFace() {
+        ArcSoftUtil.inDetecting = false
         ActivityTracker.getCurrentActivity()?.let { context ->
             ArcSoftUtil.initEngine(context)
             ArcSoftUtil.initCamera(

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

@@ -96,6 +96,7 @@ class SetFaceFragment : BaseFragment<FragmentSetFaceBinding>() {
             binding.previewLayout.isVisible = true
             binding.confirm.isVisible = false
             binding.recapture.isVisible = false
+            binding.faceOverlayView.setFaceRect(null)
         }
     }
 
@@ -130,12 +131,14 @@ class SetFaceFragment : BaseFragment<FragmentSetFaceBinding>() {
     private fun startFace() {
         binding.previewLayout.isVisible = true
         binding.image.isVisible = false
+        ArcSoftUtil.inDetecting = false
         ArcSoftUtil.initEngine(requireContext())
         ArcSoftUtil.initCamera(
             requireContext(),
             requireActivity().windowManager,
             binding.preview,
-            true
+            binding.faceOverlayView,
+            true,
         ) { bitmap, faceSize, alive ->
             binding.tipTv.isVisible = faceSize > 1 || alive == false
             logger.info("人脸检测结果: ${bitmap == null},$faceSize,$alive")

+ 1 - 0
app/src/main/java/com/grkj/iscs/features/main/fragment/user_info/UserInfoFragment.kt

@@ -130,6 +130,7 @@ class UserInfoFragment : BaseFragment<FragmentUserInfoBinding>() {
     }
 
     private fun startFace() {
+        ArcSoftUtil.inDetecting = false
         binding.preview.isVisible = true
         binding.image.isVisible = false
         ArcSoftUtil.initEngine(requireContext())

+ 36 - 27
app/src/main/res/layout-land/fragment_set_face.xml

@@ -135,37 +135,46 @@
                                 android:layout_width="match_parent"
                                 android:layout_height="match_parent" />
 
-                            <ImageView
+
+                            <com.grkj.shared.widget.FaceOverlayView
+                                android:id="@+id/face_overlay_view"
                                 android:layout_width="match_parent"
-                                android:layout_height="match_parent"
-                                android:scaleType="fitXY"
-                                android:src="@drawable/mask_vector_circle" />
+                                android:layout_height="match_parent" />
 
-                            <TextView
-                                android:id="@+id/count_down_tip"
-                                android:layout_width="wrap_content"
-                                android:layout_height="wrap_content"
-                                android:layout_gravity="center|bottom"
-                                android:layout_marginBottom="@dimen/common_spacing"
-                                android:text="@string/detect_face_tip"
-                                android:textColor="@color/dialogxColorBlue"
-                                android:textSize="@dimen/common_text_size_big"
-                                android:textStyle="bold"
-                                android:visibility="gone"
-                                tools:text="检测到人脸,即将拍摄" />
-                            <TextView
-                                android:id="@+id/tip_tv"
+                            <FrameLayout
                                 android:layout_width="match_parent"
                                 android:layout_height="wrap_content"
-                                android:layout_marginTop="10dp"
-                                android:gravity="center"
-                                android:text="@string/only_one_person_allowed"
-                                android:textColor="@color/common_status_red"
-                                android:textSize="@dimen/common_text_size_big"
-                                android:layout_gravity="center|bottom"
-                                android:layout_marginBottom="@dimen/common_spacing"
-                                android:visibility="gone"
-                                tools:text="请保证画面中只有自己" />
+                                android:layout_gravity="bottom"
+                                android:background="@color/common_transparent_half">
+
+                                <TextView
+                                    android:id="@+id/count_down_tip"
+                                    android:layout_width="wrap_content"
+                                    android:layout_height="wrap_content"
+                                    android:layout_gravity="center"
+                                    android:paddingVertical="@dimen/common_spacing"
+                                    android:gravity="center"
+                                    android:text="@string/detect_face_tip"
+                                    android:textColor="@color/dialogxColorBlue"
+                                    android:textSize="@dimen/common_text_size_big"
+                                    android:textStyle="bold"
+                                    android:visibility="gone"
+                                    tools:text="检测到人脸,即将拍摄" />
+
+                                <TextView
+                                    android:id="@+id/tip_tv"
+                                    android:layout_width="match_parent"
+                                    android:layout_height="wrap_content"
+                                    android:layout_gravity="center|bottom"
+                                    android:paddingVertical="10dp"
+                                    android:gravity="center"
+                                    android:text="@string/only_one_person_allowed"
+                                    android:textColor="@color/common_status_red"
+                                    android:textSize="@dimen/common_text_size_big"
+                                    android:visibility="gone"
+                                    tools:text="请保证画面中只有自己" />
+                            </FrameLayout>
+
                         </FrameLayout>
 
                         <ImageView

+ 36 - 28
app/src/main/res/layout/fragment_set_face.xml

@@ -129,38 +129,46 @@
                             android:layout_width="match_parent"
                             android:layout_height="match_parent" />
 
-                        <ImageView
+                        <com.grkj.shared.widget.FaceOverlayView
+                            android:id="@+id/face_overlay_view"
                             android:layout_width="match_parent"
-                            android:layout_height="match_parent"
-                            android:scaleType="fitXY"
-                            android:src="@drawable/mask_vector_circle" />
-
-                        <TextView
-                            android:id="@+id/count_down_tip"
-                            android:layout_width="wrap_content"
-                            android:layout_height="wrap_content"
-                            android:layout_gravity="center|bottom"
-                            android:layout_marginBottom="@dimen/common_spacing"
-                            android:textColor="@color/dialogxColorBlue"
-                            android:textSize="@dimen/common_text_size_big"
-                            android:textStyle="bold"
-                            android:visibility="gone"
-                            android:text="@string/detect_face_tip"
-                            tools:text="检测到人脸,即将拍摄" />
+                            android:layout_height="match_parent" />
 
-                        <TextView
-                            android:id="@+id/tip_tv"
+                        <FrameLayout
                             android:layout_width="match_parent"
                             android:layout_height="wrap_content"
-                            android:layout_marginTop="10dp"
-                            android:gravity="center"
-                            android:text="@string/only_one_person_allowed"
-                            android:textColor="@color/common_status_red"
-                            android:textSize="@dimen/common_text_size_big"
-                            android:layout_gravity="center|bottom"
-                            android:layout_marginBottom="@dimen/common_spacing"
-                            android:visibility="gone"
-                            tools:text="请保证画面中只有自己" />
+                            android:layout_gravity="bottom"
+                            android:background="@color/common_transparent_half">
+
+                            <TextView
+                                android:id="@+id/count_down_tip"
+                                android:layout_width="wrap_content"
+                                android:layout_height="wrap_content"
+                                android:layout_gravity="center"
+                                android:paddingVertical="@dimen/common_spacing"
+                                android:text="@string/detect_face_tip"
+                                android:gravity="center"
+                                android:textColor="@color/dialogxColorBlue"
+                                android:textSize="@dimen/common_text_size_big"
+                                android:textStyle="bold"
+                                android:visibility="gone"
+                                tools:text="检测到人脸,即将拍摄" />
+
+                            <TextView
+                                android:id="@+id/tip_tv"
+                                android:layout_width="match_parent"
+                                android:layout_height="wrap_content"
+                                android:layout_gravity="center"
+                                android:layout_marginTop="10dp"
+                                android:layout_marginBottom="@dimen/common_spacing"
+                                android:gravity="center"
+                                android:paddingVertical="@dimen/common_spacing"
+                                android:text="@string/only_one_person_allowed"
+                                android:textColor="@color/common_status_red"
+                                android:textSize="@dimen/common_text_size_big"
+                                android:visibility="gone"
+                                tools:text="请保证画面中只有自己" />
+                        </FrameLayout>
                     </FrameLayout>
 
                     <ImageView

+ 5 - 1
shared/src/main/java/com/grkj/shared/utils/ArcSoftUtil.kt

@@ -29,6 +29,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.utils.face.arcsoft.NV21ToBitmap
+import com.grkj.shared.widget.FaceOverlayView
 import com.sik.sikimage.CropImageUtils
 import org.slf4j.Logger
 import org.slf4j.LoggerFactory
@@ -121,6 +122,7 @@ object ArcSoftUtil {
         context: Context,
         windowManager: WindowManager,
         preview: View,
+        faceOverlayView: FaceOverlayView? = null,
         needCheckCenter: Boolean = false,
         callBack: (Bitmap?, Int, Boolean) -> Unit
     ) {
@@ -136,6 +138,7 @@ object ArcSoftUtil {
             ) {
                 logger.info("onCameraOpened: $cameraId  $displayOrientation $isMirror")
                 previewSize = camera.parameters.previewSize
+                faceOverlayView?.setCameraPreviewSize(previewSize!!.width, previewSize!!.height)
             }
 
 
@@ -152,6 +155,7 @@ object ArcSoftUtil {
                     FaceEngine.CP_PAF_NV21,
                     faceInfoList
                 )
+                faceOverlayView?.setFaceRect(faceInfoList.map { it.rect })
                 if (code == ErrorInfo.MOK && faceInfoList.isNotEmpty()) {
                     code = faceEngine!!.process(
                         nv21,
@@ -245,7 +249,7 @@ object ArcSoftUtil {
         callBack: (Bitmap?, Int, Boolean) -> Unit
     ) {
         initEngine(context)
-        initCamera(context, windowManager, preview, false, callBack)
+        initCamera(context, windowManager, preview, null, false, callBack)
     }
 
     fun stop() {

+ 81 - 0
shared/src/main/java/com/grkj/shared/widget/FaceOverlayView.kt

@@ -0,0 +1,81 @@
+package com.grkj.shared.widget
+
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import android.graphics.Rect
+import android.graphics.RectF
+import android.util.AttributeSet
+import android.view.View
+
+/**
+ * 自定义人脸框绘制控件。
+ * 根据摄像头预览尺寸与 View 尺寸的等比缩放,对应绘制人脸检测到的 Rect 区域。
+ *
+ * 使用方法:
+ * 1. 在布局中引入 FaceOverlayView
+ * 2. 调用 setCameraPreviewSize(width, height)
+ * 3. 调用 setFaceRect(Rect 或 RectF)
+ */
+class FaceOverlayView @JvmOverloads constructor(
+    context: Context,
+    attrs: AttributeSet? = null,
+    defStyleAttr: Int = 0
+) : View(context, attrs, defStyleAttr) {
+
+    private var cameraWidth = 0f
+    private var cameraHeight = 0f
+    private var faceRectF: List<RectF>? = null
+
+    private val paint = Paint().apply {
+        color = Color.GREEN
+        style = Paint.Style.STROKE
+        strokeWidth = 5f
+        isAntiAlias = true
+    }
+
+    /**
+     * 设置摄像头预览的分辨率,用于等比缩放映射
+     */
+    fun setCameraPreviewSize(width: Int, height: Int) {
+        cameraWidth = width.toFloat()
+        cameraHeight = height.toFloat()
+        invalidate()
+    }
+
+    /**
+     * 设置人脸检测得到的 Rect 坐标(基于摄像头分辨率)
+     */
+    fun setFaceRect(rects: List<Rect>?) {
+        faceRectF = rects?.map { RectF(it) }
+        invalidate()
+    }
+
+    override fun onDraw(canvas: Canvas) {
+        super.onDraw(canvas)
+        val rects = faceRectF ?: return
+        if (cameraWidth <= 0 || cameraHeight <= 0) return
+
+        // View 尺寸
+        val vw = width.toFloat()
+        val vh = height.toFloat()
+        // 等比缩放系数
+        val scale = minOf(vw / cameraWidth, vh / cameraHeight)
+        // 计算预览内容缩放后大小
+        val scaledW = cameraWidth * scale
+        val scaledH = cameraHeight * scale
+        // 居中偏移
+        val dx = (vw - scaledW) / 2
+        val dy = (vh - scaledH) / 2
+        rects.forEach { rect ->
+            // 映射到 View 坐标系
+            val left = rect.left * scale + dx
+            val top = rect.top * scale + dy
+            val right = rect.right * scale + dx
+            val bottom = rect.bottom * scale + dy
+
+            canvas.drawRect(left, top, right, bottom, paint)
+        }
+    }
+}

+ 1 - 0
ui-base/src/main/res/values/colors.xml

@@ -7,6 +7,7 @@
     <color name="main_color">#00AAFF</color>
     <color name="main_color_dark">#CC055EB3</color>
     <color name="common_transparent">#00000000</color>
+    <color name="common_transparent_half">#33ffffff</color>
     <color name="common_bg_white_10">#1affffff</color>
     <color name="common_bg_white_20">#33ffffff</color>
     <color name="common_bg_white_30">#4DFFFFFF</color>