保存使用OpenCV4Android ORB特征向量(的Java API)向量、特征、ORB、OpenCV4Android

2023-09-06 09:39:55 作者:slow(慢热)

我有图像的训练集,每个我已经detected和computed 。他们的特征向量(使用ORB特征描述和提取的的问题是:因为我需要保存这些功能reutilise他们匹配对测试图像(使用SVM分类); 什么是最好的的方式来存储的特征向量,在本地Android设备上?

I have a training set of images, for each of which I've detected and computed their feature vectors (using ORB feature descriptors and extractors. The questions is: since I need to save those features to reutilise them for matching against test images (using SVM classifier); what is the best way to store the feature vectors, locally on the Android device?

要保存的特征向量是每幅图像大小可变的,并因此与那些非最大尺寸的补零统一所有矢量'大小。最大容量目前为500行×32 COLS;因此16K功能。

The feature vectors to be saved are of variable size per image, and are thus those with non-maximal sizes are padded with zeros to unify all vectors' sizes. The maximum size currently is 500 rows x 32 cols; thus 16k features.

下面是我能达到目前的选项;

here are the options I could reach so far;

我听说过的OpenCV的FileStorage,而是通过Java文档去的时候,我注意到一个保存方法HOG功能(不ORB)。此外,我不知道,如果使用的OpenCV的文件存储选项存储功能将是最优化的内存明智的Andr​​oid手机,因为XML文件是太大,无法加载。 在我目前的选择是选择一个sqlLite数据库,有两个COLS表; ID和特征(如经常在网上建议);能够制作sqlLite所有16K功能。这似乎相当的手机存储密集型的,但它是最合理的解决方案,我可以找到。 I've heard of OpenCV's FileStorage, but when going through the java documentation, I noticed a save method for HOG features (not ORB). Furthermore, I'm not sure if saving features using OpenCV's file storage options would be most optimal memory-wise for Android phones, given that the xml file would be too large to load. My current choice is to opt for a sqlLite database, having a table with two cols; id and feature (as frequently suggested online); to tabulate all the 16k features in sqlLite. That seems rather phone-storage intensive, but it's the most reasonable solution I can find.

有一个共同的方法来处理特征向量的Andr​​oid手机?它包括任何一种上述方法;如果不是可以请你就如何实现这样的存储解决方案的一些准则?

Is there a common method to handling feature vectors on Android phones? Does it encompass any of the above methods; if not can you please offer some guidelines on how to implement such a storage solution?

感谢您。

推荐答案

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

In my opinion the most universal way to store the keypoints is to first convert them to a data-interchange format like JSON.

在你能够做到这一点的转换有很大的灵活性来储存。 JSON是很容易通过网络连接转换为字符串和/或发送。

After you are able to do that conversion you have a lot of flexibility to store it. JSON is easily converted to a String and/or sent through a network connection.

使用OpenCV的C ++ 你是能够存储数据YAML ,但事实并非可用于Android呢。

With OpenCV C++ you are able to store data as YAML, but that is not available for Android yet.

要解析JSON在Java中,你可以使用这个简单易用库谷歌GSON 。

To parse JSON in Java you can use this easy to use library Google GSON.

这里是我第一次尝试这样做正是:

And here is my first attempt to do exactly that:

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