Добавление библиотеки OpenCV в проект Android Studio


    Вступление


    Добрый день, уважаемые читатели! Всем давно известно, что мобильные устройства всё чаще комплектуются мощным аппаратным обеспечением. Процессоры современных смартфонов почти сравнялись с настольными аналогами, а проблемы с возможной нехваткой оперативной и внешней памяти уходят на второй план. Сегодня уже не встретишь телефоны или планшеты без внушительной программной платформы вроде 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.
    Поделиться публикацией
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 13
    • 0
      del
      • 0
        А какие конкретно применения есть у этой библиотеки? Практические, а не теоретические.
      • 0
        В данной статье речь пойдёт о встраивании библиотеки компьютерного зрения 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.

        Что вы скажете об этом?
        • 0
          У меня не было цели подробно рассказывать про OpenCV. Я лишь хотел показать, что подобные технологии можно и нужно использовать на мобильных устройствах и объяснил, как это сделать. По поводу статической инициализации я высказался в заключении, однако кому-нибудь может показаться полезным именно этот способ. Нужна хорошая инструкция, я в своё время потратил несколько дней, чтобы заставить работать приложение со статической инициализацией.
        • 0
          А можно поступить проще и собирать проект с помощью Maven
          • 0
            При выпуске приложения, например, в Google Play, лучше использовать OpenCV Manager.

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

            Большое спасибо!
            • 0
              Я так и не понял, в чем проблема статической инициализации? Я могу использовать ее в Релизе приложения? Ну я уж точно не хочу просить пользователей что то скачать и т.д.
              • 0
                Вы можете использовать статическую инициализацию, если не хотите принуждать пользователей дополнительно устанавливать OpenCV Manager. Это возможно даже при публикации приложения в Google Play. При разработке приложения в Android Studio можно с помощью Gradle при сборке генерировать несколько .APK файлов под различные архитектуры микропроцессоров и использовать Multiple APK в Google Play (подробности). Можно поступить так, как описано в статье, при этом итоговый .APK файл будет содержать библиотеки под все архитектуры и выбор будет происходить автоматически. OpenCV Manager даёт некоторые преимущества (подробности), но лично я считаю, что без этого можно вполне обойтись.
                • 0
                  Спасибо за Ваш ответ. И еще вопрос, а как Вы боролись с «Пьяной камерой» в Андроид? Я ни как не могу правильно настроить работу фронтальной камеры в «Портретном» режиме
                  • 0
                    Признаюсь, с этим я никак не боролся. Недавно я начал проектировать довольно крупный проект под Android с использованием OpenCV, при этом я решил отказаться от захвата изображения с камеры средствами данной библиотеки. Я решил поступить по-другому: код приложения для доступа к камере и захвата изображения будет написан с использованием стандартного API Android, а обработкой кадров займётся OpenCV. Для этого существуют функции, позволяющие преобразовать изображения Android в «родные» примитивы OpenCV. Такой подход предпочтителен в том числе потому, что существует подробная документация по работе с камерой в Android, и заставить работать камеру так, как нужно, довольно легко.
                    • 0
                      Очень хотелось бы получить от Вас новую статью по этому поводу.

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