New features: Added the Top-N as a simple_list.

Extracted NamedDistance class from EarData.
Fixes: Problem with serializing an OpenCV Mat.
parent 924e850c
...@@ -10,6 +10,7 @@ import com.aluxoft.earrecognition.R; ...@@ -10,6 +10,7 @@ import com.aluxoft.earrecognition.R;
import com.aluxoft.earrecognition.common.EarData; 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.NameDistance;
import com.aluxoft.earrecognition.common.Person; import com.aluxoft.earrecognition.common.Person;
import com.aluxoft.earrecognition.loader.EarDataLoaderCommcare; import com.aluxoft.earrecognition.loader.EarDataLoaderCommcare;
import com.google.gson.Gson; import com.google.gson.Gson;
...@@ -25,11 +26,13 @@ import bolts.Continuation; ...@@ -25,11 +26,13 @@ import bolts.Continuation;
import bolts.Task; import bolts.Task;
/** /**
* Computes SIFT & finds top 10 matches * Computes SIFT & finds top-n matches
* TODO: Get other users features, compare SIFT features, etc... * TODO: Get other users features, compare SIFT features, etc...
*/ */
public class SIFTActivity extends Activity { public class SIFTActivity extends Activity {
final int kTopN = 7;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
...@@ -56,12 +59,12 @@ public class SIFTActivity extends Activity { ...@@ -56,12 +59,12 @@ public class SIFTActivity extends Activity {
EarData data = new EarDataLoaderCommcare().load(SIFTActivity.this); EarData data = new EarDataLoaderCommcare().load(SIFTActivity.this);
data.computeDistance(earFeature); data.computeDistance(earFeature);
ArrayList<EarData.NameDistance> distances = new ArrayList<>(data.getPersons().values()); ArrayList<NameDistance> distances = new ArrayList<>(data.getPersons().values());
Collections.sort(distances); Collections.sort(distances);
EarIdList result = new EarIdList(); EarIdList result = new EarIdList();
List<EarData.NameDistance> top10 = distances.subList(0, Math.min(10, distances.size())); List<NameDistance> topN = distances.subList(0, Math.min(kTopN, distances.size()));
result.setTop(top10); result.setTop(topN);
// Pass results to next activity. // Pass results to next activity.
result.setCurrentFeature(earFeature); result.setCurrentFeature(earFeature);
......
...@@ -4,10 +4,14 @@ import android.app.Activity; ...@@ -4,10 +4,14 @@ import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button; import android.widget.Button;
import android.widget.ListView;
import com.aluxoft.earrecognition.R; import com.aluxoft.earrecognition.R;
import com.aluxoft.earrecognition.common.EarData;
import com.aluxoft.earrecognition.common.EarIdList; import com.aluxoft.earrecognition.common.EarIdList;
import com.aluxoft.earrecognition.common.NameDistance;
import com.google.gson.Gson; import com.google.gson.Gson;
/** /**
...@@ -33,6 +37,15 @@ public class SelectUserActivity extends Activity { ...@@ -33,6 +37,15 @@ public class SelectUserActivity extends Activity {
Button registerButton = (Button) findViewById(R.id.register_commcare); Button registerButton = (Button) findViewById(R.id.register_commcare);
ArrayAdapter<NameDistance> arrayAdapter = new ArrayAdapter<NameDistance>(
this,
android.R.layout.simple_list_item_1,
this.earIdList.getTop()
);
ListView topNListView = (ListView)findViewById(R.id.topNListView);
topNListView.setAdapter(arrayAdapter);
registerButton.setOnClickListener(new View.OnClickListener() { registerButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
......
...@@ -31,35 +31,5 @@ public class EarData { ...@@ -31,35 +31,5 @@ public class EarData {
} }
} }
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.CvType;
import org.opencv.core.Mat; import org.opencv.core.Mat;
import org.opencv.core.Core;
import org.opencv.core.MatOfDMatch; import org.opencv.core.MatOfDMatch;
import org.opencv.features2d.DMatch; import org.opencv.features2d.DMatch;
import org.opencv.features2d.DescriptorMatcher; import org.opencv.features2d.DescriptorMatcher;
...@@ -21,7 +18,8 @@ public class EarFeature { ...@@ -21,7 +18,8 @@ public class EarFeature {
private static DescriptorMatcher matcher; private static DescriptorMatcher matcher;
private Mat features; private String features;
private transient Mat _features = null;
static { static {
System.loadLibrary("opencv_java"); System.loadLibrary("opencv_java");
...@@ -29,20 +27,30 @@ public class EarFeature { ...@@ -29,20 +27,30 @@ public class EarFeature {
matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE); matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE);
} }
public Mat getFeatures() { public String getFeatures() {
return features; return features;
} }
public void setFeatures(Mat features) { public void setFeatures(Mat _features) {
this._features = _features;
this.features = this.serializeFeatures();
}
public void setFeatures(String features) {
this.features = features; this.features = features;
this._features = null;
} }
public EarFeature(Mat features) { public EarFeature(String features) {
this.setFeatures(features); this.setFeatures(features);
} }
public EarFeature(Mat _features) {
this.setFeatures(_features);
}
public String serializeFeatures() { public String serializeFeatures() {
Mat mFeatures = this.getFeatures(); Mat mFeatures = this._getFeatures();
ArrayList<ArrayList<Integer>> features = new ArrayList<>(); ArrayList<ArrayList<Integer>> features = new ArrayList<>();
for (int i=0;i<mFeatures.rows();++i) { for (int i=0;i<mFeatures.rows();++i) {
...@@ -57,8 +65,10 @@ public class EarFeature { ...@@ -57,8 +65,10 @@ public class EarFeature {
} }
public double distance(EarFeature feature2) { public double distance(EarFeature feature2) {
assert this._getFeatures().type() == feature2._getFeatures().type();
MatOfDMatch matches = new MatOfDMatch(); MatOfDMatch matches = new MatOfDMatch();
matcher.match(this.getFeatures(), feature2.getFeatures(), matches); matcher.match(this._getFeatures(), feature2._getFeatures(), matches);
DMatch[] aMatches = matches.toArray(); DMatch[] aMatches = matches.toArray();
double distance = 0; double distance = 0;
...@@ -69,26 +79,32 @@ public class EarFeature { ...@@ -69,26 +79,32 @@ public class EarFeature {
return distance; return distance;
} }
public static EarFeature unserialize(String featuresString) { public Mat unserialize(String featuresString) {
final int kFeatureSize = 128; final int kFeatureSize = 128;
Gson gson = new Gson(); Gson gson = new Gson();
ArrayList< ArrayList<Double> > features = new ArrayList<>(); ArrayList< ArrayList<Double> > features = new ArrayList<>();
features = gson.fromJson(featuresString, features.getClass()); features = gson.fromJson(featuresString, features.getClass());
Mat mFeatures = new Mat(); Mat mFeatures = new Mat();
mFeatures.create(features.size(), kFeatureSize, CvType.CV_32S); mFeatures.create(features.size(), kFeatureSize, CvType.CV_32F);
int buffer[] = new int[1]; float buffer[] = new float[1];
for (int i=0;i<features.size();++i) { for (int i=0;i<features.size();++i) {
ArrayList<Double> feature = features.get(i); ArrayList<Double> feature = features.get(i);
for (int j=0;j<feature.size();++j) { for (int j=0;j<feature.size();++j) {
buffer[0] = feature.get(j).intValue(); buffer[0] = feature.get(j).floatValue();
mFeatures.put(i, j, buffer); mFeatures.put(i, j, buffer);
} }
} }
EarFeature earFeature = new EarFeature(mFeatures); return mFeatures;
return earFeature; }
private Mat _getFeatures() {
if (this._features == null && this.features != null) {
this._features = this.unserialize(this.features);
}
return this._features;
} }
} }
...@@ -11,7 +11,7 @@ public class EarIdList { ...@@ -11,7 +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; private List<NameDistance> top;
public EarFeature getCurrentFeature() { public EarFeature getCurrentFeature() {
return currentFeature; return currentFeature;
...@@ -21,11 +21,11 @@ public class EarIdList { ...@@ -21,11 +21,11 @@ public class EarIdList {
this.currentFeature = currentFeature; this.currentFeature = currentFeature;
} }
public List<EarData.NameDistance> getTop() { public List<NameDistance> getTop() {
return top; return top;
} }
public void setTop(List<EarData.NameDistance> top) { public void setTop(List<NameDistance> top) {
this.top = top; this.top = top;
} }
......
package com.aluxoft.earrecognition.common;
/**
* Created by josejuliomartinez on 14/10/15.
*/
public 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;
}
}
@Override
public String toString() {
return this.person.getName();
}
}
\ No newline at end of file
...@@ -56,7 +56,7 @@ public class EarDataLoaderCommcare extends EarDataLoader { ...@@ -56,7 +56,7 @@ public class EarDataLoaderCommcare extends EarDataLoader {
person.setCaseId(caseId); person.setCaseId(caseId);
person.setName(name); person.setName(name);
person.setGender(gender); person.setGender(gender);
person.addFeature(EarFeature.unserialize(features)); person.addFeature(new EarFeature(features));
earData.addPerson(person); earData.addPerson(person);
} }
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
<ListView <ListView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="453dp" android:layout_height="453dp"
android:id="@+id/listView" android:id="@+id/topNListView"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:choiceMode="singleChoice" /> android:choiceMode="singleChoice" />
......
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