Преглед на файлове

:seedling: 整合人脸SDK

everywindchase преди 10 месеца
родител
ревизия
bc16a790bf

+ 1 - 0
app/src/main/AndroidManifest.xml

@@ -40,6 +40,7 @@
        />
 
 
+
     <application
         android:name=".apps.Application"
         android:allowBackup="false"

+ 4 - 14
app/src/main/java/com/ethan/psbc/apps/Application.kt

@@ -13,20 +13,8 @@ import com.ethan.psbc.commons.loggers.LoggerKoin
 import com.ethan.psbc.commons.loggers.LoggerQmui
 import com.ethan.psbc.constants.ConstantApp
 import com.ethan.psbc.extensions.isUiModeNight
-import com.ethan.psbc.managers.IDownloadManager
-import com.ethan.psbc.managers.IFingerprintManager
-import com.ethan.psbc.managers.ILoggerManager
-import com.ethan.psbc.managers.INetworkManager
-import com.ethan.psbc.managers.IPreferencesManager
-import com.ethan.psbc.managers.IRfidManager
-import com.ethan.psbc.managers.IRuntimeManager
-import com.ethan.psbc.managers.impls.ImplDownloadManager
-import com.ethan.psbc.managers.impls.ImplFingerprintManager
-import com.ethan.psbc.managers.impls.ImplLoggerManager
-import com.ethan.psbc.managers.impls.ImplNetworkManager
-import com.ethan.psbc.managers.impls.ImplPreferencesManager
-import com.ethan.psbc.managers.impls.ImplRfidManager
-import com.ethan.psbc.managers.impls.ImplRuntimeManager
+import com.ethan.psbc.managers.*
+import com.ethan.psbc.managers.impls.*
 import com.ethan.psbc.managers.impls.retrofit.INetworkIp
 import com.ethan.psbc.services.IServiceRefreshToken
 import com.ethan.psbc.services.impls.ImplServiceRefreshToken
@@ -91,6 +79,8 @@ internal class Application : ApplicationLifecycle(), ILifecycleCoroutineScope, R
 
         single<INetworkManager> { ImplNetworkManager() }
         single<INetworkIp> { get<INetworkManager>().apiIp }
