我有图像的训练集,其中的每一个我已经发现并计算它们的特征向量(ORB使用特征描述信息和提取的问题是 :因为我需要保存这些功能reutilise他们针对测试图像匹配(使用SVM分类); 什么是本地存储的特征向量,在Android设备上的最佳方式是什么?
要保存的特征向量是每幅图像的可变大小的,并且因此那些具有非最大尺寸用零填充到统一所有矢量尺寸。 最大尺寸目前是500行×32周的cols; 因此16K功能。
这里是我到目前为止达到的选项;
- 我听说过的OpenCV的的FileStorage ,而是通过Java文档去的时候,我注意到一个
save
的方法, HOG特征 (不ORB)。 此外,我不知道,如果使用的OpenCV的文件存储选项节电功能将是最优化的内存明智的Android手机,因为XML文件是太大,无法加载。 - 我现在的选择是选择一个sqlLite数据库,具有带两个的cols表; ID和特征(如经常在网上建议); 制表所有sqlLite的16K功能。 这似乎有些手机的存储密集型的,但它是最合理的解决方案,我可以找到。
有没有在Android手机上处理特征向量的常用方法? 它是否包含任何的上述方法; 如果不是可以请你提供如何实现这样的存储解决方案的一些准则?
谢谢。
在我看来,以存储关键点的最普遍的方式是,首先将它们转换为像JSON数据交换格式。
你能做到这一点的转换之后,你有很大的灵活性来存放它。 JSON容易转换为字符串和/或通过网络连接发送。
随着OpenCV的C ++ 您可以将数据存储为YAML ,但不适用于Android的呢。
解析JSON在Java中,你可以使用这个易于使用的库谷歌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;
}
我建议存储的特征向量的图像有一个简单和紧凑表示。 你甚至可以使用无损压缩,如PNG,以尽量减少文件大小。
我看到你使用Android SQLite数据库考虑:
我现在的选择是选择一个sqlLite数据库,具有带两个的cols表; ID和特征(如经常在网上建议); 制表所有sqlLite的16K功能。 这似乎有些手机的存储密集型的,但它是最合理的解决方案,我可以找到。
有一种方法来保存和检索MatOfKeyPoint
以合理的效率SQLite数据库。
使用数据库具有不需要请求从用户写外部存储许可(尽管可能需要一些其他的你的应用程序功能的许可)的优势。
有一个完整的Android解决方案,与Java代码中可以找到这个答案StackOverflow上 。
以下是从这个问题的答案代码是怎么回事的介绍...
MatOfKeyPoint为byte []和一些属性
要保存到数据库中,你需要保存到一个byte[]
对象。 使用MatOfKeyPoint.get()
方法,你可以得到一个人口float[]
然后使用ByteBuffer.putFloat()
你可以通过你所有的花车的循环,终于得到一个人口稠密byte[]
通过ByteBuffer.array()
您还需要保存一些attirbutes MatOfKeyPoint.rows()
MatOfKeyPoint.cols()
和MatOfKeyPoint.type()
到你的数据库,与沿blob
的byte[]
数据库团块(字节[])来MatOfKeyPoint
要重建你的MatOfKeyPoint
从数据库对象,首先你犯了一个float[]
你的斑点。 使用ByteBuffer.wrap(blob)
然后运行ByteBuffer.asFloatBuffer()
最后FloatBuffer.get()
用适当大小的新float[]
现在,你有yourFloatArray
运行MatOfKeyPoint.create(rows, cols, type)
,这三样东西从数据库中记录的到来。 最后,你运行MatOfKeyPoint.put(0, 0, yourFloatArray)