Firebase ML Kit是用于在移动应用程序中添加机器学习功能的本地和基于云的API的集合,最近已得到增强,以支持面部轮廓检测。 得益于此强大的功能,您在检测面部时不再需要将自己限制为近似矩形。 相反,您可以使用大量的坐标来准确描述检测到的脸部和脸部界标(例如眼睛,嘴唇和眉毛)的形状。
这使您可以轻松创建基于AI的应用程序,这些应用程序可以完成与计算机视觉相关的复杂任务,例如换脸,识别情绪或进行数字化妆。
在本教程中,我将向您展示如何使用ML Kit的面部轮廓检测功能来创建可突出显示照片中面部的Android应用。
先决条件
要充分利用本教程,您必须具有以下权限:
- 最新版本的Android Studio
- 运行Android API级别23或更高版本的设备
1.配置项目
由于ML Kit是Firebase平台的一部分,因此您需要一个Firebase项目才能在Android Studio项目中使用它。 要创建一个,请通过转到工具> Firebase启动Firebase助手。
接下来,打开“ 分析”部分,然后按“ 连接”按钮。 在弹出的对话框中,输入新Firebase项目的名称,选择您所在的国家/地区,然后按“ 连接”按钮。
成功建立连接后,请按向应用程序添加分析按钮,以便助手可以在Android Studio项目中进行所有与Firebase相关的必要配置更改。
此时,如果打开app
模块的build.gradle文件以及其他更改,则应该在其中看到以下implementation
依赖项:
implementation 'com.google.firebase:firebase-core:16.0.4'
为了能够使用ML Kit的面部轮廓检测功能,您还需要两个依赖关系:一个依赖于ML Vision库的最新版本,另一个依赖于ML Vision人脸模型。 您可以通过以下方式添加它们:
implementation 'com.google.firebase:firebase-ml-vision:18.0.1'
implementation 'com.google.firebase:firebase-ml-vision-face-model:17.0.2'
在本教程中,您将使用远程图像。 为了方便下载和显示此类图像,请为Picasso库添加一个依赖项:
implementation 'com.squareup.picasso:picasso:2.71828'
ML Kit的面部轮廓检测始终在您的用户设备上本地运行。 默认情况下,用户首次打开您的应用时,会自动下载执行面部轮廓检测的机器学习模型。 但是,为了改善用户体验,建议您在用户安装您的应用后立即开始下载。 为此,请将以下<meta-data>
标记添加到AndroidManifest.xml文件:
<meta-data
android:name="com.google.firebase.ml.vision.DEPENDENCIES"
android:value="face" />
2.创建布局
您将需要在应用程序布局中使用三个小部件:一个EditText
小部件(用户可以在其中键入在线照片的URL),一个ImageView
小部件(用于显示照片)和一个Button
小部件)部件来启动面部轮廓检测过程。 此外,您将需要一个RelativeLayout
小部件来放置这三个小部件。 因此,将以下代码添加到您的主要活动的布局XML文件中:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<EditText android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Image URL"
android:imeOptions="actionGo"
android:inputType="textUri"
android:id="@+id/user_input" />
<Button android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Detect contours"
android:layout_alignParentBottom="true"
android:id="@+id/action_button" />
<ImageView android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/photo"
android:layout_below="@+id/user_input"
android:layout_above="@id/action_button"
android:scaleType="centerCrop"/>
</RelativeLayout>
3.下载和显示图像
使用Picasso库,下载和显示远程图像只需调用两种方法即可。 首先,调用load()
方法以指定要下载的图像的URL,然后调用into()
方法以指定要在其中显示下载图像的ImageView
小部件。
当然,您必须仅在用户完成URL键入后才调用这两种方法。 因此,请确保在附加到上一步中创建的EditText
小部件的OnEditorActionListener
对象中调用它们。 以下代码显示了如何执行此操作:
user_input.setOnEditorActionListener { _, action, _ ->
if(action == EditorInfo.IME_ACTION_GO) {
Picasso.get()
.load(user_input.text.toString())
.into(photo)
true
}
false
}
立即运行该应用,然后尝试输入有效的图片网址以确保其正常运行。
4.创建面部轮廓检测器
您将在附加到布局的“ Button
小部件的单击事件处理程序中运行所有面部轮廓检测操作。 因此,在继续之前,请将以下代码添加到您的活动中:
action_button.setOnClickListener {
// Rest of the code goes here
}
为了能够使用面部数据,您现在必须创建一个FirebaseVisionFaceDetector
对象。 但是,由于默认情况下它不检测脸部轮廓,因此您还必须创建一个FirebaseVisionFaceDetectorOptions
对象,可以对其进行配置。
要创建有效的选项对象,必须遵循构建器模式。 因此,创建FirebaseVisionFaceDetectorOptions.Builder
类的实例,调用其setContourMode()
方法,并将ALL_CONTOURS
常量传递给它,以指定您要检测图像中存在的所有面部的轮廓。
然后,调用build()
器的build()
方法来生成options对象。
val detectorOptions =
FirebaseVisionFaceDetectorOptions.Builder()
.setContourMode(
FirebaseVisionFaceDetectorOptions.ALL_CONTOURS
).build()
现在,您可以将options对象传递给ML Kit的FirebaseVision
类的getVisionFaceDetector()
方法,以创建您的面部轮廓检测器。
val detector = FirebaseVision
.getInstance()
.getVisionFaceDetector(detectorOptions)
5.收集坐标数据
面部轮廓检测器无法直接使用ImageView
小部件显示的照片。 相反,它希望您将FirebaseVisionImage
对象传递给它。 要生成这样的对象,必须将照片转换为Bitmap
对象。 以下代码显示了如何执行此操作:
val visionImage = FirebaseVisionImage.fromBitmap(
(photo.drawable as BitmapDrawable).bitmap
)
现在,您可以调用检测器的detectInImage()
方法来检测照片中存在的所有面部的轮廓。 该方法异步运行,如果成功完成,则返回FirebaseVisionFace
对象的列表。
detector.detectInImage(visionImage).addOnSuccessListener {
// More code here
}
在成功侦听器内部,您可以使用it
隐式变量遍历检测到的面部列表。 每个面都有大量与之关联的轮廓点。 要访问这些点,必须调用getContour()
方法。 该方法可以返回几个不同的面部标志的轮廓点。 例如,如果将常量LEFT_EYE
传递给它,它将返回您需要勾勒出左眼轮廓的点。 同样,如果将UPPER_LIP_TOP
传递给它, UPPER_LIP_TOP
获得与上唇的上边缘关联的点。
在本教程中,我们将使用FACE
常量,因为我们要突出显示面部本身。 以下代码显示如何打印沿每个面的边缘存在的所有点的X和Y坐标:
it.forEach {
val contour = it.getContour(FirebaseVisionFaceContour.FACE)
contour.points.forEach {
println("Point at ${it.x}, ${it.y}")
}
// More code here
}
如果您现在尝试使用该应用程序并指定其中至少包含一张脸的图像,则应该在Logcat窗口中看到类似以下内容 :
6.在脸部周围绘制路径
要突出显示检测到的脸部,我们只需使用轮廓点在其周围绘制路径即可。 为了绘制这样的路径,您需要ImageView
小部件的位图的可变副本。 通过调用其copy()
方法创建一个。
val mutableBitmap =
(photo.drawable as BitmapDrawable).bitmap.copy(
Bitmap.Config.ARGB_8888, true
)
通过直接修改位图的像素来绘制路径可能很困难。 因此,通过将其传递给Canvas
类的构造函数为其创建一个新的2D画布。
此外,创建一个Paint
对象以指定要在画布上绘制的像素的颜色。 以下代码显示了如何创建一个画布,可以在其上绘制半透明的红色像素:
val canvas = Canvas(mutableBitmap)
val myPaint = Paint(Paint.ANTI_ALIAS_FLAG)
myPaint.color = Color.parseColor("#99ff0000")
在画布上绘制路径的最简单方法是使用Path
类。 通过使用该类的直观命名的moveTo()
和lineTo()
方法,您可以轻松地在画布上绘制复杂的形状。
现在,要绘制面的形状,请一次调用moveTo()
方法,并将第一个轮廓点的坐标传递给该方法。 这样,您可以指定路径的开始位置。 然后将所有点的坐标传递给lineTo()
方法以实际绘制路径。 最后,调用close()
方法以关闭路径并填充它。
相应地,添加以下代码:
val path = Path()
path.moveTo(contour.points[0].x, contour.points[0].y)
contour.points.forEach {
path.lineTo(it.x, it.y)
}
path.close()
要渲染路径,请将其与Paint
对象一起传递给画布的drawPath()
方法。
canvas.drawPath(path, myPaint)
并更新ImageView
小部件以显示修改后的位图,请将位图传递给其setImageBitmap()
方法。
photo.setImageBitmap(mutableBitmap)
如果立即运行该应用程序,应该可以看到它在其检测到的所有面部上绘制了半透明的红色蒙版。
结论
借助ML Kit的新面部轮廓检测API和一点点创意,您可以轻松创建基于AI的应用程序,这些应用程序可以完成与计算机视觉相关的复杂任务,例如换脸,检测情绪或进行数字化妆。 在本教程中,您学习了如何使用API生成的2D坐标绘制形状以突出显示照片中存在的面Kong。
面部轮廓检测API最多可以处理一张照片中的五个面部。 为了获得最大的速度和准确性,我建议您仅将其用于具有一张或两张脸的照片。
要了解有关API的更多信息,请参阅官方文档 。
翻译自: https://code.tutsplus.com/tutorials/detecting-face-contours-with-firebase-ml-kit--cms-32264