Статьи

Начало работы с Firebase ML Kit для Android

Благодаря TensorFlow Mobile и TensorFlow Lite встраивание и использование глубоких моделей в приложениях Android стало очень простым. Тем не менее, разработка и обучение моделей все еще требует больших навыков, времени и усилий, не говоря уже о вычислительной мощности. По этой причине большинство случайных разработчиков не испытывают энтузиазма по поводу добавления возможностей машинного обучения в свои приложения. С помощью Firebase ML Kit Google надеется изменить это.

Firebase ML Kit — это библиотека, которая позволяет вам без особых усилий и с минимальным объемом кода использовать множество высокоточных, предварительно обученных глубоких моделей в ваших приложениях для Android. Большинство предлагаемых моделей доступны как локально, так и в облаке Google.

В настоящее время модели ограничиваются только задачами, связанными с компьютерным зрением, такими как оптическое распознавание символов, сканирование штрих-кода и обнаружение объектов.

В этом уроке я покажу вам, как добавить Firebase ML Kit в проект Android Studio и использовать некоторые из его базовых API.

Прежде чем продолжить, убедитесь, что у вас есть доступ к следующему:

Чтобы включить службы Firebase для вашего приложения, вы должны создать для него проект Firebase. Войдите в консоль Firebase и на экране приветствия нажмите кнопку « Добавить проект» .

Экран приветствия консоли Firebase

В появившемся диалоговом окне присвойте проекту имя, которое легко запомнить, и нажмите кнопку « Создать проект» .

Форма конфигурации проекта

Через несколько секунд вы увидите уведомление о том, что новый проект готов. Нажмите кнопку Продолжить , чтобы продолжить.

На следующем экране перейдите в раздел « Разработка » и нажмите на ссылку ML Kit, чтобы увидеть все услуги, предлагаемые ML Kit.

Услуги ML Kit предлагает

В этом уроке мы будем использовать три сервиса: распознавание текста, распознавание лиц и маркировку изображений. Вам не нужно предпринимать никаких шагов, чтобы явно включить их, если вы собираетесь работать только с локальными моделями, которые поставляются с ML Kit. В этом уроке мы будем использовать как локальные, так и облачные модели. Так что нажмите на ссылку использования Cloud API дальше.

Теперь вы попадете в консоль Google Cloud, где вы можете просто нажать кнопку « Включить» , показанную в разделе API Cloud Vision, чтобы активировать облачные модели. Однако обратите внимание, что это будет работать только в том случае, если для вашей учетной записи Google Cloud включен биллинг.

Экран активации API Cloud Vision

Прежде чем начать использовать API-интерфейсы Firebase ML Kit, необходимо установить соединение между проектом Android Studio и проектом Firebase, созданным на предыдущем шаге. Для этого откройте панель «Помощник Firebase», выбрав « Инструменты»> «Firebase» .

Firebase Assistant в настоящее время не поддерживает ML Kit. Тем не менее, используя его для добавления Firebase Analytics, вы все равно можете избежать установки соединения вручную. Поэтому разверните раздел « Аналитика », щелкните ссылку « Журнал событий аналитики» и нажмите кнопку « Подключиться к Firebase» .

В появившемся диалоговом окне убедитесь, что вы выбрали вариант « Выбрать существующий проект Firebase или Google» и выберите созданный вами проект Firebase.

Диалог подключения к Firebase

Нажмите кнопку « Подключиться к Firebase» далее. На этом этапе Помощник автоматически загрузит файл google-services.json , содержащий ключи API и идентификаторы проекта, и добавит его в модуль app .

После успешного установления соединения обязательно нажмите кнопку « Добавить аналитику в приложение» , чтобы добавить различные основные зависимости Firebase в файл build.gradle модуля app .

Затем, чтобы фактически добавить библиотеку ML Kit, откройте файл build.gradle и введите следующие зависимости implementation :

1
2
implementation ‘com.google.firebase:firebase-ml-vision:16.0.0’
implementation ‘com.google.firebase:firebase-ml-vision-image-label-model:15.0.0’

Чтобы упростить процесс загрузки изображений из Интернета и отображения их в вашем приложении, я предлагаю вам также добавить зависимость для библиотеки Picasso .

1
implementation ‘com.squareup.picasso:picasso:2.5.2’

Кроме того, добавьте Anko в качестве зависимости, чтобы ваш код Kotlin был кратким и интуитивно понятным.

1
implementation ‘org.jetbrains.anko:anko-commons:0.10.5’

По умолчанию локальные модели Firebase ML Kit автоматически загружаются на устройства ваших пользователей только при необходимости. Если вы хотите, чтобы они загружались сразу после установки приложения, добавьте следующий код в файл AndroidManifest.xml :

1
2
3
<meta-data
   android:name=»com.google.firebase.ml.vision.DEPENDENCIES»
   android:value=»text,face,label» />

