Android y JavaCV: Cargar imágenes



Tanto JavaCV como OpenCV son muy fáciles de utilizar en un ordenador. Pero a la hora de trabajar en Android en seguida surge un pequeño problema: ¿Cómo cargo las imágenes?. La clase BufferedImage no existe en Android, y la mitad de los métodos no funcionan por una u otra razón.

Nota: Recordad que en OpenCV (y por lo tanto JavaCV), el formato por defecto es BGR para las imágenes en color (CV_LOAD_IMAGE_COLOR).


Soluciones para cargar imagenes

Desde recursos (p.ej: res/drawable/imagen.png)

Aquí el problema consiste en que los recursos se accede a través de un identificador tipo int, así que el truco consiste en cargar un bitmap y copiar directamente los píxeles desde el bitmap a una IplImage:

// Se carga el recurso en un bitmap
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.imagen);

// Se crea la imagen
IplImage image = IplImage.create(bitmapMask.getWidth(), bitmapMask.getHeight(), IPL_DEPTH_8U, 4); // ARGB

// Se copian los píxeles del bitmap a la imagen
bitmap.copyPixelsToBuffer(image);

Desde Assets (p.ej: assets/imagen.jpg) 

El problema consiste en que los archivos guardados en assets están comprimidos, por lo que acceder a través del path (file:///android_asset/imagen.jpg) no funciona. El truco consiste en copiarlo a la caché y cargar la imagen desde ahí:

// type: CV_LOAD_IMAGE_COLOR
public static IplImage loadImageFromAsset(Context context, String filename, int type) {

  IplImage image = null;

  File file = new File(context.getCacheDir() + "/" + filename);
  if (!file.exists())
   try {

    InputStream is = context.getAssets().open(filename);
    int size = is.available();
    byte[] buffer = new byte[size];
    is.read(buffer);
    is.close();

    FileOutputStream fos = new FileOutputStream(file);

    fos.write(buffer);
    fos.close();
   } catch (Exception e) {
    throw new RuntimeException(e);
   }

  if (file.exists()) {
   image = cvLoadImage(file.getAbsolutePath(), type);
  }

  return image;
 }

Y por último desde la SD o path (y aunque resulte obvio desde el ejemplo anterior):

IplImage image = cvLoadImage(path, CV_LOAD_IMAGE_COLOR);