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

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

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

По данным Grand View Research, ожидается, что рынок машинного зрения вырастет до 18,24 млрд долларов к 2025 году при среднегодовом темпе роста 7,7%. Давайте посмотрим, в каких отраслях машинное зрение наиболее эффективно.

Отрасли, в которых машинное зрение используется в мобильных приложениях

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

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

Склады и логистика

Машинное зрение используется для сканирования штрих-кода на складах. Сканеры штрих-кода могут быть встроены в носимые или мобильные приложения для мобильности на складе.

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

Розничная торговля

Розничная торговля - это большая отрасль, в которой машинное зрение может принести пользу. Как?

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

Мобильное приложение ASOS делает именно это.

Его функция визуального поиска основана на машинном зрении.

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

сельское хозяйство

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

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

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

Обзор машинного зрения

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

Машинное зрение можно использовать для

  • признавая,
  • идентификация,
  • обнаружение объектов,
  • распознавание текста,
  • реконструкция 3D-форм на основе 2D-изображений,
  • распознавание и анализ движения,
  • реконструкция изображений,
  • сегментирование изображений,
  • и многое другое.

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

Лучшие инструменты машинного обучения для распознавания изображений

OpenCV: самая известная библиотека машинного обучения

OpenCV - самая популярная библиотека машинного зрения среди разработчиков. Это библиотека с открытым исходным кодом, в которой хранятся тысячи алгоритмов обработки и анализа изображений, в том числе для распознавания объектов на фотографиях. Например, вы можете использовать OpenCV для распознавания лиц и поз людей или для распознавания текста.

Эта библиотека была разработана Intel, и теперь ее поддерживают Willow Garage и Itseez. Он написан на C ++, но также разработан для других языков программирования, включая Python, Java, Ruby и Matlab.

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

  • анализ и обработка изображений,
  • распознавание лица,
  • идентификация объекта,
  • распознавание жестов в видеороликах,
  • распознавание движения камеры,
  • построение 3D моделей объектов,
  • поиск похожих изображений в базе данных,
  • отслеживание движения глаз,
  • сегментация изображения,
  • видео слежение и
  • распознавание элементов сцены и добавление маркеров для дополненной реальности.

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

TensorFlow: фреймворк для глубокого обучения

TensorFlow - это фреймворк машинного обучения от Google, который можно использовать для проектирования, создания и реализации моделей глубокого обучения. Глубокое обучение - это часть машинного обучения, основанная на том, как работает человеческий мозг.

Вы можете использовать TensorFlow для создания и обучения нейронных сетей любого известного типа.

Библиотека TensorFlow уже работает на множестве платформ, от огромных серверов до крошечных устройств Интернета вещей. Мобильные устройства - не исключение. Для мобильных приложений Google выпустила отдельную библиотеку под названием TensorFlow Lite.

Он был представлен на I / O 2017 и

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

MLKit: новейший фреймворк для машинного обучения

Google представил Firebase MLKit на I / O 2018, и это один из самых простых в использовании фреймворков для машинного обучения. Его API позволяет разработчикам использовать

  • распознавание текста,
  • распознавание лица,
  • распознавание штрих-кода,
  • знаковое признание,
  • маркировка изображений и
  • распознавание объектов.

Независимо от того, являетесь ли вы начинающим разработчиком или опытным разработчиком, вы можете легко использовать MLKit в своих мобильных приложениях.

Позвольте мне показать вам пример того, как я использовал MLKit для маркировки изображений.

Учебник по маркировке изображений

1. Первый шаг - подключиться к сервисам Firebase. Для этого вам нужно войти в консоль Firebase и создать новый проект.

2. Затем вам нужно добавить следующие зависимости в ваш файл gradle:

implementation 'com.google.firebase:firebase-ml-vision:18.0.1'
implementation 'com.google.firebase:firebase-ml-vision-image-label-model:17.0.2'

3. Если вы используете API на устройстве, настройте приложение для автоматической загрузки модели машинного обучения на устройство после установки приложения из Play Store.
Для этого добавьте следующее объявление в Файл AndroidManifest.xml:

<meta-data
   android:name="com.google.firebase.ml.vision.DEPENDENCIES"
   android:value="label" />

4. Пришло время создать макет экрана.

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".MainActivity">
   <LinearLayout
       android:id="@+id/layout_preview"
       android:layout_width="0dp"
       android:layout_height="0dp"
       android:orientation="horizontal"
       app:layout_constraintBottom_toBottomOf="parent"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toTopOf="parent" />
   <Button
       android:id="@+id/btn_take_picture"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_marginStart="8dp"
       android:layout_marginBottom="16dp"
       android:text="Take Photo"
       android:textSize="15sp"
       app:layout_constraintBottom_toBottomOf="parent"
       app:layout_constraintStart_toStartOf="parent" />
   <TextView
       android:id="@+id/txt_result"
       android:layout_width="0dp"
       android:layout_height="wrap_content"
       android:layout_marginStart="16dp"
       android:layout_marginEnd="16dp"
       android:textAlignment="center"
       android:textColor="@android:color/white"
       app:layout_constraintBottom_toBottomOf="parent"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toEndOf="@+id/btn_take_picture" />
</android.support.constraint.ConstraintLayout>

5. Используйте SurfaceView, чтобы отобразить предварительный просмотр камеры. Вы также должны добавить разрешение камеры в Manifest.xml:

android:name="android.permission.CAMERA

6. Создайте класс, расширяющий SurfaceView и реализующий интерфейс SurfaceHolder.Callback:

import java.io.IOException;
import android.content.Context;
import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
   private SurfaceHolder mHolder;
   private Camera mCamera;
   public CameraPreview(Context context, Camera camera) {
       super(context);
       mCamera = camera;
       mHolder = getHolder();
       mHolder.addCallback(this);
       // deprecated setting, but required on Android versions prior to 3.0
       mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
   }
   public void surfaceCreated(SurfaceHolder holder) {
       try {
           // create the surface and start camera preview
           if (mCamera == null) {
               mCamera.setPreviewDisplay(holder);
               mCamera.startPreview();
           }
       } catch (IOException e) {
           Log.d(VIEW_LOG_TAG, "Error setting camera preview: " + e.getMessage());
       }
   }
   public void refreshCamera(Camera camera) {
       if (mHolder.getSurface() == null) {
           // preview surface does not exist
           return;
       }
       // stop preview before making changes
       try {
           mCamera.stopPreview();
       } catch (Exception e) {
           // ignore: tried to stop a non-existent preview
       }
       // set preview size and make any resize, rotate or
       // reformatting changes here
       // start preview with new settings
       setCamera(camera);
       try {
           mCamera.setPreviewDisplay(mHolder);
           mCamera.startPreview();
       } catch (Exception e) {
           Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
       }
   }
   public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
       // If your preview can change or rotate, take care of those events here.
       // Make sure to stop the preview before resizing or reformatting it.
       refreshCamera(mCamera);
   }
   public void setCamera(Camera camera) {
       //method to set a camera instance
       mCamera = camera;
   }
   @Override
   public void surfaceDestroyed(SurfaceHolder holder) {
   }
}

7. Последнее, что вам нужно сделать, это добавить логику для главного экрана приложения:

  • Спросите у пользователя разрешение камеры.
  • Если разрешение предоставлено, покажите предварительный просмотр камеры.
  • После того, как пользователь нажмет кнопку «Сделать фото», отправьте растровое изображение в FirebaseVisionImage и покажите результат после завершения обработки.
import android.Manifest;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.ml.vision.FirebaseVision;
import com.google.firebase.ml.vision.common.FirebaseVisionImage;
import com.google.firebase.ml.vision.label.FirebaseVisionLabel;
import com.google.firebase.ml.vision.label.FirebaseVisionLabelDetector;
import com.google.firebase.ml.vision.label.FirebaseVisionLabelDetectorOptions;
import com.gun0912.tedpermission.PermissionListener;
import com.gun0912.tedpermission.TedPermission;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class MainActivity extends AppCompatActivity {
   private Camera mCamera;
   private CameraPreview mPreview;
   private Camera.PictureCallback mPicture;
   @BindView(R.id.layout_preview)
   LinearLayout cameraPreview;
   @BindView(R.id.txt_result)
   TextView txtResult;
   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       ButterKnife.bind(this);
//keep screen always on       getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
       checkPermission();
   }
