咱们应用人脸检测sdk进行人脸识别的过程大抵能够分为上面几个步骤:
- 加载model文件并初始化接口
- 获取受权
- 调用人脸检测获取关键点
- 告诉描绘关键点
- 开释接口资源
这里的步骤3和4在接管到camera数据后重复执行。咱们能够把这几个步骤形象成数据流来进行封装。face++检测人脸后一直地生成人脸坐标数据,所以整个检测过程就是人脸坐标数据生产的过程,这里与flow的概念对应上了。
face++须要通过解决camera数据来获取人脸关键点,所以camera又是face++人脸检测api的数据提供者。下图体现了数据流动的过程:
看到这里大家也认为咱们通过flow实现这个过程更正当了吧!上面咱们分步来实现detect flow的创立.
第一步咱们通过flow的builder创立一个flow:
private val imageChannel = Channel<FacePPImage>()flow { while (currentCoroutineContext().isActive) { emit(imageChannel.receive()) } }
这里应用Channel来接管图像数据并发射。在detect flow解决图像数据前咱们还须要一些初始化face++的工作,这些工作在onStart中解决。
flow.onStart { var ret = -1 context.assets.open("megviifacepp_model").use { ios -> modelBuffer = ByteArray(ios.available()) ios.read(modelBuffer) FaceppApi.getInstance().setLogLevel(4) ret = FaceppApi.getInstance().initHandle(modelBuffer) } if (ret != 0) { Log.d("dragon_debug", " onStart open failed!") throw RuntimeException("init") } if (requestTakeLicense && modelBuffer != null) { Log.d("dragon_debug", " onStart takeLicense") ret = takeLicense(context, modelBuffer!!) } if (ret != 0) { Log.d("dragon_debug", " onStart takeLicense failed!") throw RuntimeException("takeLicense") } ret = FaceDetectApi.getInstance().initFaceDetect() DLmkDetectApi.getInstance().initDLmkDetect() if (ret != 0) { if (requestTakeLicense) { Log.d("dragon_debug", " onStart initFaceDetect error") throw RuntimeException("error") } requestTakeLicense = true Log.d("dragon_debug", " onStart initFaceDetect retry exception") throw RuntimeException("initFace") } val config = FaceDetectApi.getInstance().faceppConfig config.face_confidence_filter = 0.6f config.detectionMode = FaceDetectApi.FaceppConfig.DETECTION_MODE_TRACKING FaceDetectApi.getInstance().faceppConfig = config }
face++初始化操作包含加载模型、检测接口受权、人脸检测接口初始化等步骤。
检测接口受权解决有些特地,face++的接口受权只在受权过期的时候执行。所以这里配合flow的retryWhen来解决过期受权。
flow.retryWhen { cause, attempt -> Log.d("dragon_debug", " retryWhen $cause attempt $attempt") if (attempt > 1) { false } else { (cause as? RuntimeException)?.message?.equals("initFace") ?: false } }
首先尝试初始化face++接口,如果初始化失败,这里会抛出异样RuntimeException("init")。retryWhen捕捉这个异样后发动重试解决,当onStart再次执行时,咱们会尝试获取接口权限。
face++接口受权初始化胜利后,咱们能够应用face++的人脸检测接口了。这里应用map将图像数据转换成人脸坐标数据,转换操作由face++人脸检测接口实现。
flow.map { image -> val faces = FaceDetectApi.getInstance().detectFace(image) faces.forEach { face -> FaceDetectApi.getInstance().getLandmark(face, FaceDetectApi.LMK_84, true) } block.invoke(faces) faces }
失去的人脸坐标数据通过block回调告诉画面描绘。
face++接口的开释操作在onCompletion中,
flow.onCompletion { Log.d("dragon_debug", " onCompletion ") FaceppApi.getInstance().ReleaseHandle() DLmkDetectApi.getInstance().releaseDlmDetect() }
残缺的代码:https://github.com/mjlong1231...
原文地址:https://blog.csdn.net/mjlong1...