Guardar los vectores de características de ORB usando OpenCV4Android (java API)

Tengo un conjunto de imágenes de entrenamiento, para cada una de las cuales he detectado y calculado sus vectores de características (utilizando descriptores y extractores de funciones ORB), ya que necesito guardarlas para reutilizarlas para hacer coincidir las imágenes de prueba (usando Clasificador SVM), ¿cuál es la mejor manera de almacenar los vectores de características, localmente en el dispositivo Android?

Los vectores de función que se van a guardar son de tamaño variable por imagen y, por tanto, aquellos con tamaños no maximales se rellenan con ceros para unificar los tamaños de todos los vectores. El tamaño máximo actualmente es de 500 filas x 32 cols; Así 16k características.

Aquí están las opciones que podría alcanzar hasta ahora;

  • He oído hablar de FileStorage de OpenCV, pero al pasar por la documentación de Java, me di cuenta de un método de save para las características HOG (no ORB). Por otra parte, no estoy seguro de si las funciones de almacenamiento de almacenamiento OpenCV opciones de almacenamiento sería más óptimo en cuanto a la memoria para los teléfonos Android, dado que el archivo xml sería demasiado grande para cargar.
  • Mi opción actual es optar por una base de datos sqlLite, tener una tabla con dos cols; Id y función (como se sugiere frecuentemente en línea); Para tabular todas las características de 16k en sqlLite. Esto parece bastante intensivo en el almacenamiento de teléfonos, pero es la solución más razonable que puedo encontrar.

¿Hay un método común para manejar vectores de características en teléfonos Android? ¿Abarca alguno de los métodos anteriores? Si no puede por favor ofrecer algunas pautas sobre cómo implementar tal solución de almacenamiento?

Gracias.

En mi opinión, la forma más universal de almacenar los puntos clave es primero convertirlos a un formato de intercambio de datos como JSON.

Después de que usted pueda hacer esa conversión usted tiene mucha flexibilidad para almacenarla. JSON se convierte fácilmente en una cadena y / o se envía a través de una conexión de red.

Con OpenCV C ++ puede almacenar datos como YAML , pero eso no está disponible para Android todavía.

Para analizar JSON en Java puede utilizar esta biblioteca fácil de usar Google GSON .

Y aquí está mi primer intento de hacer exactamente eso:

  public static String keypointsToJson(MatOfKeyPoint mat){ if(mat!=null && !mat.empty()){ Gson gson = new Gson(); JsonArray jsonArr = new JsonArray(); KeyPoint[] array = mat.toArray(); for(int i=0; i<array.length; i++){ KeyPoint kp = array[i]; JsonObject obj = new JsonObject(); obj.addProperty("class_id", kp.class_id); obj.addProperty("x", kp.pt.x); obj.addProperty("y", kp.pt.y); obj.addProperty("size", kp.size); obj.addProperty("angle", kp.angle); obj.addProperty("octave", kp.octave); obj.addProperty("response", kp.response); jsonArr.add(obj); } String json = gson.toJson(jsonArr); return json; } return "{}"; } public static MatOfKeyPoint keypointsFromJson(String json){ MatOfKeyPoint result = new MatOfKeyPoint(); JsonParser parser = new JsonParser(); JsonArray jsonArr = parser.parse(json).getAsJsonArray(); int size = jsonArr.size(); KeyPoint[] kpArray = new KeyPoint[size]; for(int i=0; i<size; i++){ KeyPoint kp = new KeyPoint(); JsonObject obj = (JsonObject) jsonArr.get(i); Point point = new Point( obj.get("x").getAsDouble(), obj.get("y").getAsDouble() ); kp.pt = point; kp.class_id = obj.get("class_id").getAsInt(); kp.size = obj.get("size").getAsFloat(); kp.angle = obj.get("angle").getAsFloat(); kp.octave = obj.get("octave").getAsInt(); kp.response = obj.get("response").getAsFloat(); kpArray[i] = kp; } result.fromArray(kpArray); return result; } 

Sugiero almacenar los vectores de características como imágenes para tener una representación simple y compacta. Incluso puede utilizar la compresión no destructiva, como png para minimizar el tamaño del archivo.

Veo que ha considerado utilizar la base de datos Android de SQLite:

Mi opción actual es optar por una base de datos sqlLite, tener una tabla con dos cols; Id y función (como se sugiere frecuentemente en línea); Para tabular todas las características de 16k en sqlLite. Esto parece bastante intensivo en el almacenamiento de teléfonos, pero es la solución más razonable que puedo encontrar.

Hay una manera de guardar y recuperar MatOfKeyPoint a la base de datos SQLite con una eficiencia razonable.

El uso de la base de datos tiene la ventaja de no necesitar solicitar el permiso de escritura de almacenamiento externo del usuario (aunque este permiso podría ser necesario para algunas otras de sus funciones de aplicaciones).

Hay una solución completa de Android, con código Java que se puede encontrar en esta respuesta StackOverflow .

Lo que sigue es una descripción de lo que está pasando en el código de esa respuesta …

MatOfKeyPoint a byte [] y algunos atributos

Para guardar en la base de datos, debe guardar en un objeto byte[] . Usando el método MatOfKeyPoint.get() , puede obtener un float[] poblado float[] . A continuación, utilizando ByteBuffer.putFloat() , puede realizar bucle a través de todos sus flotadores, finalmente obtener un byte[] poblado byte[] utilizando ByteBuffer.array() .

También es necesario guardar algunos atributos MatOfKeyPoint.rows() , MatOfKeyPoint.cols() y MatOfKeyPoint.type() a su base de datos, junto con el blob de byte[] .

Bloque de base de datos (byte []) a MatOfKeyPoint

Para reconstituir su objeto MatOfKeyPoint de la base de datos, primero debe hacer un float[] fuera de su blob. Utilice ByteBuffer.wrap(blob) , a continuación, ejecute ByteBuffer.asFloatBuffer() y, finalmente, FloatBuffer.get() con un nuevo float[] tamaño adecuado float[] .

Ahora que tiene yourFloatArray ejecuta MatOfKeyPoint.create(rows, cols, type) , esas tres cosas que vienen del registro de la base de datos. Finalmente ejecuta MatOfKeyPoint.put(0, 0, yourFloatArray) .

  • Obteniendo una imagen mediana de la secuencia de imágenes con OpenCV
  • Detección de objetos para android con tesseract o OpenCV
  • OpenCV instalador independiente opencv
  • Transformación de perspectiva
  • Reconocimiento de imágenes - Descriptor binario representación en Mat - OpenCV Android
  • Error de OpenCV / Android BufferQueue: La textura de la superficie ha sido abandonada
  • OpenCV obtiene píxeles negros dentro del límite del contorno
  • Configurar el modo de escena de la cámara para OpenCV en Android
  • Ejecución de la aplicación Android + Opencv + NDK en un dispositivo real
  • Android no puede cargar la imagen orientada correcta desde la galería
  • Cargando una imagen usando OpenCV en Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.