探索MediaPipe检测人脸关键点

您所在的位置:网站首页 微信截图怎么修改日期 探索MediaPipe检测人脸关键点

探索MediaPipe检测人脸关键点

2023-09-18 15:33| 来源: 网络整理| 查看: 265

MediaPipe是Google开源的计算机视觉处理框架,基于TensorFlow来训练模型,支持人脸识别、人脸关键点、目标检测追踪、图像分类、人像分割、手势识别、文本分类、语音分类等。我们可以使用CPU来推理,也可以选择GPU加速推理。在滤镜特效场景,经常需要用到人脸关键点。

 

目录

一、配置参数与模型

1、配置参数

2、检测模型 

二、工程配置

三、初始化工作

1、初始化模型

2、初始化Camera

四、检测实时流

1、检测人脸关键点

2、绘制人脸关键点

五、检测结果​​​​​​​

一、配置参数与模型 1、配置参数

检测人脸关键点的配置参数有运行模式、人脸数、最小的检测人脸置信度、最小的显示人脸置信度、最小的追踪人脸置信度、结果回调,具体如下表所示:

选项描述取值范围默认值running_mode

IMAGE: 单个图像 

VIDEO: 视频帧

LIVE_STREAM: 实时流

{IMAGE,VIDEO,

LIVE_STREAM}

IMAGEnum_faces最多检测的人脸数大于01

min_face_detection

_confidence

人脸检测最小置信度[0.0, 1.0]0.5

min_face_presence

_confidence

人脸显示最小置信度[0.0, 1.0]0.5min_tracking_confidence人脸追踪最小置信度[0.0, 1.0]0.5output_face_blendshapes是否输出混合形状(用于3D人脸模型)Booleanfalse

output_facial_transformation

_matrixes

是否输出变换矩阵(用于滤镜特效)Booleanfalseresult_callback异步回调结果(LIVE_STREAM模式)ResultListener   / 2、检测模型 

检测人脸关键点分为三步:首先检测人脸,然后定位关键点,最后识别面部特征。使用到的模型如下:

人脸检测模型:根据人脸关键点特征来检测人脸;人脸网格模型:包含478个坐标点的3D人脸标识;混合形状模型:预测52个混合形状的分数,表示不同表情的系数;  二、工程配置

以Android平台为例,在gradle导入MediaPipe相关包:

implementation 'com.google.mediapipe:tasks-vision:0.10.0'

然后运行下载模型的task,并且指定模型保存路径:

project.ext.ASSET_DIR = projectDir.toString() + '/src/main/assets' apply from: 'download_tasks.gradle'

这里用到的模型是face_landmarker,设置src和dest:

task downloadTaskFile(type: Download) { src 'https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task' dest project.ext.ASSET_DIR + '/face_landmarker.task' overwrite false } preBuild.dependsOn downloadTaskFile 三、初始化工作 1、初始化模型

模型的初始化包括:设置运行模式、模型路径、检测人脸数、回调结果等,示例代码如下:

