Browse Source

人脸采集切换到虹软

Frankensteinly 7 months ago
parent
commit
2707267bf0

+ 2 - 0
app/src/main/java/com/grkj/iscs/MyApplication.kt

@@ -5,6 +5,7 @@ import android.content.Context
 import androidx.multidex.MultiDex
 import com.grkj.iscs.ble.BleUtil
 import com.grkj.iscs.model.Token
+import com.grkj.iscs.util.ArcSoftUtil
 import com.grkj.iscs.util.CrashUtil
 import com.grkj.iscs.util.Executor
 import com.grkj.iscs.util.FileUtil
@@ -32,6 +33,7 @@ class MyApplication : Application() {
         NetHttpManager.getInstance().initCtx(this)
 
         BusinessManager.initMsgEventBus()
+        ArcSoftUtil.checkActiveStatus(this)
 
         NetApi.logout()
         SPUtils.clearLoginUser(this)

+ 197 - 0
app/src/main/java/com/grkj/iscs/util/ArcSoftUtil.kt

@@ -0,0 +1,197 @@
+package com.grkj.iscs.util
+
+import android.Manifest
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.Point
+import android.hardware.Camera
+import android.util.DisplayMetrics
+import android.view.View
+import android.view.WindowManager
+import com.arcsoft.face.ActiveFileInfo
+import com.arcsoft.face.AgeInfo
+import com.arcsoft.face.ErrorInfo
+import com.arcsoft.face.Face3DAngle
+import com.arcsoft.face.FaceEngine
+import com.arcsoft.face.FaceInfo
+import com.arcsoft.face.GenderInfo
+import com.arcsoft.face.LivenessInfo
+import com.arcsoft.face.enums.DetectFaceOrientPriority
+import com.arcsoft.face.enums.DetectMode
+import com.grkj.iscs.R
+import com.grkj.iscs.model.Constants
+import com.grkj.iscs.util.log.LogUtil
+import com.grkj.iscs.view.activity.test.face.arcsoft.CameraHelper
+import com.grkj.iscs.view.activity.test.face.arcsoft.CameraListener
+import com.grkj.iscs.view.activity.test.face.arcsoft.NV21ToBitmap
+
+object ArcSoftUtil {
+    private var cameraHelper: CameraHelper? = null
+    private var previewSize: Camera.Size? = null
+    private val rgbCameraId = Camera.CameraInfo.CAMERA_FACING_BACK
+    private var faceEngine: FaceEngine? = null
+    private var afCode = -1
+    private val processMask: Int =
+        FaceEngine.ASF_AGE or FaceEngine.ASF_FACE3DANGLE or FaceEngine.ASF_GENDER or FaceEngine.ASF_LIVENESS
+
+    private const val ACTION_REQUEST_PERMISSIONS: Int = 0x001
+    var isActivated = false
+
+    /**
+     * 所需的所有权限信息
+     */
+    private val NEEDED_PERMISSIONS: Array<String?> = arrayOf(
+        Manifest.permission.CAMERA,
+        Manifest.permission.READ_PHONE_STATE
+    )
+
+    fun checkActiveStatus(context: Context) {
+        val activeCode = FaceEngine.activeOnline(context, Constants.APP_ID, Constants.SDK_KEY)
+        when (activeCode) {
+            ErrorInfo.MOK -> {
+                isActivated = true
+                LogUtil.i("initEngine : active success")
+            }
+
+            ErrorInfo.MERR_ASF_ALREADY_ACTIVATED -> {
+                isActivated = true
+                LogUtil.i("initEngine : already activated")
+            }
+
+            else -> {
+                isActivated = false
+                LogUtil.e("initEngine : active failed $activeCode")
+                ToastUtils.tip(R.string.face_active_fail)
+            }
+        }
+        val activeFileInfo = ActiveFileInfo()
+        val res = FaceEngine.getActiveFileInfo(context, activeFileInfo)
+        if (res == ErrorInfo.MOK) {
+            LogUtil.e("initEngine:  getActiveFileInfo: $activeFileInfo")
+        }
+    }
+
+    fun initEngine(context: Context) {
+        faceEngine = FaceEngine()
+        afCode = faceEngine!!.init(
+            context,
+            DetectMode.ASF_DETECT_MODE_VIDEO,
+            DetectFaceOrientPriority.valueOf("ASF_OP_0_ONLY"),
+            16,
+            20,
+            FaceEngine.ASF_FACE_DETECT or FaceEngine.ASF_AGE or FaceEngine.ASF_FACE3DANGLE or FaceEngine.ASF_GENDER or FaceEngine.ASF_LIVENESS
+        )
+        LogUtil.i("initEngine:  init: $afCode")
+        if (afCode != ErrorInfo.MOK) {
+            ToastUtils.tip(R.string.face_active_fail)
+        }
+    }
+
+    fun unInitEngine() {
+        if (afCode == 0) {
+            afCode = faceEngine!!.unInit()
+            LogUtil.i("unInitEngine: $afCode")
+        }
+    }
+
+    fun initCamera(context: Context, windowManager: WindowManager, preview: View, callBack: (Bitmap?) -> Unit) {
+        val metrics = DisplayMetrics()
+        windowManager.defaultDisplay.getMetrics(metrics)
+
+        val cameraListener: CameraListener = object : CameraListener {
+            override fun onCameraOpened(
+                camera: Camera,
+                cameraId: Int,
+                displayOrientation: Int,
+                isMirror: Boolean
+            ) {
+                LogUtil.i("onCameraOpened: $cameraId  $displayOrientation $isMirror")
+                previewSize = camera.parameters.previewSize
+            }
+
+
+            override fun onPreview(nv21: ByteArray?, camera: Camera?) {
+                val faceInfoList: List<FaceInfo> = ArrayList()
+                var code = faceEngine!!.detectFaces(
+                    nv21,
+                    previewSize!!.width,
+                    previewSize!!.height,
+                    FaceEngine.CP_PAF_NV21,
+                    faceInfoList
+                )
+                if (code == ErrorInfo.MOK && faceInfoList.size > 0) {
+                    code = faceEngine!!.process(
+                        nv21,
+                        previewSize!!.width,
+                        previewSize!!.height,
+                        FaceEngine.CP_PAF_NV21,
+                        faceInfoList,
+                        processMask
+                    )
+                    if (code != ErrorInfo.MOK) {
+                        return
+                    }
+                } else {
+                    return
+                }
+
+                val ageInfoList: List<AgeInfo> = ArrayList()
+                val genderInfoList: List<GenderInfo> = ArrayList()
+                val face3DAngleList: List<Face3DAngle> = ArrayList()
+                val faceLivenessInfoList: List<LivenessInfo> = ArrayList()
+                val ageCode = faceEngine!!.getAge(ageInfoList)
+                val genderCode = faceEngine!!.getGender(genderInfoList)
+                val face3DAngleCode = faceEngine!!.getFace3DAngle(face3DAngleList)
+                val livenessCode = faceEngine!!.getLiveness(faceLivenessInfoList)
+
+                // 有其中一个的错误码不为ErrorInfo.MOK,return
+                if ((ageCode or genderCode or face3DAngleCode or livenessCode) != ErrorInfo.MOK) {
+                    return
+                }
+
+                // 自己加的,必须有活体检测
+                if (faceLivenessInfoList.none { it.liveness == LivenessInfo.ALIVE }) {
+                    return
+                }
+                val bitmap = NV21ToBitmap(context).nv21ToBitmap(nv21, previewSize!!.width, previewSize!!.height)
+                LogUtil.i("识别结果 : ${bitmap == null} - $faceInfoList")
+                callBack(bitmap)
+            }
+
+            override fun onCameraClosed() {
+                LogUtil.i("onCameraClosed: ")
+            }
+
+            override fun onCameraError(e: Exception) {
+                LogUtil.i("onCameraError: " + e.message)
+            }
+
+            override fun onCameraConfigurationChanged(cameraID: Int, displayOrientation: Int) {
+                LogUtil.i("onCameraConfigurationChanged: $cameraID  $displayOrientation")
+            }
+        }
+        cameraHelper = CameraHelper.Builder()
+            .previewViewSize(Point(preview.measuredWidth, preview.measuredHeight))
+            .rotation(windowManager.defaultDisplay.rotation)
+            .specificCameraId(rgbCameraId ?: Camera.CameraInfo.CAMERA_FACING_FRONT)
+            .isMirror(false)
+            .previewOn(preview)
+            .cameraListener(cameraListener)
+            .build()
+        cameraHelper!!.init()
+        cameraHelper!!.start()
+    }
+
+    fun start(context: Context, windowManager: WindowManager, preview: View, callBack: (Bitmap?) -> Unit) {
+        initEngine(context)
+        initCamera(context, windowManager, preview, callBack)
+    }
+
+    fun stop() {
+        if (cameraHelper != null) {
+            cameraHelper!!.release()
+            cameraHelper = null
+        }
+        unInitEngine()
+    }
+}

+ 23 - 23
app/src/main/java/com/grkj/iscs/view/dialog/FaceCaptureDialog.kt

@@ -2,9 +2,10 @@ package com.grkj.iscs.view.dialog
 
 import android.graphics.Bitmap
 import android.view.View
+import com.grkj.iscs.R
 import com.grkj.iscs.databinding.DialogFaceCaptureBinding
-import com.grkj.iscs.util.Executor
-import com.grkj.iscs.view.activity.test.face.FaceDetectorHelper
+import com.grkj.iscs.util.ArcSoftUtil
+import com.grkj.iscs.util.ToastUtils
 import com.grkj.iscs.view.base.BaseActivity
 import com.grkj.iscs.view.base.BaseDialog
 
@@ -16,10 +17,6 @@ class FaceCaptureDialog(val ctx: BaseActivity<*>, var callback: (Bitmap?) -> Uni
 
     private var mCapturedBitmap: Bitmap? = null
 
-    private val faceDetectorHelper by lazy {
-        FaceDetectorHelper()
-    }
-
     override val viewBinding: DialogFaceCaptureBinding
         get() = DialogFaceCaptureBinding.inflate(layoutInflater)
 
@@ -27,10 +24,11 @@ class FaceCaptureDialog(val ctx: BaseActivity<*>, var callback: (Bitmap?) -> Uni
         mBinding?.cbRecapture?.setOnClickListener {
             mBinding?.preview?.visibility = View.VISIBLE
             mBinding?.preview?.bringToFront()
-            faceDetectorHelper.startDetector()
 
             mBinding?.cbRecapture?.visibility = View.GONE
             mBinding?.cbConfirm?.visibility = View.GONE
+
+            startFace()
         }
 
         mBinding?.cbCancel?.setOnClickListener {
@@ -50,27 +48,29 @@ class FaceCaptureDialog(val ctx: BaseActivity<*>, var callback: (Bitmap?) -> Uni
         // 启动预览
         mBinding?.preview?.visibility = View.VISIBLE
         mBinding?.preview?.bringToFront()
-        faceDetectorHelper.startPreview(ctx, mBinding?.preview!!) {
-            // 注意切换线程
-            Executor.runOnMain {
-                mCapturedBitmap = it
-                // 关闭识别
-                faceDetectorHelper.stopDetector()
-                // 设置图片
-                mBinding?.image?.setImageBitmap(it)
-                mBinding?.image?.bringToFront()
-                // 隐藏预览页面
-                mBinding?.preview?.visibility = View.INVISIBLE
-                mBinding?.cbRecapture?.visibility = View.VISIBLE
-                mBinding?.cbConfirm?.visibility = View.VISIBLE
-            }
+        if (!ArcSoftUtil.isActivated) {
+            ToastUtils.tip(R.string.face_can_not_process)
+        }
+        startFace()
+    }
+
+    private fun startFace() {
+        ArcSoftUtil.initEngine(context)
+        ArcSoftUtil.initCamera(context, ctx.windowManager, mBinding?.preview!!) { bitmap ->
+            ArcSoftUtil.stop()
+            mBinding?.preview?.visibility = View.INVISIBLE
+            mBinding?.image?.visibility = View.VISIBLE
+            mCapturedBitmap = bitmap
+            mBinding?.image?.setImageBitmap(bitmap)
+
+            mBinding?.cbRecapture?.visibility = View.VISIBLE
+            mBinding?.cbConfirm?.visibility = View.VISIBLE
         }
-        faceDetectorHelper.startDetector()
     }
 
     override fun dismiss() {
         super.dismiss()
         mCapturedBitmap = null
-        faceDetectorHelper.release()
+        ArcSoftUtil.stop()
     }
 }

+ 1 - 2
app/src/main/res/layout/dialog_face_capture.xml

@@ -74,8 +74,7 @@
                 android:layout_marginHorizontal="@dimen/common_spacing_small"
                 android:layout_weight="1"
                 android:background="@drawable/face_capture_tip_bg">
-
-                <androidx.camera.view.PreviewView
+                <TextureView
                     android:id="@+id/preview"
                     android:layout_width="match_parent"
                     android:layout_height="match_parent"

+ 2 - 0
app/src/main/res/values/strings.xml

@@ -265,4 +265,6 @@
     <string name="please_do_colock">请共锁人进行共锁,并在工作完成后解除共锁</string>
     <string name="please_go_unlocking">请上锁员执行去解锁操作</string>
     <string name="please_return_key_after_unlocking">请上锁员完成解锁后,归还钥匙</string>
+    <string name="face_active_fail">人脸识别激活失败</string>
+    <string name="face_can_not_process">人脸引擎激活失败,识别暂不可用</string>
 </resources>