New features: Downloading cases and features, calculate distances and sort, populate top-10 list.

parent cc9972b1
...@@ -7,11 +7,18 @@ import android.os.Bundle; ...@@ -7,11 +7,18 @@ import android.os.Bundle;
import com.aluxoft.earrecognition.EarIdentifier; import com.aluxoft.earrecognition.EarIdentifier;
import com.aluxoft.earrecognition.R; import com.aluxoft.earrecognition.R;
import com.aluxoft.earrecognition.common.EarData;
import com.aluxoft.earrecognition.common.EarFeature; import com.aluxoft.earrecognition.common.EarFeature;
import com.aluxoft.earrecognition.common.EarIdList; import com.aluxoft.earrecognition.common.EarIdList;
import com.aluxoft.earrecognition.common.Person;
import com.aluxoft.earrecognition.loader.EarDataLoaderCommcare;
import com.google.gson.Gson; import com.google.gson.Gson;
import java.io.File; import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import bolts.Continuation; import bolts.Continuation;
...@@ -46,9 +53,15 @@ public class SIFTActivity extends Activity { ...@@ -46,9 +53,15 @@ public class SIFTActivity extends Activity {
new File(imagePath).delete(); new File(imagePath).delete();
// Compares the current features with the database. // Compares the current features with the database.
EarIdList result = new EarIdList(); EarData data = new EarDataLoaderCommcare().load(SIFTActivity.this);
data.computeDistance(earFeature);
ArrayList<EarData.NameDistance> distances = new ArrayList<>(data.getPersons().values());
Collections.sort(distances);
// Generate the top-x. EarIdList result = new EarIdList();
List<EarData.NameDistance> top10 = distances.subList(0, Math.min(10, distances.size()));
result.setTop(top10);
// Pass results to next activity. // Pass results to next activity.
result.setCurrentFeature(earFeature); result.setCurrentFeature(earFeature);
......
package com.aluxoft.earrecognition.common; package com.aluxoft.earrecognition.common;
import com.aluxoft.earrecognition.unused.Person;
import java.util.HashMap; import java.util.HashMap;
/** /**
...@@ -10,11 +8,58 @@ import java.util.HashMap; ...@@ -10,11 +8,58 @@ import java.util.HashMap;
*/ */
public class EarData { public class EarData {
private HashMap<String, Person> persons = new HashMap<String, Person>(); private HashMap<String, NameDistance> persons = new HashMap<String, NameDistance>();
public void addPerson(Person person) { public void addPerson(Person person) {
this.persons.put(person.getIdentifier(), person); this.persons.put(person.getCaseId(), new NameDistance(0.0, person));
}
public HashMap<String, NameDistance> getPersons() {
return this.persons;
}
public void computeDistance(EarFeature feature) {
for (String caseId : this.persons.keySet()) {
NameDistance tuple = this.persons.get(caseId);
double minDistance = Double.MAX_VALUE;
for (EarFeature feature2 : tuple.person.getFeatures()) {
minDistance = Math.min(feature.distance(feature2), minDistance);
}
tuple.distance = minDistance;
}
}
public static class NameDistance implements Comparable<NameDistance> {
public double distance = 0;
public Person person = null;
public NameDistance() {
}
public NameDistance(double distance, Person person) {
this.set(distance, person);
}
public void set(double distance, Person person) {
this.distance = distance;
this.person = person;
}
@Override
public int compareTo(NameDistance nameDistance) {
if (this.distance < nameDistance.distance) {
return -1;
} else if (this.distance == nameDistance.distance) {
return 0;
} else {
return 1;
}
}
} }
} }
package com.aluxoft.earrecognition.common; package com.aluxoft.earrecognition.common;
import com.aluxoft.earrecognition.activities.SIFTActivity;
import com.aluxoft.earrecognition.utils.OpenCvUtils;
import com.google.gson.Gson; import com.google.gson.Gson;
import org.opencv.core.CvType;
import org.opencv.core.Mat; import org.opencv.core.Mat;
import org.opencv.core.Core;
import org.opencv.core.MatOfDMatch;
import org.opencv.features2d.DMatch;
import org.opencv.features2d.DescriptorMatcher;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -12,8 +19,16 @@ import java.util.ArrayList; ...@@ -12,8 +19,16 @@ import java.util.ArrayList;
*/ */
public class EarFeature { public class EarFeature {
private static DescriptorMatcher matcher;
private Mat features; private Mat features;
static {
System.loadLibrary("opencv_java");
System.loadLibrary("nonfree");
matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE);
}
public Mat getFeatures() { public Mat getFeatures() {
return features; return features;
} }
...@@ -41,4 +56,39 @@ public class EarFeature { ...@@ -41,4 +56,39 @@ public class EarFeature {
return gson.toJson(features); return gson.toJson(features);
} }
public double distance(EarFeature feature2) {
MatOfDMatch matches = new MatOfDMatch();
matcher.match(this.getFeatures(), feature2.getFeatures(), matches);
DMatch[] aMatches = matches.toArray();
double distance = 0;
for (int i=0;i<aMatches.length;++i) {
distance += aMatches[i].distance;
}
return distance;
}
public static EarFeature unserialize(String featuresString) {
final int kFeatureSize = 128;
Gson gson = new Gson();
ArrayList< ArrayList<Double> > features = new ArrayList<>();
features = gson.fromJson(featuresString, features.getClass());
Mat mFeatures = new Mat();
mFeatures.create(features.size(), kFeatureSize, CvType.CV_32S);
int buffer[] = new int[1];
for (int i=0;i<features.size();++i) {
ArrayList<Double> feature = features.get(i);
for (int j=0;j<feature.size();++j) {
buffer[0] = feature.get(j).intValue();
mFeatures.put(i, j, buffer);
}
}
EarFeature earFeature = new EarFeature(mFeatures);
return earFeature;
}
} }
package com.aluxoft.earrecognition.common; package com.aluxoft.earrecognition.common;
import java.util.List;
/** /**
* Represents top 10 Ear ID matches. * Represents top 10 Ear ID matches.
* *
...@@ -9,6 +11,7 @@ public class EarIdList { ...@@ -9,6 +11,7 @@ public class EarIdList {
// Store EarFeatures // Store EarFeatures
// Store Top-x // Store Top-x
private EarFeature currentFeature; private EarFeature currentFeature;
private List<EarData.NameDistance> top;
public EarFeature getCurrentFeature() { public EarFeature getCurrentFeature() {
return currentFeature; return currentFeature;
...@@ -18,4 +21,12 @@ public class EarIdList { ...@@ -18,4 +21,12 @@ public class EarIdList {
this.currentFeature = currentFeature; this.currentFeature = currentFeature;
} }
public List<EarData.NameDistance> getTop() {
return top;
}
public void setTop(List<EarData.NameDistance> top) {
this.top = top;
}
} }
package com.aluxoft.earrecognition.unused; package com.aluxoft.earrecognition.common;
import com.aluxoft.earrecognition.common.EarFeature;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -9,16 +7,18 @@ import java.util.ArrayList; ...@@ -9,16 +7,18 @@ import java.util.ArrayList;
*/ */
public class Person { public class Person {
private String identifier; private String caseId;
private String name; private String name;
private String gender;
private ArrayList<EarFeature> features = new ArrayList<EarFeature>(); private ArrayList<EarFeature> features = new ArrayList<EarFeature>();
public String getIdentifier() { public String getCaseId() {
return identifier; return caseId;
} }
public void setIdentifier(String identifier) { public void setCaseId(String caseId) {
this.identifier = identifier; this.caseId = caseId;
} }
public String getName() { public String getName() {
...@@ -29,7 +29,20 @@ public class Person { ...@@ -29,7 +29,20 @@ public class Person {
this.name = name; this.name = name;
} }
public String getGender() {
return this.gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public void addFeature(EarFeature feature) { public void addFeature(EarFeature feature) {
this.features.add(feature); this.features.add(feature);
} }
public ArrayList<EarFeature> getFeatures() {
return this.features;
}
} }
...@@ -5,6 +5,8 @@ import android.database.Cursor; ...@@ -5,6 +5,8 @@ import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import com.aluxoft.earrecognition.common.EarData; import com.aluxoft.earrecognition.common.EarData;
import com.aluxoft.earrecognition.common.EarFeature;
import com.aluxoft.earrecognition.common.Person;
/** /**
* Created by josejuliomartinez on 13/10/15. * Created by josejuliomartinez on 13/10/15.
...@@ -14,28 +16,50 @@ public class EarDataLoaderCommcare extends EarDataLoader { ...@@ -14,28 +16,50 @@ public class EarDataLoaderCommcare extends EarDataLoader {
@Override @Override
public EarData load(Activity current) { public EarData load(Activity current) {
EarData data = new EarData(); EarData earData = new EarData();
Cursor c = current.managedQuery(Uri.parse("content://org.commcare.dalvik.case/casedb/case"), null, null, null, null); Cursor c = current.managedQuery(Uri.parse("content://org.commcare.dalvik.case/casedb/case"), null, null, null, null);
if (c == null) { if (c == null) {
return data; // Throw an exception (Unable to connect to commcare)
return earData;
} }
String caseId;
String name;
String gender;
String features;
while (c.moveToNext()) { while (c.moveToNext()) {
String caseId = c.getString(c.getColumnIndex("case_id")); caseId = c.getString(c.getColumnIndex("case_id"));
name = c.getString(c.getColumnIndex("case_name"));
gender = null;
features = null;
Uri uri = Uri.parse("content://org.commcare.dalvik.case/casedb/data/" + caseId); Uri uri = Uri.parse("content://org.commcare.dalvik.case/casedb/data/" + caseId);
Cursor caseCursor = current.managedQuery(uri, null, null, null, null); Cursor caseCursor = current.managedQuery(uri, null, null, null, null);
if (caseCursor == null) { if (caseCursor == null) {
continue; continue;
} }
while (caseCursor.moveToNext()) { while (caseCursor.moveToNext()) {
String gender = caseCursor.getString(caseCursor.getColumnIndex("gender")); String datumId = caseCursor.getString(caseCursor.getColumnIndex("datum_id"));
String features = caseCursor.getString(caseCursor.getColumnIndex("features")); if (datumId.equals("gender")) {
// Agregar el gender, caseid y features a data gender = caseCursor.getString(caseCursor.getColumnIndex("value"));
} else if (datumId.equals("features")) {
features = caseCursor.getString(caseCursor.getColumnIndex("value"));
}
}
if (gender == null || features == null) {
continue;
} }
Person person = new Person();
person.setCaseId(caseId);
person.setName(name);
person.setGender(gender);
person.addFeature(EarFeature.unserialize(features));
earData.addPerson(person);
} }
return data; return earData;
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment