Вступление


Добрый день, уважаемые читатели! Всем давно известно, что мобильные устройства всё чаще комплектуются мощным аппаратным обеспечением. Процессоры современных смартфонов почти сравнялись с настольными аналогами, а проблемы с возможной нехваткой оперативной и внешней памяти уходят на второй план. Сегодня уже не встретишь телефоны или планшеты без внушительной программной платформы вроде Android, iOS или Windows, а кроме того, все мобильные устройства имеют те или иные встроенные модули, вроде фотокамеры. В данной статье речь пойдёт о встраивании библиотеки компьютерного зрения OpenCV в проект приложения для Android. Вероятно, данная статья не имела бы никакой значимой ценности, однако все инструкции в ней предназначены для Android Studio, новой официальной среды разработки от Google. К тому же, в статье описывается статическая инициализация OpenCV в Android без использования OpenCV Manager. Ниже представлен план руководства:

  1. Загрузка OpenCV SDK для Android
  2. Установка OpenCV в проект Android Studio
  3. Разработка примера приложения OpenCV для Android

Не будем терять времени и начнём работу.

1. Загрузка OpenCV SDK для Android


Для того, чтобы использовать OpenCV в своих приложениях, необходимо загрузить соответствующий SDK. Сделать это можно на официальном сайте opencv.org. На рисунке ниже показана ссылка на скачивание нужного архива:



В архив OpenCV SDK для Android входят двоичные файлы библиотек под разные архитектуры микропроцессоров, обёртка на языке программирования Java, которая использует Java Native Interface (JNI) для вызова функций из платформо-зависимых библиотек, исходные коды примеров программ и файлы .apk для установки OpenCV Manager. Следующий шаг — добавление модуля OpenCV в проект Android Studio.

2. Установка OpenCV в проект Android Studio


Импорт модуля OpenCV в проект Android Studio не представляет труда. Для этого нужно выбрать меню File -> New -> Import Module... и указать путь sdk/java из распакованного архива SDK. Все остальные настройки импорта менять не обязательно. На рисунке ниже показано окно мастера с указанием пути импорта модуля и его нового имени в проекте:



После импорта модуля в его build.gradle нужно обязательно обновить параметры compileSdkVersion, buildToolsVersion, minSdkVersion и targetSdkVersion, чтобы они совпадали с соответствующими параметрами из модуля приложения. После того, как модуль OpenCV был добавлен, его нужно присоединить в качестве зависимости к модулю приложения. Для этого нужно выбрать меню File -> Project Structure... и для модуля app указать зависимость от opencv. На рисунке ниже показано окно настройки зависимостей:



Последнее, что осталось сделать — добавить двоичные библиотеки OpenCV в проект, чтобы при сборке они были упакованы в .apk приложения. Для этого нужно скопировать папку sdk/native/libs из OpenCV SDK в папку проекта по пути app/src/main. Затем нужно переименовать папку libs в jniLibs. Следует отметить, что не нужно упаковывать статические библиотеки OpenCV (расширение .a) в .apk и хранить их в проекте. В образовавшейся папке jniLibs для каждой архитектуры можно оставить только файлы с расширением .so. На рисунке ниже показана получившаяся структура папок в Проводнике Windows:



3. Разработка примера приложения OpenCV для Android


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

MainActivity.java
package com.androidcv;

import android.app.Activity;
import android.os.Bundle;
import android.view.SurfaceView;
import android.view.WindowManager;

import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Mat;


public class MainActivity extends Activity implements CvCameraViewListener2 {
    private CameraBridgeViewBase mOpenCvCameraView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setContentView(R.layout.activity_main);
        mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.view);
        mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
        mOpenCvCameraView.setCvCameraViewListener(this);
    }

    @Override
    public void onPause()
    {
        super.onPause();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    @Override
    public void onResume()
    {
        super.onResume();
        OpenCVLoader.initDebug();
        mOpenCvCameraView.enableView();
    }

    public void onDestroy() {
        super.onDestroy();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    public void onCameraViewStarted(int width, int height) {
    }

    public void onCameraViewStopped() {
    }

    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
        return inputFrame.rgba();
    }
}


activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:opencv="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <org.opencv.android.JavaCameraView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:visibility="gone"
        android:id="@+id/view"
        opencv:camera_id="any" />

</FrameLayout>


AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.androidcv" >

    <supports-screens android:resizeable="true"
        android:smallScreens="true"
        android:normalScreens="true"
        android:largeScreens="true"
        android:anyDensity="true" />

    <uses-permission android:name="android.permission.CAMERA"/>

    <uses-feature android:name="android.hardware.camera" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.front" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:screenOrientation="landscape"
            android:configChanges="keyboardHidden|orientation">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


На рисунке ниже показан результат работы приложения:



Заключение


В заключение нужно сказать, что хотя статическое связывание библиотек OpenCV представляется удобным, разработчики предписывают использовать этот способ только на этапе отладки. При выпуске приложения, например, в Google Play, лучше использовать OpenCV Manager.

Комментарии (7)


  1. Valery35
    08.07.2015 17:51

    del


  1. oENDark
    09.07.2015 07:13

    А какие конкретно применения есть у этой библиотеки? Практические, а не теоретические.


    1. andlom Автор
      09.07.2015 10:39
      +1

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



  1. Mikhail_dev
    09.07.2015 07:45

    В данной статье речь пойдёт о встраивании библиотеки компьютерного зрения OpenCV в проект приложения для Android.

    Всё? Это всё что можно сказать про OpenCV, о котором вы пишете статью?

    Вот статья про подключение OpenCV для андроида через градл, с помощью менеджера
    habrahabr.ru/post/217377

    Автор приводит некоторые вырезки с документации, отсюда
    According to this approach all OpenCV binaries are included into your application package. It is designed mostly for development purposes. This approach is deprecated for the production code, release package is recommended to communicate with OpenCV Manager via the async initialization described above.

    Что вы скажете об этом?


    1. andlom Автор
      09.07.2015 10:59

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


  1. ftp27
    09.07.2015 10:23

    А можно поступить проще и собирать проект с помощью Maven