感谢TensorFlow Mobile和TensorFlow Lite,在Android应用程序中嵌入和使用深层模型变得非常容易。 但是,设计和训练模型仍然需要大量的技能,时间和精力,更不用说计算能力了。 因此,大多数临时开发人员对向其应用程序添加机器学习功能并不热衷。 谷歌希望借助Firebase ML Kit改变这一状况。
Firebase ML Kit是一个库,可让您毫不费力地以最少的代码在Android应用中使用各种高度精确的,经过预训练的深度模型。 它提供的大多数模型都可以在本地和Google Cloud上使用。
当前,这些模型仅限于与计算机视觉相关的任务,例如光学字符识别,条形码扫描和对象检测。
在本教程中,我将向您展示如何将Firebase ML Kit添加到Android Studio项目并使用其一些基本API。
先决条件
在继续之前,请确保您可以访问以下内容:
- 最新版本的Android Studio
- 运行Android API级别21或更高版本的设备或模拟器
- 一个Firebase帐户
- 一个Google Cloud帐户
1.创建一个Firebase项目
要为您的应用启用Firebase服务,您必须为其创建一个Firebase项目。 因此,登录到Firebase控制台 ,然后在欢迎屏幕上,按“ 添加项目”按钮。
在弹出的对话框中,给项目起一个易于记忆的名称,然后按“ 创建项目”按钮。
几秒钟后,您应该看到一条通知,通知您新项目已准备就绪。 按继续按钮继续。
在下一个屏幕中,转到“ 开发”部分,然后单击“ ML Kit”链接以查看ML Kit提供的所有服务。
在本教程中,我们将使用三种服务:文本识别,面部检测和图像标记。 如果只打算使用ML Kit随附的本地模型,则无需采取任何步骤来明确启用它们。 不过,在本教程中,我们将同时使用本地模型和基于云的模型。 因此,请点击下一步Cloud API使用率链接。
现在,您将被带到Google Cloud控制台,在这里您只需按Cloud Vision API部分中显示的Enable按钮即可激活基于云的模型。 但是请注意,只有在您为Google Cloud帐户启用了结算功能后,此方法才有效。
2.配置您的Android Studio项目
在开始使用Firebase ML Kit API之前,必须在Android Studio项目和上一步中创建的Firebase项目之间建立连接。 为此,请转到工具> Firebase来打开Firebase助手面板。
Firebase Assistant当前不支持ML Kit。 但是,通过使用它来添加Firebase Analytics,您仍然可以避免手动建立连接。 因此,展开“ 分析”部分,单击“ 记录分析事件”链接,然后按“ 连接到Firebase”按钮。
在弹出的对话框中,确保选择“ 选择现有Firebase或Google项目”选项,然后选择您创建的Firebase项目。
接下来,点击“ 连接到Firebase”按钮。 此时,助手将自动下载包含API密钥和项目ID的google-services.json文件,并将其添加到app
模块。
成功建立连接后,请确保按“ 向应用程序添加分析”按钮以将各种核心Firebase依赖项添加到app
模块的build.gradle文件中。
接下来,要实际添加ML Kit库,请打开build.gradle文件并键入以下implementation
依赖项:
implementation 'com.google.firebase:firebase-ml-vision:16.0.0'
implementation 'com.google.firebase:firebase-ml-vision-image-label-model:15.0.0'
为了简化从Internet下载图像并将其显示在应用程序中的过程,建议您还为Picasso库添加一个依赖项。
implementation 'com.squareup.picasso:picasso:2.5.2'
另外,添加Anko作为依赖项,以确保您的Kotlin代码既简洁又直观。
implementation 'org.jetbrains.anko:anko-commons:0.10.5'
默认情况下,仅在需要时,Firebase ML Kit的本地模型才会自动下载到用户的设备上。 但是,如果希望在安装应用程序后立即下载它们,则将以下代码添加到AndroidManifest.xml文件中:
<meta-data
android:name="com.google.firebase.ml.vision.DEPENDENCIES"
android:value="text,face,label" />
3.定义布局
在本教程中,我们将创建一个应用程序,允许用户键入图像的URL并对其执行文本识别,面部检测和图像标记操作。 因此,该应用程序的布局必须具有一个EditText
小部件(用户可以在其中键入URL)和三个Button
小部件(可让他们选择要执行的操作)。
(可选)您可以包括ImageView
小部件以显示图像。
如果使用RelativeLayout
小部件放置上述所有小部件,则布局XML文件应如下所示:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Image URL"
android:id="@+id/image_url_field"
android:imeOptions="actionDone"
android:inputType="textUri"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="300dp"
android:id="@+id/image_holder"
android:layout_below="@+id/image_url_field"
android:layout_marginTop="10dp"
android:scaleType="centerInside"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_alignParentBottom="true">
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.33"
android:text="Text"
android:onClick="recognizeText"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.33"
android:text="Faces"
android:onClick="detectFaces"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.33"
android:text="Labels"
android:onClick="generateLabels"/>
</LinearLayout>
</RelativeLayout>
这是布局的更直观表示:
在上面的XML中,您可能已经注意到每个按钮都有一个onClick
属性,该属性指向on-click事件处理程序方法。 这些方法尚不存在,所以现在在您的活动中创建它们。
fun recognizeText(v: View) {
// To do
}
fun detectFaces(v: View) {
// To do
}
fun generateLabels(v: View) {
// To do
}
4.加载图像
当用户在EditText
小部件中键入图像的URL后按下“ 完成”键时,我们的应用程序必须下载该图像并将其显示在ImageView
小部件内。
要检测在用户的虚拟键盘上执行的操作, OnEditorActionListener
对象与EditText
小部件关联。 在侦听器内部,确认执行了IME_ACTION_DONE
操作后,您可以简单地调用Picasso的load()
和into()
方法分别加载和显示图像。
因此,在您的活动的onCreate()
方法内添加以下代码:
image_url_field.setOnEditorActionListener { _, action, _ ->
if (action == EditorInfo.IME_ACTION_DONE) {
Picasso.with(ctx).load(image_url_field.text.toString())
.into(image_holder)
true
}
false
}
5.识别文字
Firebase ML Kit针对其提供的所有各种图像识别操作具有单独的检测器类。 要识别文本,则必须使用FirebaseVisionTextDetector
类,它依赖于一个局部模型,或使用FirebaseVisionCloudTextDetector
类,它依赖于一个基于云计算的模型。 现在,让我们使用前者。 它的速度要快得多,但是只能处理以拉丁字母书写的文本。
ML Kit检测器期望其输入采用FirebaseVisionImage
对象的形式。 要创建这样的对象,您需要做的就是调用FirebaseVisionImage
类的fromBitmap()
实用程序方法,并将位图传递给它。 以下代码必须添加到我们之前创建的FirebaseVisionImage
recognizeText()
事件处理程序中,向您展示如何将布局的ImageView
小部件中显示的ImageView
转换为位图,然后FirebaseVisionImage
创建FirebaseVisionImage
对象:
val textImage = FirebaseVisionImage.fromBitmap(
(image_holder.drawable as BitmapDrawable).bitmap
)
接下来,要获取对FirebaseVisionTextDetector
对象的引用,您必须使用FirebaseVision
实例。
val detector = FirebaseVision.getInstance().visionTextDetector
现在,您可以通过调用detectInImage()
方法并将FirebaseVisionImage
对象传递给它来启动文本识别过程。 因为该方法异步运行,所以它返回Task
对象。 因此,为了能够在结果可用时进行处理,必须将OnCompleteListener
实例附加到该实例上。 这是如何做:
detector.detectInImage(textImage)
.addOnCompleteListener {
// More code here
}
在侦听器内部,您可以访问Block
对象的列表。 通常,每个块都可以认为是图像中检测到的单独段落。 通过查看所有Block
对象的text
属性,可以确定已检测到的所有文本。 以下代码显示了如何执行此操作:
var detectedText = ""
it.result.blocks.forEach {
detectedText += it.text + "\n"
}
您如何使用检测到的文本当然取决于您。 现在,我们只使用警报对话框显示它。 感谢Anko的alert()
函数,这样做只需很少的代码。
runOnUiThread {
alert(detectedText, "Text").show()
}
在上面的代码中, runOnUiThread()
方法确保alert()
函数在应用程序的主线程上运行。
最后,使用完检测器后,必须记住要调用其close()
方法以释放其拥有的所有资源。
detector.close()
如果您现在运行该应用程序,请输入包含大量文本的图像的URL,然后按“ 文本”按钮,您应该能够看到ML Kit的文本识别服务的运行情况。
ML Kit的文本识别本地模型对于大多数印刷文本都相当准确。
6.检测人脸
即使它们不共享任何通用的高级接口,大多数检测器类也具有相同的方法。 这意味着检测图像中的面部与识别文本并没有太大不同。 但是,请注意,ML Kit当前仅提供用于面部检测的本地模型,可以使用FirebaseVisionFaceDetector
类进行访问。 您可以使用FirebaseVision
类获得对其实例的引用。
将以下代码添加到detectFaces()
方法:
val detector = FirebaseVision.getInstance().visionFaceDetector
通过再次调用detectInImage()
方法并向其传递位图,您可以异步启动人脸检测过程。 通过使用附加到它返回的Task
对象的OnCompleteListener
实例,您可以轻松地知道该过程何时完成。
detector.detectInImage(FirebaseVisionImage.fromBitmap(
(image_holder.drawable as BitmapDrawable).bitmap
)).addOnCompleteListener {
// More code here
}
在侦听器内部,您可以访问FirebaseVisionFace
对象的列表,其中包含外接检测到的面部的矩形的坐标。 因此,现在让我们在已处理的原始图像的副本上绘制这些矩形。
要创建原始图像的位图的copy()
,必须使用其copy()
方法,如下所示:
var markedBitmap =
(image_holder.drawable as BitmapDrawable)
.bitmap
.copy(Bitmap.Config.ARGB_8888, true)
接下来,要能够绘制新的位图,必须为其创建Canvas
和Paint
对象。 为矩形使用稍微透明的颜色将是理想的。
val canvas = Canvas(markedBitmap)
val paint = Paint(Paint.ANTI_ALIAS_FLAG)
paint.color = Color.parseColor("#99003399")
// semi-transparent blue
此时,您可以简单地遍历FirebaseVisionFace
对象的列表,并使用它们的boundingBox
属性在检测到的面部上绘制矩形。
it.result.forEach {
canvas.drawRect(it.boundingBox, paint)
}
最后,一旦准备好,别忘了将新的位图传递给ImageView
小部件。
runOnUiThread {
image_holder.setImageBitmap(markedBitmap)
}
如果您现在运行该应用程序,则应该能够对其中有人物的任何图像执行面部检测。
我相信您会对ML Kit的人脸检测操作速度和准确性感到印象深刻。
7.生成标签
要为图像生成标签,您必须使用基于本地模型的FirebaseVisionLabelDetector
类或基于云模型的FirebaseVisionCloudLabelDetector
类。 因为在本教程中我们一直只使用本地模型,所以现在就使用云模型。 要获得对FirebaseVisionCloudLabelDetector
类的实例的引用,您必须再次使用FirebaseVision
类。
将以下代码添加到generateLabels()
方法:
val detector =
FirebaseVision.getInstance().visionCloudLabelDetector
接下来,像往常一样,调用detectInImage()
方法并将OnCompleteListener
实例分配给它的返回值。
detector.detectInImage(FirebaseVisionImage.fromBitmap(
(image_holder.drawable as BitmapDrawable).bitmap
)).addOnCompleteListener {
// More code here
}
这次,您将在侦听器内部访问FirebaseVisionCloudLabel
对象的列表,每个对象都有一个label
属性,其中包含图像的潜在标签。 每个标签还具有与之关联的confidence
属性,用于指定ML Kit如何确定标签。
以下代码显示了如何循环浏览标签列表并生成一个警报对话框,该对话框仅显示置信度得分超过70%的那些标签。
var output = ""
it.result.forEach {
if(it.confidence > 0.7)
output += it.label + "\n"
}
runOnUiThread {
alert(output, "Labels").show()
}
继续并再次运行该应用程序,以查看您的应用程序生成的图像标签。
结论
借助Firebase ML Kit,Google希望使机器学习与更简单的任务(如分析和崩溃报告)一样易于访问并成为主流。 在此入门教程中,您学习了如何在Android应用程序中使用其一些基本API。 您还学习了如何同时使用其提供的云和本地模型。
要了解更多信息,请参阅官方文档 。
翻译自: https://code.tutsplus.com/tutorials/getting-started-with-firebase-ml-kit-for-android--cms-31305