Programación OpenCV para Android Introducción

Esta vez veremos el proceso requerido para desarrollar una App para el sistema Android utilizando la biblioteca OpenCV, aprenderemos como configurar nuestro entorno de programación y crearemos nuestra primera aplicación la cual nos permitirá capturar video accediendo a la cámara del dispositivo, dicho video será procesado en tiempo real para mostrar el detector de bordes Canny.

app opencv

Para empezar con este tutorial requerimos Android Studio 3.x además del OpenCV4Android SDK que puedes compilar a partir del código fuente como lo hicimos en la publicación anterior o simplemente puedes descargar los archivos pre-compilados, por supuesto también se requieren todas las herramientas destinadas a desarrollar aplicaciones Android, asumiremos que sabes como instalar y configurar el Android SDK y que haz desarrollado aplicaciones de este tipo anteriormente o por lo menos tienes los conocimientos básicos.

Lo primero que haremos será crear nuestro proyecto, de la siguiente manera:

Android - Crear proyecto nuevo

Le damos una ubicación y nombre al proyecto.

Android - Seleccionar SDK

Establecemos el nivel de API mínimo aceptado por nuestra aplicación.

Android Studio - agregar activity

Creamos una actividad vacía.

Android Studio - agregar nombre activity

Le damos un nombre a la actividad y listo, tenemos nuestro proyecto.

Agregar OpenCV4Android SDK a Android Studio IDE

Para agregarlo debemos ir al menú principal File | New | Import Module..., debes localizar la carpeta en donde guardaste el OpenCV4Android-SDK dentro de él seleccionas la carpeta ../sdk/java cuando lo hagas el nombre del módulo aparecerá automáticamente.

Recuerda que este SDK lo puedes obtener ya sea compilando desde código fuente y descargando el Zip comprimido que contiene los archivos pre-compilados.

OpenCV4Android importar módulo

Al presionar Next se muestra la ventana de la imagen de abajo, quita todas las selecciones ya que no las necesitamos.

OpenCV4Android configurar módulo

Para terminar solo debes presionar el botón Finish.

Lo siguiente que debemos hacer es editar el archivo build.gradle que corresponde al módulo que acabamos de agregar, puedes ubicarlo en la pestaña Project expandiendo el módulo correspondiente.

Observa que en la parte superior izquierda está seleccionada la opción Project si tienes otro selección el archivo puede aparecer en otro lugar o quizás no aparezca.

Editar build.gradle

Deberás cambiar la primera línea y también quitar la configuración applicationId el archivo debe quedar de este modo:

apply plugin: 'com.android.library' // editar .application

android {
    compileSdkVersion 26
    buildToolsVersion "26.0.2"

    defaultConfig {
//        applicationId "org.opencv" // comentar
        minSdkVersion 8
        targetSdkVersion 21
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
}

La versión del SDK de compilación y de las herramientas de construcción debe coincidir con las indicadas el archivo build.gradle de la aplicación, esto es solo si las haz cambiado si tienes la configuración por defecto todo estará correcto.

El siguiente paso es agregar el módulo openCVLibrary330 como una dependencia de nuestra aplicación, debes acceder al menú File | Project Structure… ubica app luego selecciona la pestaña Dependencies haz clic en icono + que se muestra en la parte superior derecha de la ventana y selecciona la opción 3, en la siguiente ventana selecciona el módulo indicado y presiona OK.

agregar módulo opencv a android studio

Hecho esto el siguiente paso el modificar el XML de nuestra actividad (Activity) lo que haremos será agregar un componente llamado JavaCameraView el cual nos permitirá visualizar en tiempo real el video capturado por la cámara del dispositivo.

<?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:opencv="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="programacion.tutor.opencvandroid.OpenCVActivity">

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

</android.support.constraint.ConstraintLayout>

Ahora podemos modificar el código java de la actividad, utilizaremos el método estático OpenCVLoader.initDebug() para inicializar la librería y aprovecharemos los métodos onResume() y onPause() para habilitar o deshabilitar el componente, en el método onCreate() lo inicializamos.

public class OpenCVActivity extends AppCompatActivity 
        implements CameraBridgeViewBase.CvCameraViewListener2 {

    private CameraBridgeViewBase cameraView = null;
    private static boolean initOpenCV = false;

    static { initOpenCV = OpenCVLoader.initDebug(); }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_open_cv);

        cameraView = (CameraBridgeViewBase) findViewById(R.id.cameraview);
        cameraView.setVisibility(SurfaceView.VISIBLE);
        cameraView.setCvCameraViewListener(this);
    }


    @Override
    protected void onResume() {
        super.onResume();

        if (initOpenCV) { cameraView.enableView(); }
    }

    @Override
    public void onPause() {
        super.onPause();

        // Release the camera.
        if (cameraView != null) {
            cameraView.disableView();
            cameraView = null;
        }
    }

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

    @Override
    public void onCameraViewStopped() { }

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

Los tres últimos métodos que se observan arriba son requeridos por la interface CvCameraViewListener2 nos sirven para detectar cuando la captura se inicia o se detiene, los primeros dos respetivamente, mientras que el tercero onCameraFrame(...) nos permitirá procesar cada cuadro capturado, en nuestro ejemplo usamos el método inputFrame.rgba() para devolver el objeto Mat original sin modificación.

Hagamos una modificación para hacer nuestra aplicación un poco más interesante:

public class OpenCVActivity extends AppCompatActivity
        implements CameraBridgeViewBase.CvCameraViewListener2 {

   //...
    
    @Override
    public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {

        Mat src = inputFrame.gray(); // convertir a escala de grises
        Mat cannyEdges = new Mat();  // objeto para almacenar el resultado

        // aplicar el algoritmo canny para detectar los bordes
        Imgproc.Canny(src, cannyEdges, 10, 100);

        // devolver el objeto Mat procesado
        return cannyEdges;
    }
}

Ahora obtendremos una imagen binaria que el resultado de aplicar el algoritmo Canny.

Para poder acceder a la cámara requerimos permisos por lo que debemos modificar el manifiesto de nuestra aplicación el cual quedara del siguiente modo:

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".OpenCVActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

    <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"/>

</manifest>

El último paso es copiar el contenido de la carpeta ..\opencv4android\sdk\native\libs en nuestro proyecto debemos hacerlo en el siguiente directorio ..\OpenCVAndroid\app\src\main\jniLibs puedes eliminar los archivo con extensión .a solo nos interesa el archivo libopencv_java3.so puedes copiar todas las carpetas o solo aquella que corresponde a la arquitectura de CPU para la cual esta destinada tu aplicación, ejemplos (arm64-v8a, armeabi-v7a, …).

Agregar libreria nativa

Con esto ya puedes puedes probar tu aplicación en un dispositivo físico, debes recordar que el versiones actuales de la API de Android se requiera otorgar permisos en tiempo de ejecución para acceder a la cámara no hemos agregado este código para hacer lo más simple posible nuestro proyecto pero puedes otorgar el permiso desde tu dispositivo en: Ajustes | Aplicaciones | <NuestraApp> | Permisos activar la opción para la cámara.

Si no tienes el permiso verás un mensaje como este:

sin permiso para camara

Cuando ya tengas todo preparado para probar tu aplicación podrás ver algo como esto:

tutorial app opencv android

En tiempo real se muestra la captura de la cámara del dispositivo, esta es procesada por al algoritmo de detección de bordes Canny implementado por OpenCV, debes tener presente que el componente JavaCameraView esta diseñado para trabajar en modo landscape.

Descargar código fuente: opencv-android.zip (no están incluidas las librerías nativas en la carpeta jniLibs)

Comentarios

  1. Hola carmelo, quiero dialogar con usted.

    ResponderEliminar
    Respuestas
    1. Hola, si tienes alguna consulta con respecto al tema OpenCV Android me la puedes hacer llegar por este medio, por otra parte si lo que requieres es mi ayuda como profesional me puedes contactar por medio de Workana, mi perfil es:
      https://goo.gl/bJXJ2V

      Eliminar
  2. Carmelo, estoy interesado en tus servicios profesionales. publique un proyecto en workana pero no se como contactarte. se llama Tortilla Counter!

    ResponderEliminar
    Respuestas
    1. Hola, ya me he contactado con usted por Workana.

      Eliminar
  3. disculpa en el ultimo paso debemos copiar las carpetas que vienen en el \opencv4android\sdk\native\libs y veo que tu las estas pegando en una carpeta llamada "jniLibs" mi pregunta es de donde salio la carpeta "jniLibs"? tu la creaste y pegaste ahí los archivos o se tuvo que crear por si sola?

    ResponderEliminar
    Respuestas
    1. Si la carpeta jniLibs no existe en tu proyecto debes crearla.

      Eliminar
  4. amigo disculpa, quiero crear una aplicacion para reconocer objetos en android studio entreno un clasificador y me arroja un archivo .XML el cual ya he implementado en python, funciona para reconocer el pbjeto que yo le diga solo ace falta imagenes positivas y negativas a demas de un buen entrenamiento para que funcione, mi pregunta es como puedo introducir ese archivo .XML entrenado para reconocer desde mi android? se puede?

    ResponderEliminar
    Respuestas
    1. Por supuesto que es posible, debes agregar el archivo .xml como recurso del proyecto Android y luego leerlo o cargarlo, casualmente trabajo en un tutorial sobre el tema de clasificadores en cascada XML, lo tendré listo en un par de días.

      Eliminar
  5. hola profe carmelo quiero contactar tus servicios profesionales para el proyecto que tengo , que ya en otros tutoriales te he comentado, ya he creado el clasificador siguiendo tus tutoriales, pero no he logrado concretar el código para que me entrene las señas, ya que el proceso de reconocimiento facial tiene parametros como lo son las coordenadas del rostro y los ojos.

    ResponderEliminar
  6. Disculpa quisiera saber de que manera puedo aplicar ese filtro pero para una imagen fija guardada en el movil

    ResponderEliminar
    Respuestas
    1. Debes cargar la imagen y luego convertirla a un objeto Mat de OpenCV después de esto aplicas el filtro, puedes usar la clase org.opencv.android.Utils que contiene métodos estáticos como: loadResource() que sirve para cargar una imagen que se encuentra como recurso, matToBitmap() y bitmapToMap() te sirven para realizar la conversión de Mat a Bitmap y viceversa.

      Eliminar
  7. Buenas noches, el ejemplo me funciono pero tuve un error sobre CMake, el cual encontré la solución en Internet, lo que quiero aprender es desarrollar una aplicación de reconocimiento de placas de vehículos en tiempo real, seguiré buscando información, muchas gracias por su aportación me sirve de mucho.

    ResponderEliminar

Publicar un comentario

Temas relacionados

Entradas populares de este blog

Conectar SQL Server con Java

Entrenar OpenCV en Detección de Objetos

Spring Boot : Crear una Aplicación Web

Spring Acceso a datos con JDBC

Manipular pixeles OpenCV Python