В этом руководстве мы создадим приложение, которое позволит пользователям вводить URL-адреса изображений и выполнять на них операции распознавания текста, распознавания лиц и маркировки изображений. Следовательно, макет приложения должен иметь виджет EditText , где пользователи могут вводить URL-адреса, и три виджета Button , которые позволяют им выбирать, какую операцию они хотят выполнить.

При желании вы можете включить виджет ImageView для отображения изображений.

Если вы разместите все вышеупомянутые виджеты с помощью виджета RelativeLayout , ваш XML-файл макета должен выглядеть следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?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

В приведенном выше XML-коде вы, возможно, заметили, что каждая кнопка имеет атрибут onClick указывающий на метод-обработчик события щелчка. Эти методы еще не существуют, поэтому создайте их прямо сейчас.

01
02
03
04
05
06
07
08
09
10
11
fun recognizeText(v: View) {
    // To do
}
 
fun detectFaces(v: View) {
    // To do
}
 
fun generateLabels(v: View) {
    // To do
}

Когда пользователь нажимает клавишу Готово после ввода URL-адреса изображения в виджет EditText , наше приложение должно загрузить изображение и отобразить его внутри виджета ImageView .

Чтобы обнаружить действия, выполняемые на виртуальной клавиатуре пользователя, OnEditorActionListener объект OnEditorActionListener с виджетом EditText . Внутри слушателя, после подтверждения IME_ACTION_DONE действия IME_ACTION_DONE , вы можете просто вызвать методы Picasso load() и into() для загрузки и отображения изображения соответственно.

Соответственно, добавьте следующий код в метод onCreate() вашей деятельности:

1
2
3
4
5
6
7
8
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
}

Firebase ML Kit имеет отдельные классы детекторов для всех различных операций распознавания изображений, которые он предлагает. Чтобы распознать текст, вы должны либо использовать класс FirebaseVisionTextDetector , который зависит от локальной модели, либо использовать класс FirebaseVisionCloudTextDetector , который зависит от облачной модели. А пока давайте воспользуемся первым. Это намного быстрее, но он может обрабатывать текст, написанный только на латинице.

Детектор ML Kit ожидает, что его вход будет в форме объекта FirebaseVisionImage . Чтобы создать такой объект, все, что вам нужно сделать, это вызвать метод утилиты fromBitmap() класса FirebaseVisionImage и передать ему растровое изображение. Следующий код, который должен быть добавлен в обработчик события recognizeText() который мы создали ранее, показывает, как преобразовать изображение, отображаемое в виджете ImageView макета, в растровое изображение, а затем создать из него объект FirebaseVisionImage :

1
2
3
val textImage = FirebaseVisionImage.fromBitmap(
        (image_holder.drawable as BitmapDrawable).bitmap
)

Затем, чтобы получить ссылку на объект FirebaseVisionTextDetector , вы должны использовать экземпляр FirebaseVision .

1
val detector = FirebaseVision.getInstance().visionTextDetector

Теперь вы можете запустить процесс распознавания текста, вызвав метод detectInImage() и передав ему объект FirebaseVisionImage . Поскольку метод выполняется асинхронно, он возвращает объект Task . Следовательно, чтобы иметь возможность обрабатывать результат, когда он доступен, вы должны прикрепить к OnCompleteListener экземпляр OnCompleteListener . Вот как:

1
2
3
4
detector.detectInImage(textImage)
       .addOnCompleteListener {
           // More code here
       }

Внутри слушателя у вас будет доступ к списку объектов Block . В общем, каждый блок можно рассматривать как отдельный абзац, обнаруженный на изображении. Взглянув на свойства text всех объектов Block , вы можете определить весь текст, который был обнаружен. Следующий код показывает вам, как это сделать:

1
2
3
4
var detectedText = «»
it.result.blocks.forEach {
    detectedText += it.text + «\n»
}

Как вы используете обнаруженный текст, конечно, зависит от вас. А пока давайте просто отобразим его с помощью диалогового окна с предупреждением. Благодаря функции Anko alert() этого требуется совсем немного кода.

1
2
3
runOnUiThread {
    alert(detectedText, «Text»).show()
}

В приведенном выше коде метод runOnUiThread() обеспечивает запуск функции alert() в главном потоке приложения.

Наконец, как только вы закончили использовать детектор, вы должны не забыть вызвать его метод close() для освобождения всех ресурсов, которые он содержит.

1
detector.close()

Если вы запустите приложение сейчас, введите URL-адрес изображения, содержащего много текста, и нажмите кнопку « Текст» , вы сможете увидеть службу распознавания текста ML Kit в действии.

Приложение, выполняющее распознавание текста

Локальная модель распознавания текста ML Kit достаточно точна для большинства видов печатного текста.