//camera permission is a dangerous permission, so the user should grant this permission directly in real time. Here we show a permission pop-up and listen for the user’s response. 
   private void checkPermission() {
       //Set up the permission listener
       PermissionListener permissionlistener = new PermissionListener() {
           @Override
           public void onPermissionGranted() {
               setupPreview();
           }
           @Override
           public void onPermissionDenied(ArrayList deniedPermissions) {
               Toast.makeText(MainActivity.this, "Permission Denied\n" + deniedPermissions.toString(), Toast.LENGTH_SHORT).show();
           }
       };
       //Check camera permission
       TedPermission.with(this)
               .setPermissionListener(permissionlistener)
               .setDeniedMessage("If you reject permission,you can not use this service\n\nPlease turn on permissions at [Setting] > [Permission]")
               .setPermissions(Manifest.permission.CAMERA)
               .check();
   }
//Here we set up the camera preview
   private void setupPreview() {
       mCamera = Camera.open();
       mPreview = new CameraPreview(getBaseContext(), mCamera);
       try {
           //Set camera autofocus
           Camera.Parameters params = mCamera.getParameters();
           params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
           mCamera.setParameters(params);
       }catch (Exception e){
       }
       cameraPreview.addView(mPreview);
       mCamera.setDisplayOrientation(90);
       mCamera.startPreview();
       mPicture = getPictureCallback();
       mPreview.refreshCamera(mCamera);
   }
// take photo when the users tap the button
   @OnClick(R.id.btn_take_picture)
   public void takePhoto() {
       mCamera.takePicture(null, null, mPicture);
   }
   @Override
   protected void onPause() {
       super.onPause();
       //when on Pause, release camera in order to be used from other applications
       releaseCamera();
   }
   private void releaseCamera() {
       if (mCamera != null) {
           mCamera.stopPreview();
           mCamera.setPreviewCallback(null);
           mCamera.release();
           mCamera = null;
       }
   }
//Here we get the photo from the camera and pass it to mlkit processor
   private Camera.PictureCallback getPictureCallback() {
       return new Camera.PictureCallback() {
           @Override
           public void onPictureTaken(byte[] data, Camera camera) {
               mlinit(BitmapFactory.decodeByteArray(data, 0, data.length));
               mPreview.refreshCamera(mCamera);
           }
       };
   }
//the main method that processes the image from the camera and gives labeling result
   private void mlinit(Bitmap bitmap) {
       //By default, the on-device image labeler returns at most 10 labels for an image.
       //But it is too much for us and we wants to get less
       FirebaseVisionLabelDetectorOptions options =
               new FirebaseVisionLabelDetectorOptions.Builder()
                       .setConfidenceThreshold(0.5f)
                       .build();
       //To label objects in an image, create a FirebaseVisionImage object from a bitmap
       FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);
       //Get an instance of FirebaseVisionCloudLabelDetector
       FirebaseVisionLabelDetector detector = FirebaseVision.getInstance()
               .getVisionLabelDetector(options);
       detector.detectInImage(image)
               .addOnSuccessListener(
                       new OnSuccessListener>() {
                           @Override
                           public void onSuccess(List labels) {
                               StringBuilder builder = new StringBuilder();
                               // Get information about labeled objects
                               for (FirebaseVisionLabel label : labels) {
                                   builder.append(label.getLabel())
                                           .append(" ")
                                           .append(label.getConfidence()).append("\n");
                               }
                               txtResult.setText(builder.toString());
                           }
                       })
               .addOnFailureListener(
                       new OnFailureListener() {
                           @Override
                           public void onFailure(@NonNull Exception e) {
                               txtResult.setText(e.getMessage());
                           }
                       });
   }
}

Вот как выглядит результат:

Я использовал офлайн-версию MLKit. Облачная версия доступна только при платной подписке.

Ключевые выводы

Внедрить MLKit в мобильное приложение для Android оказалось довольно просто. Когда я его протестировал, я обнаружил, что он не очень точен, но все же отлично работает для офлайн-сервиса.

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

Разработчики MLKit позаботились о том, чтобы их решение машинного обучения было удобно интегрировать в мобильное приложение. Чтобы сделать его более продвинутым и настраиваемым, вам нужно будет использовать TensorFlow. В этом случае MLKit станет уровнем API для вашей системы машинного обучения, позаботится о хостинге и принесет модель TensorFlow в ваше мобильное приложение.

Хотите узнать, как создать расширенную модель машинного обучения или машинного зрения и интегрировать ее в свое мобильное приложение? Свяжитесь с Mobindustry. Мы поможем вам создать интеллектуальное решение для мобильного бизнеса.

Получите бесплатную консультацию!
[email protected]

Https://www.mobindustry.net/how-to-integrate-machine-learning-into-an-android-app-best-image-recognition-tools/