+
+        factory {  ImplFaceManager()}
     }
 
     private val mKoinServiceModule = module {

+ 11 - 0
app/src/main/java/com/ethan/psbc/managers/IFaceManager.kt

@@ -0,0 +1,11 @@
+package com.ethan.psbc.managers
+
+interface IFaceManager {
+
+    fun initSdk(): Int
+
+
+    fun release(handle:Int): Int
+
+
+}

+ 118 - 0
app/src/main/java/com/ethan/psbc/managers/impls/ImplFaceManager.kt

@@ -0,0 +1,118 @@
+package com.ethan.psbc.managers.impls
+
+import android.os.Environment
+import android.util.Log
+import cn.face.sdk.FaceDetTrack
+import cn.face.sdk.FaceInterface
+import cn.face.sdk.FaceParam
+import cn.face.sdk.FaceRecog
+import com.ethan.psbc.constants.ConstantApp
+import com.ethan.psbc.managers.IFaceManager
+import org.koin.core.component.KoinComponent
+
+import java.io.File
+
+class ImplFaceManager: IFaceManager, KoinComponent {
+
+
+
+
+    override fun initSdk():Int {
+        var faceHandleRet:Int=-1
+        var faceRegFlag:Boolean=false;
+        var faceDetFlag:Boolean=false;
+        try {
+
+            Log.d("demo", "访问外部文件权限" + Environment.getExternalStorageState())
+
+
+            val dirPath= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absolutePath + File.separator + "gg"
+
+
+
+
+
+
+            Log.d("demo", "初始化人脸识别SDK")
+
+
+
+            try{
+                FaceRecog.getInstance()
+                val faceRegConfigFile: File?
+                faceRegConfigFile = File("$dirPath/CWModels", "CWR_Config_1_1.xml")
+                val res= FaceRecog.cwCreateRecogHandle(faceRegConfigFile.absolutePath, ConstantApp.faceLicense, 0)
+                if (res >= FaceInterface.cw_errcode_t.CW_UNKNOWN_ERR) {
+                    Log.d("demo", "创建人脸识别句柄失败")
+                    Log.d("demo", "人脸识别句柄加载失败:${res}" )
+                } else {
+                    Log.d("demo", "创建人脸识别句柄成功" )
+                    Log.d("demo", "获取人脸识别句柄限制数:${res}")
+                    faceRegFlag=true
+                }
+            }catch (e:Exception){
+                throw e
+            }
+
+            try {
+                FaceDetTrack.getInstance()
+                val faceDetConfigFile: File?
+                faceDetConfigFile = File("$dirPath/CWModels", "_configs_frontend_x86_arm.xml")
+                val res=FaceDetTrack.cwCreateDetHandle(faceDetConfigFile.absolutePath, ConstantApp.faceLicense);
+                if (res >= FaceInterface.cw_errcode_t.CW_UNKNOWN_ERR) {
+                    Log.d("demo", "创建人脸跟踪句柄失败")
+                    Log.d("demo", "人脸跟踪句柄加载失败:${res}" )
+                } else {
+                    Log.d("demo", "创建人脸跟踪句柄成功" )
+                    Log.d("demo", "获取人脸跟踪句柄限制数:${res}")
+                    faceDetFlag=true
+
+                    Log.d("demo", "设置人脸跟踪参数" )
+                    var faceParam=FaceParam()
+                    FaceDetTrack.cwSetFaceParam(res,faceParam,dirPath)
+                }
+            }catch (e:Exception){
+                throw e
+            }
+
+
+            if(faceDetFlag&&faceRegFlag){
+                faceHandleRet=0
+            }
+
+        }catch (e:Exception){
+            Log.d("demo", "人脸SDK加载失败:" + e.message)
+        }
+
+        return  faceHandleRet
+    }
+
+
+
+    override fun release(handle:Int): Int {
+        var ret = 0;
+        if (handle != -1) {
+            try {
+                ret = FaceRecog.cwReleaseRecogHandle(handle);
+                if (ret == FaceInterface.cw_errcode_t.CW_SDKLIT_OK)
+                    ret = -1;
+
+            }catch (e:Exception){
+                Log.d("demo", "人脸识别句柄销毁异常:" + e.message)
+            }
+
+
+            try {
+                ret = FaceDetTrack.cwReleaseDetHandle(handle);
+                if (ret == FaceInterface.cw_errcode_t.CW_SDKLIT_OK)
+                    ret = -1;
+
+            }catch (e:Exception){
+                Log.d("demo", "人脸跟踪句柄销毁异常:" + e.message)
+            }
+
+
+        }
+        return ret;
+    }
+}

+ 50 - 143
app/src/main/java/com/ethan/psbc/ui/dialogs/DialogValidateFace.kt

@@ -3,8 +3,6 @@ package com.ethan.psbc.ui.dialogs
 import android.Manifest
 import android.content.Context
 import android.content.pm.PackageManager
-import android.content.res.AssetManager
-import android.os.Environment
 import android.util.Log
 import android.view.View
 import android.widget.Toast
@@ -15,13 +13,16 @@ import androidx.camera.view.PreviewView
 import androidx.core.app.ActivityCompat
 import androidx.core.content.ContextCompat
 import androidx.lifecycle.LifecycleOwner
+import cn.face.sdk.FaceDetTrack
+import cn.face.sdk.FaceInfo
 import cn.face.sdk.FaceInterface
 import cn.face.sdk.FaceRecog
 import com.ethan.psbc.R
-import com.ethan.psbc.constants.ConstantApp
 import com.ethan.psbc.databinding.DialogValidateFaceBinding
+import com.ethan.psbc.managers.impls.ImplFaceManager
 import com.lxj.xpopup.impl.FullScreenPopupView
-import java.io.*
+import org.koin.core.component.KoinComponent
+import org.koin.core.component.inject
 import java.nio.ByteBuffer
 import java.util.concurrent.ExecutorService
 import java.util.concurrent.Executors
@@ -30,7 +31,7 @@ import java.util.concurrent.Executors
  * <p>人脸验证界面</p>
  * @author gy
  */
-class DialogValidateFace( mContext: Context) : FullScreenPopupView(mContext){
+class DialogValidateFace( mContext: Context) : FullScreenPopupView(mContext), KoinComponent {
 
 
 
@@ -41,151 +42,25 @@ class DialogValidateFace( mContext: Context) : FullScreenPopupView(mContext){
     }
 
 
-    init {
-        initSdk(mContext)
-    }
-
-
-
-    private lateinit    var faceConfigFile:File
-
-    var faceHandleRet:Int=-1
-
-
 
-    fun initSdk(mContext:Context){
 
 
-        try {
-            Log.d("demo", "访问外部文件权限" + Environment.getExternalStorageState())
 
 
-            val dirPath= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
 
+    val mFace:ImplFaceManager by inject()
 
 
-            //createModelFileAll(dirPath, mContext.assets)
-
-            faceConfigFile = File(dirPath, "CWR_Config_1_1.xml")
-
-
-            Log.d("demo", "初始化人脸识别SDK")
-            FaceRecog.getInstance();
-            faceHandleRet = FaceRecog.cwCreateRecogHandle(faceConfigFile.absolutePath, ConstantApp.faceLicense, 0)
-            Log.d("demo", "获取SDK句柄:$faceHandleRet")
-            if (faceHandleRet >= FaceInterface.cw_errcode_t.CW_UNKNOWN_ERR) {
-                faceHandleRet = -1
-            } else {
-                faceHandleRet = 0
-            }
-
-
-        }catch (e:Exception){
-            Log.d("demo", "人脸SDK加载失败:"+e.message)
-            faceHandleRet = -1
-        }
-
-    }
-
-
-
-
-
-
-    fun createModelFileAll(modelDirPath: String, assetManager: AssetManager) {
-        val parentDir = "CWModels"
-        var fileNameList: List<String?>? = null
-        var files: Array<String?>? = null
-
-        var fileAbsPath = ""
-        fileAbsPath = if (modelDirPath.endsWith("/")) {
-            modelDirPath
-        } else {
-            "$modelDirPath/"
-        }
-        mkDir(modelDirPath)
-        try {
-            files = assetManager.list(parentDir)
-            fileNameList =files?.toCollection(ArrayList())
-        } catch (e: IOException) {
-            Log.e("demo", e.message!!)
-        }
-
-        for (fileName in fileNameList!!) {
-            Log.e("demo", fileName!!)
-            val modelFile = File(fileAbsPath + fileName)
-            if (!modelFile.exists()) {
-                copyRawFileToSdcard(parentDir + File.separator + fileName, assetManager, fileAbsPath + fileName)
-            }
-        }
-    }
-
-
-    fun mkDir(dirPath: String) {
-        val dirArray = dirPath.split("/".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
-        var pathTemp = ""
-        for (i in 1 until dirArray.size) {
-            pathTemp = pathTemp + "/" + dirArray[i]
-            val newF = File(dirArray[0] + pathTemp)
-            if (!newF.exists()) {
-                newF.mkdir()
-            }
-        }
-    }
-
-
-    fun copyRawFileToSdcard(rawFileName: String?, assetManager: AssetManager, outPutFileAbs: String?) {
-        var inputStream: InputStream? = null
-        try {
-            inputStream = assetManager.open(rawFileName!!)
-        } catch (e: IOException) {
-            Log.e("tag", e.message!!)
-        }
-
-        if (inputStream != null) inputStreamToFile(inputStream, outPutFileAbs)
-    }
-
-
-    fun inputStreamToFile(inputStream: InputStream, absPath: String?) {
-        val outputStream = ByteArrayOutputStream()
-
-
-        val bufferSize = 1024
-        val buffer = ByteArray(bufferSize)
-        var length: Int
-
-        try {
-            while (inputStream.read(buffer).also { length = it } != -1) {
-                outputStream.write(buffer, 0, length)
-            }
-        } finally {
-            inputStream.close()
-            outputStream.close()
-        }
-
-
-        try {
-            val imgBytes = outputStream.toByteArray()
-            val fos = FileOutputStream(absPath, false)
-            fos.write(imgBytes)
-            fos.close()
-        } catch (e: IOException) {
-            e.printStackTrace()
-        }
-    }
-
-
+    var faceHandleRet:Int=-1
 
     override  fun onCreate() {
         super.onCreate()
         mBinding = DialogValidateFaceBinding.bind(popupContentView)
+        val faceHandleRet:Int=mFace.initSdk()
+        this.faceHandleRet=faceHandleRet
+        runCamera(this, mBinding.mPreviewView, faceHandleRet, context = context)
         mBinding.cameraLayout.visibility= View.VISIBLE
         mBinding.mPreviewView.bringToFront()
-
-
-
-        runCamera(  this  ,mBinding.mPreviewView,faceHandleRet)
-
     }
 
 
@@ -197,7 +72,7 @@ class DialogValidateFace( mContext: Context) : FullScreenPopupView(mContext){
     private lateinit   var imageAnalysis: ImageAnalysis
 
 
-    fun runCamera(lifecycleOwner:LifecycleOwner, previewView: PreviewView?, handle:Int){
+    fun runCamera(lifecycleOwner:LifecycleOwner, previewView: PreviewView?, handle:Int,context: Context){
 
         if( PackageManager.PERMISSION_GRANTED!= ContextCompat.checkSelfPermission(context    , Manifest.permission.CAMERA)){
             ActivityCompat.requestPermissions(context    as AppCompatActivity, arrayOf(Manifest.permission.CAMERA),1)
@@ -246,16 +121,42 @@ class DialogValidateFace( mContext: Context) : FullScreenPopupView(mContext){
                     buffer.get(data)
 
 
-                    if(handle==-1){
-                        Log.d("demo", "SDK无法使用")
-                    }else{
-                        val iFeaLen:Int = FaceRecog.cwGetFeatureLength(handle)
-                        Log.d("demo", "获取到人脸特征长度${iFeaLen}")
-                    }
+                    //第一步调用人脸跟踪API分析图像流特征
 
 
 
+                    if(handle==-1){
+                        Log.d("demo", "SDK无法使用:SDK未初始化加载成功")
+                    }else {
+                        Log.d("demo", "SDK可以使用")
+                        try{
+                            val iFeaLen =FaceRecog.cwGetFeatureLength(handle)
+                             Log.d("demo", "获取到人脸特征长度:${iFeaLen}")
+
+                            var pFaceBuffer=Array(3){_ ->FaceInfo()}
+                            val faceDetRet:Int= FaceDetTrack.cwFaceDetection(handle,data,0, 0, FaceInterface.cw_img_form_t.CW_IMAGE_BINARY, 0, 0, FaceInterface.cw_op_t.CW_OP_ALIGN , pFaceBuffer)
+                            if (faceDetRet >= FaceInterface.cw_errcode_t.CW_UNKNOWN_ERR) {
+                                Log.d("demo", "检测到人脸异常:${faceDetRet}" )
+                            }else  if(faceDetRet<1){
+                                Log.d("demo", "未检测到人脸:${faceDetRet}" )
+                            }else{
+                                Log.d("demo", "检测到人脸" )
+                                val btFeature=ByteArray(iFeaLen)
+                                FaceRecog.cwGetFaceFeature(handle,pFaceBuffer[0].alignedData,pFaceBuffer[0].alignedW,
+                                    pFaceBuffer[0].alignedH,pFaceBuffer[0].nChannels, btFeature)
+
+                                var scores=FloatArray(1)
+                                FaceRecog.cwComputeMatchScore(handle,btFeature,btFeature,1,scores)
+                                Log.d("demo", "检测到相似度为:${scores[0]}" )
+
+
+                            }
+
+                        }catch (e:Exception){
+                                Log.d("demo", "人脸识别异常:${e.message}")
+                        }
 
+                    }
 
 
 
@@ -287,6 +188,12 @@ class DialogValidateFace( mContext: Context) : FullScreenPopupView(mContext){
     }
 
 
+    override fun onDismiss() {
+        mFace.release(this.faceHandleRet)
+        super.onDismiss()
+    }
+
+