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