使用OpenCV4Android(java API)保存ORB特征向量

我有一组训练图像,我已经检测并计算了它们的每一个特征向量(使用ORB特征描述符和提取器)。 问题是 :因为我需要保存这些特征以重新使用它们来匹配testing图像(使用SVM分类器); 在Android设备上本地存储特征向量的最佳方式是什么?

要保存的特征向量是每个图像可变的大小,并且因此具有非最大大小的特征向量被填充为零以统一所有向量的大小。 目前的最大尺寸是500行×32列; 从而16kfunction。

以下是我可以达到的选项;

  • 我听说过OpenCV的FileStorage ,但是在阅读java文档时,我注意到了HOG特性 (不是ORB)的save方法。 此外,我不确定使用OpenCV的文件存储选项保存function是否是Android手机的最佳记忆方式,因为xml文件太大而无法加载。
  • 我目前的select是select一个sqlLite数据库,有一个两列的表; id和function(经常在网上build议); 将sqlLite中的所有16kfunction列表。 这似乎相当电话存储密集型,但这是我能find的最合理的解决scheme。

有没有一种常见的方法来处理Android手机上的特征向量? 它是否包含上述任何一种方法? 如果不能,请提供一些关于如何实施这样的存储解决scheme的指导方针?

谢谢。

Related of "使用OpenCV4Android(java API)保存ORB特征向量"

在我看来,存储关键点的最普遍的方法是首先将它们转换为像JSON这样的数据交换格式。

在您完成转换之后,您可以灵活地存储它。 JSON很容易转换为string和/或通过networking连接发送。

使用OpenCV C ++, 您可以将数据存储为YAML ,但尚不适用于Android。

要parsingJava中的JSON,你可以使用这个易于使用的谷歌GSON 。

这是我第一次尝试做到这一点:

  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; } 

我build议将特征向量存储为图像以具有简单和紧凑的表示。 你甚至可以使用非破坏性的压缩,如PNG最小化文件大小。

我看到你已经考虑使用Android SQLite数据库:

我目前的select是select一个sqlLite数据库,有一个两列的表; id和function(经常在网上build议); 将sqlLite中的所有16kfunction列表。 这似乎相当电话存储密集型,但这是我能find的最合理的解决scheme。

有一种方法可以将MatOfKeyPoint以合理的效率保存到SQLite数据库中。

使用数据库的优点是无需向用户请求写入外部存储权限(尽pipe您的某些其他应用程序function可能需要该权限)。

有一个完整的Android解决scheme,Java代码可以在这个StackOverflow答案中find。

以下是对该答案的代码中发生了什么的描述…

MatOfKeyPoint到byte []和一些属性

要保存到数据库,您需要保存到一个byte[]对象。 使用MatOfKeyPoint.get()方法,你可以得到一个填充的float[] 。 然后使用ByteBuffer.putFloat() ,你可以遍历所有的浮点数,最后通过使用ByteBuffer.array()得到一个填充的byte[]

您还需要将一些attirbutes MatOfKeyPoint.rows()MatOfKeyPoint.cols()MatOfKeyPoint.type()byte[]blob一起保存到数据库。

数据库blob(byte [])到MatOfKeyPoint

为了从数据库中重构你的MatOfKeyPoint对象,首先你需要在blob中创build一个float[] 。 使用ByteBuffer.wrap(blob) ,然后运行ByteBuffer.asFloatBuffer() ,最后使用适当大小的新float[]运行FloatBuffer.get()

现在你有了你的MatOfKeyPoint.create(rows, cols, type) yourFloatArray你可以运行MatOfKeyPoint.create(rows, cols, type) ,这三件事来自数据库logging。 最后你运行MatOfKeyPoint.put(0, 0, yourFloatArray)