TfLite Android: Garbage values when running inference for multiple output model - android

I have a model that predicts the age and gender of the input image of size 160X160. I am creating a byte buffer to input the image to the model and everything works just fine when using a model with only one output.
But when I am using the tflite.runForMultipleInputsOutputs(), I am getting garbage values which are of the form -> [[F#e233 etc.
I have followed the documentation and the sample apps to the detail and have been stuck at this for almost 2 days. Please help.
I am posting my code below for reference.
The model has 2 outputs:
Edit:
age -> float32 [1, 101]
gender -> float32 [1,2]
P.S - I am not doing anything with the output as of now. I just want to see the result of the model.
String classifyImage(Bitmap bitmap){
try{
ByteBuffer byteBuffer = convertBitmaptoByteBuffer(bitmap);
float[][] out_gender = new float[1][2];
float[][] out_age = new float[1][101];
Object[] input = {byteBuffer};
Map<Integer, Object> outputs = new HashMap();
outputs.put(0, out_age);
outputs.put(1, out_gender);
interpreter.runForMultipleInputsOutputs(input, outputs);
}catch (Exception e){
e.printStackTrace();
}
return "";
}

First, I would suggest that you double-check that the outputs from your model match your output map. It seems strange to me that the gender would be a 101-dimensional array and the age a 2-dimensional one. Have you by any chance mixed those up?
Secondly, I think you are calling toString() on the float arrays. Consider using e.g. System.out.println(Arrays.deepToString(out_age)); to present the result.

Related

Convert Array list to Sparse Array

I have copied some code from a project and want to reuse a small part of it in my private app.
The class contains a Sparse Array
public class GolfResult {
String hcpAfter;
String hcpBefore;
SparseArray roundResults;
public GolfResult() {
hcpAfter = "";
hcpBefore = "";
roundResults = new SparseArray();
}
}
I have created an ArrayList for roundResults that is filled with the necessary data.
Then I am trying to fill the instance with content.
GolfResult golferRes = new GolfResult();
SparseArray<RoundResults> hu= new SparseArray<>();
hu = roundresults; // *
golferRes.setHcpAfter("33");
golferRes.setHcpBefore("kk");
golferRes.setRoundResults(hu);
But the problem is that hu = roudresults is not possible, because of the error message:
required: Android.util.SparseArray found: java.util.Array List
Any help will be welcome.
After receiving two helpful answers I got a step further, but now I am facing the problem that my SparseArray hu is empty {}.
The content of hu should be the class roundresults that has the following structure:
public class RoundResults {
boolean actualRound;
private List<HoleResult> holeResults;
Integer roundId;
Integer roundNumber;
String unfinishedReason;
The arrayList roundresults has the size of 1 and has data in the objects.
unfinishedReason =""
holeResults = ArrayLIST size= 18
roundID = "1"
roundNumber = "1"
actualRound = true
hu ={}
mValues = All elements are null
mSize = 0
Does anybody have an idea why?
SparseArray is different than ArrayList, from the documentation:
SparseArrays map integers to Objects. Unlike a normal array of
Objects, there can be gaps in the indices. It is intended to be more
memory efficient than using a HashMap to map Integers to Objects, both
because it avoids auto-boxing keys and its data structure doesn't rely
on an extra entry object for each mapping.
It's using a key value pair principle where the key is an integer and the value which the key mapping is the object. You need to use put [(int key, E value)](https://developer.android.com/reference/android/util/SparseArray.html#put(int, E)) where the E is your object. Remember that:
Adds a mapping from the specified key to the specified value,
replacing the previous mapping from the specified key if there was
one.
So you need to use a loop to add each object in your ArrayList as #valentino-s says:
SparseArray<RoundResults> hu= new SparseArray<>();
for( int i = 0; i < roundresults.size(); i++) {
// i as the key for the object.
hu.put(i, roundresults.get(i));
}
If I understand well your problem, maybe you can try with this:
for ( int i=0; i<roundresults.size(); i++ ) {
hu.put(i,roundresults.get(i));
}
After some trial and error I found a solution for the empty hu:
Instead of put I used append and it is working now.
hu.append(i, roundresults.get(i));
Time for a beer.

Ormlite RawRowMapper truncated double

I am using RawRowMapper to load relevant columns from ormlite. RawRowMapper returns all data as String.
The observation is that it truncates the double value.
Example:
Data inserted -> 57.1117146374
Data type used to store the data -> Double
Data from Ormlite when directly queried: -> 57.1117146374 (This is correct and essentially means that ormlite is actually storing the data correctly)
Data from Ormlite when using mapper -> 57.1117 (Truncated data coming as part of String[] resultColumns
Any idea how do I avoid it getting truncated?
EDIT:
#DatabaseField(columnName = "LAT")
private Double lat;
Object Field:
private double lat;
The key here is that the string in resultcolumns[], I get is already truncated.
Data from Ormlite when using mapper -> 57.1117 (Truncated data coming as part of String[] resultColumns
The problem seems to be that getting a double value out as a String is truncated by Android's cursor.getString(...) method. Not sure why but if the result is extracted by using cursor.getDouble(columnIndex); on the same column-index, the full precision is preserved.
The solution here I believe is to map the rows differently. If you use dao.queryRaw(String, DataType[], ...) method, the double field seems to be extracted appropriately. Here's a sample from my test class.
GenericRawResults<Object[]> results =
dao.queryRaw(dao.queryBuilder().selectColumns("lat")
.prepareStatementString(), new DataType[] { DataType.DOUBLE });
CloseableIterator<Object[]> iterator = results.closeableIterator();
try {
assertTrue(iterator.hasNext());
Object[] objs = iterator.next();
assertEquals(foo.doubleField, objs[0]);
} finally {
iterator.close();
}
You could also use a custom row mapper and the dao.queryRaw(String, RawRowMapper, ...) method to convert and return a custom object with a double field.

Allow all characters in Android app

I am helping to develop an app for Android that uses special characters from different parts of the world at times, specifically when listing the names of people. So, a good example would be a Spanish or Swedish accent on a name. The app is not rendering these correctly. What do I need to add to web services so that these accent marks show correctly? They show correctly in my database, but not in the app.
Here is an example:
http://docs.oracle.com/javase/tutorial/i18n/text/string.html
String original;
original = new String("A" + "\u00ea" + "\u00f1" + "\u00fc" + "C");
When printed, the String named original appears as:
AêñüC
To convert the String object to UTF-8, invoke the getBytes
method and specify the appropriate encoding as a parameter.
The getBytes method returns an array of bytes in UTF-8 format. To
create a String object from an array of non-Unicode bytes, invoke the
String constructor with the encoding parameter. The code that makes
these calls is enclosed in a try block, in case the specified encoding
is unsupported:
try {
byte[] utf8Bytes = original.getBytes("UTF8");
byte[] defaultBytes = original.getBytes();
String roundTrip = new String(utf8Bytes, "UTF8");
System.out.println("roundTrip = " + roundTrip);
System.out.println();
printBytes(utf8Bytes, "utf8Bytes");
System.out.println();
printBytes(defaultBytes, "defaultBytes");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
The StringConverter program prints out the values in the utf8Bytes and defaultBytes arrays to demonstrate an
important point: The length of the converted text might not be the
same as the length of the source text. Some Unicode characters
translate into single bytes, others into pairs or triplets of bytes.

How to retrieve data from ArrayList<ModelObject> not from ArrayList<String>?

Hi I'm still new to java data management.
I have a model object class named Computer which has 3 fields: processor, ram, hddSize.
I created a ArrayList
ArrayList<Computer> myCompList = new ArrayList<Computer>();
Computer comp1 = new Computer();
comp1.setProcessor("1.5 GHZ");
comp1.setRam("512 MB");
comp1.setHddSize("100 GB");
Computer comp2 = new Computer();
comp2.setProcessor("2.5 GHZ");
comp2.setRam("512 MB");
comp2.setHddSize("50 GB");
myCompList.add(comp1);
myCompList.add(comp2);
Now How can I retrieve data at index1 of the ArrayList above?
PS: I know how to do it if its a ArrayList< String> by convert it to String[] and then String[index].
Look at the Javadocs for ArrayList
This is where you should check for simple questions like this. The answer can be found in the "Method Summary" section.
Assuming that you have created getters and setters in your Computer class:
String processor = myCompList.get(1).getProcessor();
String ram = myCompList.get(1).getRam();
String hddSize = myCompList.get(1).getHddSize();
Can't you just go myCompList.get(0); ?
An arraylist of objects is essentially the same as an arraylist of strings. The .get() method returns the specific object at the given index. Here is the documentation for ArrayList.
myCompList.get(index) will return you data on the given index, make sure index number wouldn't be greater than array size, it will give you index out of bounds exception.

Reading a textfile database and displaying the results

I have a database thats in the form of a text file, my job is to parse the txt file and display the data in a listview. I have no idea where to start.
Heres an example entry.
"|9251115|,|0|,|DETAILS|,||,||,|Heading Price Text Text |,||,||
Where each || represents a field. There are also html tags between heading price and the text (p,b)
My first idea would be to parse it similarly to an xml document, i.e have it create a new line where it starts with a "|", fill it with everything in between and end the line when it reaches the next "|". But I still have no concrete idea on how to do this.
EDIT:
Taking it one step at a time for now. Using stringtokenizer to read it line by line and remove "," for a start. Ran into a problem, the textview to display the results is displaying false for some reason instead of the scanned text. here's my code if anyone needs a good headscratcher.
Context myContext;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView t = (TextView) findViewById(R.id.text);
st = new ArrayList<property>();
try
{
InputStream is;
is = myContext.getAssets().open("rooms.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(is,"UTF-8"));
String read = br.readLine();
while( read != null)
{
StringTokenizer st = new StringTokenizer(read,",");
{
while(st.hasMoreTokens())
{
String a = st.nextToken();
String b = st.nextToken();
String c = st.nextToken();
String d = st.nextToken();
String e = st.nextToken();
String f = st.nextToken();
String g = st.nextToken();
String h = st.nextToken();
t.setText(a+" "+b+" "+c+" "+d+" "+e+" "+f+" "+g+" "+h);
}
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
While you can definitely implement your own parser using pure Java code, you should consider using a SQLite database (1) to store your data, which will allow you to insert, delete, modify and query much more easily.
If you database comes in that format from an external source, I'd write a one-time parser that parses the data and inserts it into the SQLite database for future use.
Remember that the CPU on Android devices is slower than your average PC CPU, so if you are parsing large amounts of data in this format all the time, your app might become very slow. Hence my suggestion of converting it to a database.
Another option you have in this case is using XML like you said, because there are ready-to-use parsers out there. But the advice about performance remains: you should really avoid reparsing the data all the time and, instead, store it in a ready-to-use format.
(1): http://developer.android.com/reference/android/database/sqlite/package-summary.html
Here is how I would do,
Have an object with getter/setter
Have a list intialized
1) You need to use StreamReaders/Bufferedreader to read the file
2) If each is not empty
2a) Use StringTokenizer to parse the string with "," as delimiter
2b) Set tokenized values to object
2c) Add object to list
3) return the list created in above step.
Note: If large data you need to be careful while reading entire file, you may get OutofMemoryError.
Bruno Oliveira gave very good advice.
You can parse your file by reading it line by line and then use string.split method, as result you will have all your data in an array where you can easily read and put into a list view or move it to a sqlite database.

Categories

Resources