簡體   English   中英

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

[英]Saving ORB feature vectors using OpenCV4Android (java API)

我有一組訓練有素的圖像,我已經針對每個圖像檢測計算了它們的特征向量(使用ORB特征描述符和提取器。 問題是 :由於我需要保存這些特征以重新使用它們以與測試圖像進​​行匹配(使用SVM分類器); 在Android設備上本地存儲特征向量的最佳方法是什么?

要保存的特征向量每個圖像的大小都是可變的,因此,對於非最大大小的特征向量,將其填充零以統一所有向量的大小。 當前最大大小為500行x 32列; 因此具有16k的功能。

到目前為止,這是我可以達到的選擇;

  • 我聽說過OpenCV的FileStorage ,但是在閱讀Java文檔時,我注意到了HOG功能 (不是ORB)的save方法。 此外,由於xml文件太大而無法加載,因此我不確定使用OpenCV的文件存儲選項保存功能對於Android手機而言是否是最佳內存。
  • 我當前的選擇是選擇一個sqlLite數據庫,該數據庫的表包含兩個cols。 ID和功能(網上經常建議); 列出sqlLite中的所有16k功能。 這似乎需要大量的電話存儲,但這是我能找到的最合理的解決方案。

有沒有通用的方法來處理Android手機上的特征向量? 是否包括上述任何方法? 如果不能,請提供一些有關如何實施這種存儲解決方案的指南?

謝謝。

在我看來,存儲關鍵點的最通用的方法是先將它們轉換為數據交換格式,例如JSON。

在完成該轉換之后,您將可以靈活地存儲它。 JSON可以輕松轉換為String和/或通過網絡連接發送。

使用OpenCV C ++, 您可以將數據存儲為YAML ,但是尚不適用於Android。

要解析Java中的JSON,您可以使用這個易於使用的Google 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 Answer中找到。

以下是該答案中代碼中所發生情況的描述...

MatOfKeyPoint指向byte []和一些屬性

要保存到數據庫,您需要保存到byte[]對象。 使用MatOfKeyPoint.get()方法,可以獲得填充的float[] 然后使用ByteBuffer.putFloat() ,可以遍歷所有浮點數,最后使用ByteBuffer.array()獲得填充的byte[]

您還需要將一些屬性MatOfKeyPoint.rows()MatOfKeyPoint.cols()MatOfKeyPoint.type()以及byte[]blob到數據庫中。

數據庫blob(byte [])到MatOfKeyPoint

要從數據庫中重構MatOfKeyPoint對象,請首先從blob中創建一個float[] 使用ByteBuffer.wrap(blob) ,然后運行ByteBuffer.asFloatBuffer() ,最后運行帶有適當大小的新float[] FloatBuffer.get()

現在您有了yourFloatArray您可以運行MatOfKeyPoint.create(rows, cols, type) ,這三件事來自數據庫記錄。 最后,您運行MatOfKeyPoint.put(0, 0, yourFloatArray)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM