Статьи

Как применить машинное обучение к Android с помощью Fritz.ai

В этой статье описывается, как применить машинное обучение к Android с помощью Fritz.ai. Прежде чем углубляться в детали разработки Android-приложения для машинного обучения, полезно кратко описать, что такое платформа Fritz.ai. Как вы, возможно, знаете, машинное обучение является интересной темой, которая приобретает все большее значение и обещает изменить несколько областей, включая то, как мы взаимодействуем с приложениями для Android.

Чтобы экспериментировать, как применить машинное обучение к Android с помощью Fritz.ai, мы разработаем приложение для Android, которое использует классификацию изображений машинного обучения .

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

Что такое платформа машинного обучения Fritz.ai?

Fritz.ai — это платформа машинного обучения для Android и iOS, которая упрощает разработку приложения машинного обучения для Android . При разработке приложения Android с машинным обучением обычно необходимо создать ML-модель, которая будет использоваться приложением Android. Процесс построения ML-модели утомителен и сложен. Fritz.ai предоставляет набор встроенных моделей, готовых к использованию, что ускоряет разработку приложения Machine Learning для Android.

Встроенные ML-модели, представленные Fritz.ai:

  • Маркировка изображения
  • Обнаружение объекта
  • Стиль передачи
  • Сегментация изображения
  • Оценка позы

Кроме того, можно загрузить пользовательскую модель, если мы хотим использовать конкретную модель.

Как настроить Fritz.ai

Первым шагом для использования платформы Fritz.ai Machine Learning является создание бесплатной учетной записи, а затем создание нового проекта Android для машинного обучения, как показано на рисунке ниже:

Fritz.ai

Теперь можно добавить новый проект:

Fritz.ai

Вы должны предоставить название проекта. После того, как проект создан, необходимо предоставить пакет проекта:

Fritz.ai

Как настроить проект Android с помощью Fritz.ai

После того, как проект правильно настроен в консоли Fritz.ai, мы можем настроить проект Android на включение Fritz.ai. На уровне проекта необходимо изменить build.gradle следующим образом:

1
2
3
4
5
6
7
8
9
...
allprojects {
 repositories {
    google()
    jcenter()
  }
}
...

и в build.gradle на уровне приложения:

1
2
3
4
5
dependencies {
    ....
    implementation 'ai.fritz:core:3.0.1'
    implementation 'ai.fritz:vision:3.0.1'
}

Последний шаг — регистрация службы, чтобы приложение Android могло получать обновления модели. Для этого в Manifest.xml необходимо добавить:

1
2
3
4
<service           
   android:name="ai.fritz.core.FritzCustomModelService"
   android:exported="true"
   android:permission="android.permission.BIND_JOB_SERVICE" />

Это все. Теперь мы готовы начать разработку нашего Android-приложения для машинного обучения.

Больше полезных ресурсов

Firebase ML Kit: создание приложения для определения особенностей лица с помощью Face Detection API

9 способов машинного обучения революционизируют управление цепочками поставок

Внедрение машинного обучения для маркировки изображений в Android

Чтобы реализовать приложение Android, которое использует маркировку изображений машинного обучения, мы должны выполнить следующие шаги:

  • Настройте Fritz.ai SDK в приложении для Android
  • Пометьте изображение как обнаруженное

Настроить Fritz.ai SDK в приложении для Android

Первым шагом является настройка Fritz.ai SDK в нашем приложении для Android, чтобы мы могли использовать его позже, когда нам понадобится пометить захваченное изображение. Давайте создадим действие и в onCreate() добавим следующие строки:

1
2
3
4
5
6
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Fritz.configure(this, "your_fritz.ai_key");
     downloadModel();
 }

В строке 4 необходимо настроить Fritz с помощью API_KEY, который мы получаем во время настройки проекта в консоли. Следующий шаг, это загрузка модели из облака:

01
02
03
04
05
06
07
08
09
10
11
private void downloadModel() {
  FritzManagedModel model = new ImageLabelManagedModel();
  Log.d(TAG, "Download model...");
  FritzVision.ImageLabeling.loadPredictor(model, new PredictorStatusListener<FritzVisionLabelPredictor>() {
      @Override
      public void onPredictorReady(FritzVisionLabelPredictor predictor) {
         Log.d(TAG, "Model downloaded");
         MainActivity.this.predictor = predictor;
      }
   });
}

В этом случае приложение Android использует ImageLabelManageModel потому что мы хотим пометить изображение с помощью машинного обучения.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
 
    <TextureView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:id="@+id/preview"/>
 
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btnLabel"
        android:text="Label it"
        android:layout_alignParentBottom="true"/>
 
</RelativeLayout>


TextureView

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

Как использовать машинное обучение для маркировки изображения

Чтобы использовать машинное обучение для классификации изображения, когда у нас есть изображение с камеры, необходимо создать экземпляр FritzVisionImage . Предположим, к настоящему времени, что у нас есть экземпляр ImageReader который содержит изображение, снятое с камеры. Необходимо преобразовать его в растровое изображение, а затем использовать предиктор для маркировки изображения:

1
2
3
4
5
6
7
Image image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
Bitmap bitmapImage = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, null);
 
FritzVisionImage fvi = FritzVisionImage.fromBitmap(bitmapImage);

Наконец, в строке 8 предиктор, который пометит изображение, готов к использованию. Теперь приложение Android может получить список меток с

Относительная
точность:

1
2
3
4
5
6
FritzVisionLabelResult labels = predictor.predict(fvi);
List<FritzVisionLabel> labelList = labels.getVisionLabels();
if (labelList != null && labelList.size() > 0) {
    FritzVisionLabel label = labels.getVisionLabels().get(0);
    System.out.println("Label [" + label.getText() + "]");
}

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

Управление камерой в Android

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

TextureView

буду

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
TextureView.SurfaceTextureListener surfaceListener = new TextureView.SurfaceTextureListener() {
   @Override
   public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
       Log.d(TAG, "Surface available");
       openCamera();
   }
   @Override
   public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {}
   @Override
   public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
      return false;
   }
   @Override
   public void onSurfaceTextureUpdated(SurfaceTexture surface) {
    }
 };

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

1
2
preview = (TextureView) findViewById(R.id.preview);
preview.setSurfaceTextureListener(surfaceListener);

Теперь можно открыть камеру:

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
private void openCamera() {
    CameraManager manager = (CameraManager)
    getSystemService(Context.CAMERA_SERVICE);
    // We get the first available camera
     try {
         cameraId = manager.getCameraIdList()[0];
         CameraCharacteristics characteristics =
               manager.getCameraCharacteristics(cameraId);
         StreamConfigurationMap streamConfMap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
         imageDimension = streamConfMap.getOutputSizes(SurfaceTexture.class)[0];
 
         // We can open the camera now
         manager.openCamera(cameraId, new cameraDevice.StateCallback() {
             @Override
             public void onOpened(@NonNull CameraDevice camera) {
                Log.i(TAG, "Camera opened");
                cameraDevice = camera;
                createPreview();
             }
             @Override
             public void onDisconnected(@NonNull CameraDevice camera) {      }
             @Override
             public void onError(@NonNull CameraDevice camera, int error) {
                Log.e(TAG, "Error opening the camera");
                }
            }, null);
        }
        catch(CameraAccessException cae) {
            // Let us handle the error
        }
        catch(SecurityException se) {
 
        }
    }

Когда камера открыта и готова к использованию, приложение Android может начать потоковую передачу изображений:

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
49
50
51
private void createPreview() {
        SurfaceTexture surfaceTexture = preview.getSurfaceTexture();
        surfaceTexture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());
        Surface surface = new Surface(surfaceTexture);
        try {
            previewRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            previewRequestBuilder.addTarget(surface);
 
            cameraDevice.createCaptureSession(Arrays.asList(surface),
                new CameraCaptureSession.StateCallback() {
                   public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
                       cameraSession = cameraCaptureSession;
                       previewRequestBuilder.set(
                              CaptureRequest.CONTROL_AF_MODE,
                               CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                       // Flash is automatically enabled when necessary.
                       previewRequestBuilder.set(
                               CaptureRequest.CONTROL_AE_MODE,
                               CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
 
                       // Finally, we start displaying the camera preview.
                       CaptureRequest previewRequest = previewRequestBuilder.build();
                       try {
                           cameraSession.setRepeatingRequest(
                                   previewRequest, new CameraCaptureSession.CaptureCallback() {
                                       @Override
                                       public void onCaptureProgressed(
                                               final CameraCaptureSession session,
                                               final CaptureRequest request,
                                               final CaptureResult partialResult) {
                                       }
 
                                       @Override
                                       public void onCaptureCompleted(
                                               final CameraCaptureSession session,
                                               final CaptureRequest request,
                                               final TotalCaptureResult result) {
                                       }
                                   }, backgroundHandler);
                       }
                       catch(CameraAccessException cae) {}
                  }
 
                 @Override
                    public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
                    Log.e(TAG, "Configuration failed");
                   }
               }, null);
        }
        catch (CameraAccessException cae) {}
    }

Маркировка изображения, полученного камерой

На этом последнем шаге необходимо сделать снимок и пометить его с помощью машинного обучения. Для этого приложение Android использует кнопку, определенную в предыдущем макете:

1
2
3
4
5
6
7
labelBtn = (Button) findViewById(R.id.btnLabel);
labelBtn.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View v) {
          takePicture();
      }
});

В


takePicture

метод
приложение для Android берет изображение и маркирует его (как показано выше). Если вы хотите получить полный код, вы можете зайти на Github и скачать его.

Резюме

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

Опубликовано на Java Code Geeks с разрешения Франческо Аццолы, партнера по нашей программе JCG. Смотрите оригинальную статью здесь: Как применить Machine Learning к Android с помощью Fritz.ai

Мнения, высказанные участниками Java Code Geeks, являются их собственными.