Reputation: 351
I want to store a descriptor matrix generated by a random OpenCV descriptor extractor as a database entity.
Assuming desc is the descriptor Matrix
String s = (desc.reshape(1,1)).dump;
To get the matrix back from the database, I did
Mat desc = new Mat(numberOfRows * numberOfCols * numberOfChannels, 1, type);
/* I stored number of rows and number of cols and type of the matrix separately and pass them to the function that returns the matrix */
String ss[] = s.substring(1, s.length -1).split(", ");
int[] temp = new int[sss.length ];
for(int i = 0; i < sss.length; i++) temp [i] = Integer.parseInt(sss[i]);
MatOfInt int_values = new MatOfInt(temp);
int_values.convertTo(desc, type);
desc = fingerprint.desc(numberOfChannels, numberOfRows);
This works fine but takes a lot of time, especially the .split method and the loop involving parseInt due to the large number of elements in the matrix (about 100k in my case).
My question is: is there a better way to do this?
my second question is, come on, assigning a 100K long string array and parsing it (given the fact that the strings are actually 2-3 characters at most) shouldn't really take 2 seconds, is it because Android/Java is slow
Upvotes: 2
Views: 4121
Reputation: 351
Ok, I found a solution a bit similar to Berak as Kiran mentioned. My attempt is a bit less general but works fine for descriptor matrices, is fast and does not involve jni.
// for writing
MatOfByte bytes = new MatOfByte(desc.reshape(1, nrows * ncols * nchannels));
byte[] bytes_ = bytes.toArray();
String s = Base64.encodeToString(bytes_, Base64.DEFAULT);
// for reading
byte[] bytes_ = Base64.decode(s, Base64.DEFAULT);
MatOfByte bytes = new MatOfByte(bytes_);
Mat desc = new Mat(nrows * ncols * nchannels, 1, type);
bytes.convertTo(desc, type);
desc = desc.reshape(nchannels, nrows);
Upvotes: 1
Reputation: 11221
OpenCV provides FileStorage
class for persistence as in link. Basically the Mat
image could be saved as XML/YAML file from which we could read later. A simple example will be as below.
//for writing
cv::FileStorage store(“save.yml", cv::FileStorage::WRITE);
store << “mat” << img;
store.release();
//for reading
cv::FileStorage store(“save.yml", cv::FileStorage::READ);
store[“mat”] >> img;
store.release();
But we don't have FileStorage
java wrapper in Android. Alternative could be invoking above code over JNI as in this example or even better - check Berak's sample.
Upvotes: 3