节约使用OpenCV4Android ORB特征向量(JAVA的API)(Saving ORB fe

2019-07-21 04:01发布

我有图像的训练集,其中的每一个我已经发现并计算它们的特征向量(ORB使用特征描述信息和提取的问题是 :因为我需要保存这些功能reutilise他们针对测试图像匹配(使用SVM分类); 什么是本地存储的特征向量,在Android设备上的最佳方式是什么?

要保存的特征向量是每幅图像的可变大小的,并且因此那些具有非最大尺寸用零填充到统一所有矢量尺寸。 最大尺寸目前是500行×32周的cols; 因此16K功能。

这里是我到目前为止达到的选项;

  • 我听说过的OpenCV的的FileStorage ,而是通过Java文档去的时候,我注意到一个save的方法, HOG特征 (不ORB)。 此外,我不知道,如果使用的OpenCV的文件存储选项节电功能将是最优化的内存明智的Android手机,因为XML文件是太大,无法加载。
  • 我现在的选择是选择一个sqlLite数据库,具有带两个的cols表; ID和特征(如经常在网上建议); 制表所有sqlLite的16K功能。 这似乎有些手机的存储密集型的,但它是最合理的解决方案,我可以找到。

有没有在Android手机上处理特征向量的常用方法? 它是否包含任何的上述方法; 如果不是可以请你提供如何实现这样的存储解决方案的一些准则?

谢谢。

Answer 1:

在我看来,以存储关键点的最普遍的方式是,首先将它们转换为像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;
}


Answer 2:

我建议存储的特征向量的图像有一个简单和紧凑表示。 你甚至可以使用无损压缩,如PNG,以尽量减少文件大小。



Answer 3:

我看到你使用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()到你的数据库,与沿blobbyte[]

数据库团块(字节[])来MatOfKeyPoint

要重建你的MatOfKeyPoint从数据库对象,首先你犯了一个float[]你的斑点。 使用ByteBuffer.wrap(blob)然后运行ByteBuffer.asFloatBuffer()最后FloatBuffer.get()用适当大小的新float[]

现在,你有yourFloatArray运行MatOfKeyPoint.create(rows, cols, type) ,这三样东西从数据库中记录的到来。 最后,你运行MatOfKeyPoint.put(0, 0, yourFloatArray)



文章来源: Saving ORB feature vectors using OpenCV4Android (java API)