Несмотря на то, что они не имеют общего высокоуровневого интерфейса, большинство классов детекторов имеют идентичные методы. Это означает, что обнаружение лиц на изображении не слишком отличается от распознавания текста. Однако обратите внимание, что в настоящее время ML Kit предлагает только локальную модель для обнаружения лиц, доступ к которой можно получить с помощью класса FirebaseVisionFaceDetector . Вы можете получить ссылку на его экземпляр, используя класс FirebaseVision .

Добавьте следующий код в метод detectFaces() :

1
val detector = FirebaseVision.getInstance().visionFaceDetector

detectInImage() вызвав метод detectInImage() и передав ему растровое изображение, вы можете запустить процесс обнаружения лица асинхронно. Используя экземпляр OnCompleteListener присоединенный к объекту Task он возвращает, вы можете легко узнать, когда процесс завершится.

1
2
3
4
5
detector.detectInImage(FirebaseVisionImage.fromBitmap(
           (image_holder.drawable as BitmapDrawable).bitmap
       )).addOnCompleteListener {
           // More code here
       }

Внутри слушателя вы получите доступ к списку объектов FirebaseVisionFace , которые содержат координаты прямоугольников, которые окружают обнаруженные лица. Итак, давайте теперь нарисуем эти прямоугольники поверх копии исходного изображения, которое было обработано.

Чтобы создать копию растрового изображения исходного изображения, вы должны использовать его метод copy() как показано ниже:

1
2
3
4
var markedBitmap =
   (image_holder.drawable as BitmapDrawable)
           .bitmap
           .copy(Bitmap.Config.ARGB_8888, true)

Далее, чтобы иметь возможность рисовать на новом растровом изображении, вы должны создать для него объекты Canvas и Paint . Использование слегка прозрачного цвета для прямоугольников было бы идеально.

1
2
3
4
val canvas = Canvas(markedBitmap)
val paint = Paint(Paint.ANTI_ALIAS_FLAG)
paint.color = Color.parseColor(«#99003399»)
                            // semi-transparent blue

На этом этапе вы можете просто просмотреть список объектов FirebaseVisionFace и использовать их свойства boundingBox для рисования прямоугольников над обнаруженными лицами.

1
2
3
it.result.forEach {
    canvas.drawRect(it.boundingBox, paint)
}

Наконец, не забудьте передать новое растровое изображение в виджет ImageView только он будет готов.

1
2
3
runOnUiThread {
    image_holder.setImageBitmap(markedBitmap)
}

Если вы запустите приложение сейчас, вы сможете выполнять распознавание лиц на любом изображении, в котором есть люди.

Приложение, выполняющее распознавание лиц

Я уверен, что вы будете впечатлены быстротой и точностью операций по распознаванию лиц ML Kit.

Для создания меток для изображения необходимо использовать либо локальный класс FirebaseVisionLabelDetector либо класс FirebaseVisionLabelDetector на основе облачной модели. Поскольку в этом руководстве мы использовали только локальные модели, давайте теперь воспользуемся облачной моделью. Чтобы получить ссылку на экземпляр класса FirebaseVisionCloudLabelDetector , вы должны снова использовать класс FirebaseVision .

Добавьте следующий код в метод generateLabels() :

1
2
val detector =
       FirebaseVision.getInstance().visionCloudLabelDetector

Затем, как обычно, вызовите метод detectInImage() и присвойте экземпляру OnCompleteListener его возвращаемое значение.

1
2
3
4
5
detector.detectInImage(FirebaseVisionImage.fromBitmap(
           (image_holder.drawable as BitmapDrawable).bitmap
       )).addOnCompleteListener {
           // More code here
       }

На этот раз внутри слушателя вы получите доступ к списку объектов FirebaseVisionCloudLabel , каждый из которых имеет свойство label содержащее потенциальную метку для изображения. С каждой меткой также связано свойство confidence , определяющее, насколько ML Kit относится к метке.

В следующем коде показано, как выполнить цикл по списку меток и создать диалоговое окно с предупреждением, отображающее только те метки, у которых показатель достоверности превышает 70%.

1
2
3
4
5
6
7
8
var output = «»
it.result.forEach {
    if(it.confidence > 0.7)
        output += it.label + «\n»
}
runOnUiThread {
    alert(output, «Labels»).show()
}

Продолжайте и снова запустите приложение, чтобы увидеть, какие ярлыки генерирует ваше приложение для изображений, которые вы на него бросаете.

Приложение, генерирующее ярлыки

С помощью Firebase ML Kit Google хочет сделать машинное обучение доступным и массовым, а также упростить такие задачи, как аналитика и отчеты о сбоях. Из этого вводного руководства вы узнали, как работать с некоторыми из его базовых API в приложениях для Android. Вы также узнали, как использовать предлагаемые им облачные и локальные модели.

Чтобы узнать больше, обратитесь к официальной документации .