Does the Android OpenCV binary have data persistence functions? - android

I'd like to be able to persist matrices to disk. The c,c++ version of OpenCV supports with with the function cvWrite. I don't wee an equivalent function for the Android binary. Are there any other options?

In C/C++ you have the full API on all supported platforms:
XML/YAML Persistence
XML/YAML Persistence (C API)
Android Java API does not export the persistence API, but some classes provide Save/Load methods for their configurations.

Because OpenCV4Android does not yet have its own persistence, in my opinion the most universal way to store a Mat is to first convert it to a data-interchange format like 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.
With OpenCV C++ you are able to store data as YAML, but that is not available for Android yet like it was pointed by Andrey Kamaev. JSON here has the same purpose as YAML.
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 (I did a simple test and it worked, let me know if there are problems):
public static String matToJson(Mat mat){
JsonObject obj = new JsonObject();
if(mat.isContinuous()){
int cols = mat.cols();
int rows = mat.rows();
int elemSize = (int) mat.elemSize();
byte[] data = new byte[cols * rows * elemSize];
mat.get(0, 0, data);
obj.addProperty("rows", mat.rows());
obj.addProperty("cols", mat.cols());
obj.addProperty("type", mat.type());
// We cannot set binary data to a json object, so:
// Encoding data byte array to Base64.
String dataString = new String(Base64.encode(data, Base64.DEFAULT));
obj.addProperty("data", dataString);
Gson gson = new Gson();
String json = gson.toJson(obj);
return json;
} else {
Log.e(TAG, "Mat not continuous.");
}
return "{}";
}
public static Mat matFromJson(String json){
JsonParser parser = new JsonParser();
JsonObject JsonObject = parser.parse(json).getAsJsonObject();
int rows = JsonObject.get("rows").getAsInt();
int cols = JsonObject.get("cols").getAsInt();
int type = JsonObject.get("type").getAsInt();
String dataString = JsonObject.get("data").getAsString();
byte[] data = Base64.decode(dataString.getBytes(), Base64.DEFAULT);
Mat mat = new Mat(rows, cols, type);
mat.put(0, 0, data);
return mat;
}

Related

How to send ArrayList<ParcelableCustomObject> from Android Wear using the MessageAPI?

I have an ArrayList of parcelable custom items:
ArrayList<AudioLog> audioLogs = getAudioLogs();
I want to send this from the watch to the phone using the MessageAPI:
Wearable.MessageApi.sendMessage(googleClient, node.getId(), path, audioLogs).await();
BUT, I need to convert the entire ArrayList and its contents to a byte[], as the sendMessage method takes - (GoogleClient client, int id, String path, byte[] message).
To convert each of my parcelable AudioLog objects, I have a custom Util class that marshals and unmarshals each of them to a byte[]. I just need a similar class that can convert the whole ArrayList and its contents to a byte[] in the one go, if that's possible, thanks.
You should create a DataMap object, which can be converted into a byte array.
DataMap audioLogMap = new DataMap();
ArrayList<DataMap> audioLogArrayList = new ArrayList<>();
for (AudioLog audioLog: audioLogs) {
DataMap audioLogMap = new DataMap();
//TODO: copy something from audioLog to audioLogMap
audioLogArrayList.add(audioLogMap);
}
audioLogMap.putDataMapArrayList("key", audioLogArrayList);
byte[] audioLogByteArray = audioLogMap.toByteArray();

Parse nested object using GsonConverter with Retrofit2

