[英]Saving ORB feature vectors using OpenCV4Android (java API)
我有一組訓練有素的圖像,我已經針對每個圖像檢測並計算了它們的特征向量(使用ORB特征描述符和提取器。 問題是 :由於我需要保存這些特征以重新使用它們以與測試圖像進行匹配(使用SVM分類器); 在Android設備上本地存儲特征向量的最佳方法是什么?
要保存的特征向量每個圖像的大小都是可變的,因此,對於非最大大小的特征向量,將其填充零以統一所有向量的大小。 當前最大大小為500行x 32列; 因此具有16k的功能。
到目前為止,這是我可以達到的選擇;
save
方法。 此外,由於xml文件太大而無法加載,因此我不確定使用OpenCV的文件存儲選項保存功能對於Android手機而言是否是最佳內存。 有沒有通用的方法來處理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中找到。
以下是該答案中代碼中所發生情況的描述...
要保存到數據庫,您需要保存到byte[]
對象。 使用MatOfKeyPoint.get()
方法,可以獲得填充的float[]
。 然后使用ByteBuffer.putFloat()
,可以遍歷所有浮點數,最后使用ByteBuffer.array()
獲得填充的byte[]
。
您還需要將一些屬性MatOfKeyPoint.rows()
, MatOfKeyPoint.cols()
和MatOfKeyPoint.type()
以及byte[]
的blob
到數據庫中。
要從數據庫中重構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.