fun setupFaceLandmark() { val baseOptionBuilder = BaseOptions.builder() // 设置运行模式,默认CPU when (currentDelegate) { DELEGATE_CPU -> { baseOptionBuilder.setDelegate(Delegate.CPU) } DELEGATE_GPU -> { baseOptionBuilder.setDelegate(Delegate.GPU) } } // 设置模型路径 baseOptionBuilder.setModelAssetPath(MP_FACE_LANDMARKER_TASK) try { val baseOptions = baseOptionBuilder.build() // 设置检测的人脸数、最小的检测人脸置信度 val optionsBuilder = FaceLandmarker.FaceLandmarkerOptions.builder() .setBaseOptions(baseOptions) .setMinFaceDetectionConfidence(minFaceDetectionConfidence) .setMinTrackingConfidence(minFaceTrackingConfidence) .setMinFacePresenceConfidence(minFacePresenceConfidence) .setNumFaces(maxNumFaces) .setRunningMode(runningMode) // LIVE_STREAM模式:设置回调结果 if (runningMode == RunningMode.LIVE_STREAM) { optionsBuilder .setResultListener(this::returnLivestreamResult) .setErrorListener(this::returnLivestreamError) } val options = optionsBuilder.build() faceLandmarker = FaceLandmarker.createFromOptions(context, options) } catch (e: IllegalStateException) { faceLandmarkerHelperListener?.onError( "Face Landmark failed to initialize, error: " + e.message) } catch (e: RuntimeException) { faceLandmarkerHelperListener?.onError( "Face Landmark failed to initialize. See error logs for details", GPU_ERROR) } } 2、初始化Camera

这里以LIVE_STREAM模式为例,Camera的初始化包括:设置像素格式、预览宽高比、绑定生命周期、关联SurfaceProvider。示例代码如下:

private fun bindCameraUseCases() { val cameraProvider = cameraProvider ?: throw IllegalStateException("Camera init failed.") val cameraSelector = CameraSelector.Builder().requireLensFacing(cameraFacing).build() // 预览的宽高比为4:3 preview = Preview.Builder().setTargetAspectRatio(AspectRatio.RATIO_4_3) .setTargetRotation(fragmentCameraBinding.viewFinder.display.rotation) .build() // 设置像素格式为RGBA_8888,预览的旋转角度 imageAnalyzer = ImageAnalysis.Builder().setTargetAspectRatio(AspectRatio.RATIO_4_3) .setTargetRotation(fragmentCameraBinding.viewFinder.display.rotation) .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) .setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888) .build() .also { it.setAnalyzer(backgroundExecutor) { image -> // 执行检测人脸关键点 faceLandmarkerHelper.detectLiveStream(image, cameraFacing == CameraSelector.LENS_FACING_FRONT) } } // 绑定之前,先解除绑定 cameraProvider.unbindAll() try { // 绑定Lifecycle camera = cameraProvider.bindToLifecycle( this, cameraSelector, preview, imageAnalyzer) // 关联SurfaceProvider preview?.setSurfaceProvider(fragmentCameraBinding.viewFinder.surfaceProvider) } catch (exc: Exception) { Log.e(TAG, "bind lifecycle failed", exc) } } 四、检测实时流 1、检测人脸关键点

在检测之前,先拷贝数据,图像帧预处理,然后执行检测:

fun detectLiveStream( imageProxy: ImageProxy, isFrontCamera: Boolean) { val frameTime = SystemClock.uptimeMillis() // 拷贝RGB数据到缓冲区 val bitmapBuffer = Bitmap.createBitmap( imageProxy.width, imageProxy.height, Bitmap.Config.ARGB_8888 ) imageProxy.use { bitmapBuffer.copyPixelsFromBuffer(imageProxy.planes[0].buffer) } imageProxy.close() val matrix = Matrix().apply { // 图像旋转 postRotate(imageProxy.imageInfo.rotationDegrees.toFloat()) // 如果是前置摄像头,需要左右镜像 if (isFrontCamera) { postScale(-1f, 1f, imageProxy.width.toFloat(), imageProxy.height.toFloat()) } } val rotatedBitmap = Bitmap.createBitmap( bitmapBuffer, 0, 0, bitmapBuffer.width, bitmapBuffer.height, matrix, true) // 转换Bitmap为MPImage val mpImage = BitmapImageBuilder(rotatedBitmap).build() // 异步检测人脸关键点 faceLandmarker?.detectAsync(mpImage, frameTime) } 2、绘制人脸关键点

检测到人脸关键点结果后,然后回调到主线程:

override fun onResults(resultBundle: FaceLandmarkerHelper.ResultBundle) { activity?.runOnUiThread { if (_fragmentCameraBinding != null) { // 显示推理时长 fragmentCameraBinding.bottomSheetLayout.inferenceTimeVal.text = String.format("%d ms", resultBundle.inferenceTime) // 传递结果给OverlayView fragmentCameraBinding.overlay.setResults( resultBundle.result, resultBundle.inputImageHeight, resultBundle.inputImageWidth, RunningMode.LIVE_STREAM ) // 主动触发渲染 fragmentCameraBinding.overlay.invalidate() } } }

最后绘制人脸关键点,包括面部表情、轮廓:

override fun draw(canvas: Canvas) { super.draw(canvas) if(results == null || results!!.faceLandmarks().isEmpty()) { clear() return } results?.let { faceLandmarkResult -> // 绘制关键点 for(landmark in faceLandmarkResult.faceLandmarks()) { for(normalizedLandmark in landmark) { canvas.drawPoint(normalizedLandmark.x() * imageWidth * scaleFactor, normalizedLandmark.y() * imageHeight * scaleFactor, pointPaint) } } // 绘制线条 FaceLandmarker.FACE_LANDMARKS_CONNECTORS.forEach { canvas.drawLine( faceLandmarkResult.faceLandmarks()[0][it!!.start()].x() * imageWidth * scaleFactor, faceLandmarkResult.faceLandmarks()[0][it.start()].y() * imageHeight * scaleFactor, faceLandmarkResult.faceLandmarks()[0][it.end()].x() * imageWidth * scaleFactor, faceLandmarkResult.faceLandmarks()[0][it.end()].y() * imageHeight * scaleFactor, linePaint) } } } 五、检测结果

输入数据可以是静态图像、实时视频流、文件视频帧。输出数据有人脸边界框、人脸网格、关键点坐标。其中,人脸关键点包括:脸部轮廓、嘴巴、鼻子、眼睛、眉毛、脸颊等,属于3D的landmark模型。如下图所示:

 在人脸识别、人脸关键点基础上,还支持换脸,变成可爱的卡通效果。眨眼睛、摇头、张嘴这些表情动作,都会有实时的卡通头像变化。如下图所示:



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3