I`m trying to convert the next JSON to object:
{
AccountName:"temnoi",
Parts:{
part-0:{
Name:"HOME",
UptimeSeconds:"2143943",
},
part-1:{
Name:"WORK",
UptimeSeconds:"2276958",
}
}
}
The problem is that Parts isn't an array so I don't have any idea how
to obtain them as List or any other data structure.
For now I have such DTO class
public class Info {
private String AccountName;
private List<Parts> Parts;
}
But obviously program crash as there are no array. I use Retrofit2 with GsonConverter.
Can anyone suggest something to solve this problem?
Unfortunately, as I don't have a lot of time, I came with the next solution.
I replace Retrofit2 by OkHTTP and Gson with built-in JSON parser.
After I get a response with OkHttpClient I manually convert JSON to my object.
JSONObject root = new JSONObject(responseFromServer);
JSONObject parts = root.getJSONObject("Parts");
Iterator<String> jsonPartsIterator = parts.keys();
List<Part> partsList = new ArrayList<>();
while (jsonPartsIterator.hasNext()) {
try{
String key = jsonRootIterator.next();
partsList.add(convertPartJsonToObject(computers.getJSONObject(key)));
} catch(Exception e){
// in case if there will be number '0' return empty List
}
}
Here Part convertPartJsonToObject(JSONObject object) is method to convert part-0, part-1... to object which I need.

How to compress Ti.utils.base64encode and decompress using .Net method?

Does anyone know how to compress Ti.Utils.base64encode??
for example i have this code :
uploadFile = Ti.Filesystem.getFile(pathFile, listing[_fileCtr].toString());
uploadFileName = listing[_fileCtr].toString();
encodedFile = Ti.Utils.base64encode(uploadFile.read()).toString();
//Send Image to .NET web service
And this is the method in my web services for decompressing image from titanium (if i can compress my image before):
static byte[] Decompress(byte[] input)
{
using (MemoryStream output = new MemoryStream(input))
{
using (GZipStream zip = new GZipStream(output, CompressionMode.Decompress))
{
List<byte> bytes = new List<byte>();
int b = zip.ReadByte();
while (b != -1)
{
bytes.Add((byte)b);
b = zip.ReadByte();
}
return bytes.ToArray();
}
}
Until now, i can't find some method for compressing my byte array so i can decompress them using my .NET method..
If u guys have any information about my problem, please tell me..
Many thanks.. :)
In .Net you can use System.Convert.FromBase64String to converts the specified string, which encodes binary data as base-64 digits, to an equivalent 8-bit unsigned integer array.
System.Convert.FromBase64String(encodedString);

Approach to serialize cloud endpoint model class to Android file system

I have successfully created a cloud endpoint model that allows for easy retrieval of information from App Engine. To reduce the roundtrips and provide a faster user experience, I have identified one instance I wish to store to local storage.
Throughout the rest of my app, I am using ObjectInputStream to read and write the objects such as:
FileInputStream fis = context.openFileInput("PRIVFILE");
ObjectInputStream ois = new ObjectInputStream(fis);
AppModelState s = (AppModelState) ois.readObject();
This obviously requires all data members to implement the Serializable interface. The Model class extends GenericJSON and is not "Serializable", as
public final class ModelClass extends GenericJson {}
I could manually create a serializable object that maps to the model; however, that seems very amateur due to the number of attributes.
The other alternative I considered was creating a Serializable Object wrapper that simply has the JSON string as a member and provides a setter/getter accepting the ModelClass as parameters, such as:
class AppModelState implements Serializable {
private String modelClassJSON;
public ModelClass getModelClass() {
// generate a new ModelClass from the JSON
}
public void setModelClass(ModelClass c) {
// extract the JSON for storage
}
.....
}
I feel like there must be a better way and this should have been solved a dozen times but I am not finding any resources. Please provide input.
I'm doing exactly the same as you say in your question.
Since Cloud Endpoints objects are already serialized for transmit over the wire, they are also serializable to be stored locally. As an added bonus, with Android 3.0 or later, you don't even need to import any libraries -- it's already there! For example:
import com.google.api.client.extensions.android.json.AndroidJsonFactory;
import com.google.api.client.json.GenericJson;
import com.google.api.client.json.JsonFactory;
private static final JsonFactory JSON_FACTORY = new AndroidJsonFactory();
public void putObject(String key, Object value) throws Exception {
byte[] outputbytes = null;
if (value instanceof GenericJson) {
outputbytes = JSON_FACTORY.toByteArray(value);
} else {
ByteArrayOutputStream output = new ByteArrayOutputStream();
ObjectOutputStream objectstream = new ObjectOutputStream(output);
objectstream.writeObject(value);
objectstream.close();
outputbytes = output.toByteArray();
}
// persist "outputbytes" ...
}
public <T> T getObject(String key, Class<T> outclass) throws Exception {
// retrieve saved bytes...
byte[] valuebytes = ...
if (valuebytes[0] == '{' && valuebytes[1] == '"' && valuebytes[valuebytes.length-1] == '}') {
// Looks like JSON...
return JSON_FACTORY.fromString(new String(valuebytes, "UTF-8"), outclass);
} else {
ByteArrayInputStream input = new ByteArrayInputStream(valuebytes);
ObjectInputStream objectstream = new ObjectInputStream(input);
Object value = objectstream.readObject();
objectstream.close();
return outclass.cast(value);
}
}
Note that the default AndroidJsonFactory (as of Android v4.3, anyway) is quite slow when serializing long strings. Create a new JacksonFactory instead if you have performance problems. Everything else stays the same.
Update: If you want to serialize a list of GenericJson objects, you just have to create a GenericJson object that includes a list of those objects. For example:
import com.google.api.client.json.GenericJson;
import com.google.api.client.util.Key;
public static class PersistantJson extends GenericJson {
#Key public int one;
#Key public String two;
}
public static class PersistantJsonList extends GenericJson {
#Key public List<PersistantJson> list = new ArrayList<PersistantJson>();
}
You can now add all your PersistantJson (i.e. some class created by "generate cloud endpoint client library") objects to the .list element of a PersistantJsonList variable and then pass that variable to putObject(). Note that this requires all objects in the list to be of the same class so that deserialization knows what the type is (because JSON serialization does not record the type). If you use List<Object> then what is read back is a List<Map<String, Object>> and you have to extract the fields manually.
I think that doing standard Java serialization of classes that will be used with Endpoints doesn't work very well. The problem is that serialization is binary, and HTTP comm is string.
If you were doing the HTTP comm yourself, rather then using endpoints, I think you would have the same problem. In order to send the object you would serialize it (converting an string members to binary) and then you would have to convert the binary back to string.
So, if the amount of data you are using is not too much, it would probably be easiest to store your objects as JSON.

how to return a list from servlet to my android application

There are some pdf files in my d drive.In my android application I have to return the list of files from a servlet to my activity class,but through my codes it is returning the name of all files as a string.But i need each name separetly.How to do that,
You a using HTTP to pass data from your servlet to your Android application. HTTP doesn't care about the content of the response, so there is no standard way of defining the structure of the data you are passing. You are pretty much free to do as you please.
One option therefore would be to put your filenames into a comma-separated list in the servlet. In your Android application you chop the String apart into an array of Strings each representing one file name:
String[] filenames;
filenames = responseString.split(",");
That's the easy way. You could also create XML from your filenames in your servlet, and parse the XML in your Android application. That would look nicer, but it is more work.
Use JSONObject
JSONObject jsEmployeeObj = new JSONObject();
JSONArray empArray = new JSONArray();
while (condition) {
JSONObject jsObject = new JSONObject();
jsObject.accumulate("name", res.getString("name"));
empArray.add(jsObject);
}
if ((empArray != null) && (empArray.size() > 0)) {
jsEmployeeObj.accumulate("employeeList", empArray);
} else {
jsEmployeeObj.accumulate("employeeList", "empty");
}
String output = jsEmployeeObj.toString();
return the string ... u can parse JSON in android

Categories

Resources