...
 
Commits (3)
......@@ -11,3 +11,4 @@
/build
/captures
.externalNativeBuild
/fertilizeSorting
package ch.bionomous.eggsorter.controller.processing.fertilizeSorting;
import android.graphics.Bitmap;
import android.graphics.Color;
import Jama.Matrix;
public class BoundaryImage {
Bitmap image;
protected static final int WINDOW_SIZE = 500; // in pixels
protected static final int POINT_SIZE = 10; // in pixels
protected static final int BOUNDARY_SIZE = 2; // in pixels
// Global variables
private Matrix Xp_norm;
private int nbFert;
private int ex, ey;
GmmModel gmmModels;
// Constructor
public BoundaryImage(Matrix Xp_norm, int nbFert, int ex, int ey, GmmModel gmmModel) {
image = Bitmap.createBitmap(WINDOW_SIZE, WINDOW_SIZE, Bitmap.Config.ARGB_8888);
this.Xp_norm = Xp_norm;
this.nbFert = nbFert;
this.ex = ex;
this.ey = ey;
this.gmmModels = gmmModels;
}
// Method to draw the background classification boundary
public void drawClassBoundary() {
for (int x=0; x<WINDOW_SIZE; x++) // for every image column
for (int y=0; y<WINDOW_SIZE; y++) {// for every image row
double[][] values = {{(double)x/WINDOW_SIZE}, {(double)y/WINDOW_SIZE}};
Matrix X_test = new Matrix(values);
// Compute the pixel label
SortAlgo0.Class label = gmmModels.classifySingle(X_test);
// Give a color to the pixel in function of the label
int color;
if (label == SortAlgo0.Class.Fertilized)
color = Color.rgb(100, 0, 0); // dark red color
else
color = Color.rgb(0, 0, 100); // dark blue color
image.setPixel(x, y, color);
}
}
// Method to draw the datapoints on classification boundary image
public void drawDatapoints() {
int M = Xp_norm.getColumnDimension();
// Draw the fert datapoints in bright red
int color = Color.RED;
for (int j=0; j<nbFert; j++) {
int projection_x = (int)(Xp_norm.get(ex-1, j)*WINDOW_SIZE);
int projection_y = (int)(Xp_norm.get(ey-1, j)*WINDOW_SIZE);
drawPoint(projection_x, projection_y, color);
}
// Draw the unfert datapoints in bright blue
color = Color.BLUE;
for (int j=nbFert; j<M; j++) {
int projection_x = (int)(Xp_norm.get(ex-1, j)*WINDOW_SIZE);
int projection_y = (int)(Xp_norm.get(ey-1, j)*WINDOW_SIZE);
drawPoint(projection_x, projection_y, color);
}
}
// Method to put a circle with a color C on a datapoint with pixel coordinates (x0;y0)
private void drawPoint(int x0, int y0, int C) {
int R = POINT_SIZE/2;
for (int x=0; x<WINDOW_SIZE; x++) // for every image column
for (int y=0; y<WINDOW_SIZE; y++) // for every image row
if ((x-x0)*(x-x0) + (y-y0)*(y-y0) < R*R)
image.setPixel(x, y, C);
}
}
package ch.bionomous.eggsorter.controller.processing.fertilizeSorting;
import android.graphics.Bitmap;
import android.graphics.Color;
import Jama.Matrix;
public class BoundaryImage {
Bitmap image;
protected static final int WINDOW_SIZE = 500; // in pixels
protected static final int POINT_SIZE = 10; // in pixels
protected static final int BOUNDARY_SIZE = 2; // in pixels
// Global variables
private Matrix Xp_norm;
private int nbFert;
private int ex, ey;
GmmModel gmmModels;
// Constructor
public BoundaryImage(Matrix Xp_norm, int nbFert, int ex, int ey, GmmModel gmmModel) {
image = Bitmap.createBitmap(WINDOW_SIZE, WINDOW_SIZE, Bitmap.Config.ARGB_8888);
this.Xp_norm = Xp_norm;
this.nbFert = nbFert;
this.ex = ex;
this.ey = ey;
this.gmmModels = gmmModels;
}
// Method to draw the background classification boundary
public void drawClassBoundary() {
for (int x=0; x<WINDOW_SIZE; x++) // for every image column
for (int y=0; y<WINDOW_SIZE; y++) {// for every image row
double[][] values = {{(double)x/WINDOW_SIZE}, {(double)y/WINDOW_SIZE}};
Matrix X_test = new Matrix(values);
// Compute the pixel label
SortAlgo0.Class label = gmmModels.classifySingle(X_test);
// Give a color to the pixel in function of the label
int color;
if (label == SortAlgo0.Class.Fertilized)
color = Color.rgb(100, 0, 0); // dark red color
else
color = Color.rgb(0, 0, 100); // dark blue color
image.setPixel(x, y, color);
}
}
// Method to draw the datapoints on classification boundary image
public void drawDatapoints() {
int M = Xp_norm.getColumnDimension();
// Draw the fert datapoints in bright red
int color = Color.RED;
for (int j=0; j<nbFert; j++) {
int projection_x = (int)(Xp_norm.get(ex-1, j)*WINDOW_SIZE);
int projection_y = (int)(Xp_norm.get(ey-1, j)*WINDOW_SIZE);
drawPoint(projection_x, projection_y, color);
}
// Draw the unfert datapoints in bright blue
color = Color.BLUE;
for (int j=nbFert; j<M; j++) {
int projection_x = (int)(Xp_norm.get(ex-1, j)*WINDOW_SIZE);
int projection_y = (int)(Xp_norm.get(ey-1, j)*WINDOW_SIZE);
drawPoint(projection_x, projection_y, color);
}
}
// Method to put a circle with a color C on a datapoint with pixel coordinates (x0;y0)
private void drawPoint(int x0, int y0, int C) {
int R = POINT_SIZE/2;
for (int x=0; x<WINDOW_SIZE; x++) // for every image column
for (int y=0; y<WINDOW_SIZE; y++) // for every image row
if ((x-x0)*(x-x0) + (y-y0)*(y-y0) < R*R)
image.setPixel(x, y, C);
}
}
package ch.bionomous.eggsorter.controller.processing.fertilizeSorting;
import Jama.Matrix;
import ch.bionomous.eggsorter.filesmanager.FilesManager;
public class CrossValidation {
// Constants
protected static final double SMALL_DIFF = 1e-6;
protected static final double MAX_DIST = 1.0;
protected static final int MAX_ITER = 100;
protected static final int N = 2;
// Global variables
private int p, M;
private int best_K;
private int best_ex, best_ey;
private double best_accuracy = 0.0;
// Constructor
public CrossValidation(Matrix xpNorm, int K_max, int E_max, int F_fold, double tt_ratio, double unequalClassCoef, String configId) {
this.p = xpNorm.getRowDimension();
this.M = xpNorm.getColumnDimension();
if (p < E_max)
E_max = p;
int nbFert = FilesManager.getIntValueInFile(configId + "/numberOfFertImagesFile.txt");
for (int K=1; K<=K_max; K++ )
for (int ex=0; ex<E_max; ex++)
for (int ey=0; ey<E_max; ey++)
if (ex<ey) {
// Extract the 2D dataset
int[] rows = {ex, ey};
Matrix Xp_norm_2D = xpNorm.getMatrix(rows, 0, M-1);
// F-fold cross-validation
double mean_accuracy = 0;
for (int f=0; f<F_fold; f++ ) {
// Split the dataset into train and test datasets
SplitDataTrainTest splitDataTrainTest = new SplitDataTrainTest(Xp_norm_2D, nbFert, tt_ratio);
Matrix X_train = splitDataTrainTest.getTrainMatrix();
Matrix X_test = splitDataTrainTest.getTestMatrix();
Matrix y_test = splitDataTrainTest.getTestLabels();
// Train the 2D dataset
GmmModel gmmModels = new GmmModel(X_train, K, unequalClassCoef, configId);
// Test the 2D dataset
Matrix y_est = gmmModels.classify(X_test);
// Compute the mean accuracy
mean_accuracy += getAccuracy(y_test, y_est, unequalClassCoef);
}
mean_accuracy = mean_accuracy/F_fold;
// Find the best accuracy
if (mean_accuracy > best_accuracy) {
best_accuracy = mean_accuracy;
best_K = K;
best_ex = ex;
best_ey = ey;
}
}
}
public double getBestAccuracy() {
return best_accuracy;
}
public int getBestK() {
return best_K;
}
public int getBestEx() {
return best_ex;
}
public int getBestEy() {
return best_ey;
}
// Compute the accuracy of the classification
public static double getAccuracy(Matrix y_test, Matrix y_est, double unequalClassCoef) {
double accuracy = unequalClassCoef * getFertAccuracy(y_test, y_est) +
(1.0-unequalClassCoef) * getUnfertAccuracy(y_test, y_est);
return accuracy;
}
// Compute the fertilized egg classified as unfertilized accuracy
public static double getFertAccuracy(Matrix y_test, Matrix y_est) {
double accuracy = 0;
int M_test = y_test.getColumnDimension();
int M_fert = 0;
int N_errors = 0; // compute the number of missclassified fertilized eggs
for (int j=0; j<M_test; j++)
if ( y_test.get(0, j) == 0 ) { // take the fertilized eggs
M_fert++;
if ( y_est.get(0, j) == 1 ) // take the classified as unfertilized
N_errors++;
}
accuracy = (double)(M_fert - N_errors)/M_fert;
return accuracy;
}
// Compute the unfertilized egg classified as fertilized accuracy
public static double getUnfertAccuracy(Matrix y_test, Matrix y_est) {
double accuracy = 0;
int M_test = y_test.getColumnDimension();
int M_unfert = 0;
int N_errors = 0; // compute the number of missclassified unfertilized eggs
for (int j=0; j<M_test; j++)
if ( y_test.get(0, j) == 1 ) { // take the unfertilized eggs
M_unfert++;
if ( y_est.get(0, j) == 0 ) // take the classified as fertilized
N_errors++;
}
accuracy = (double)(M_unfert - N_errors)/M_unfert;
return accuracy;
}
}
package ch.bionomous.eggsorter.controller.processing.fertilizeSorting;
import Jama.Matrix;
import ch.bionomous.eggsorter.filesmanager.FilesManager;
public class CrossValidation {
// Constants
protected static final double SMALL_DIFF = 1e-6;
protected static final double MAX_DIST = 1.0;
protected static final int MAX_ITER = 100;
protected static final int N = 2;
// Global variables
private int p, M;
private int best_K;
private int best_ex, best_ey;
private double best_accuracy = 0.0;
// Constructor
public CrossValidation(Matrix xpNorm, int K_max, int E_max, int F_fold, double tt_ratio, double unequalClassCoef, String configId) {
this.p = xpNorm.getRowDimension();
this.M = xpNorm.getColumnDimension();
if (p < E_max)
E_max = p;
int nbFert = FilesManager.getIntValueInFile(configId + "/numberOfFertImagesFile.txt");
for (int K=1; K<=K_max; K++ )
for (int ex=0; ex<E_max; ex++)
for (int ey=0; ey<E_max; ey++)
if (ex<ey) {
// Extract the 2D dataset
int[] rows = {ex, ey};
Matrix Xp_norm_2D = xpNorm.getMatrix(rows, 0, M-1);
// F-fold cross-validation
double mean_accuracy = 0;
for (int f=0; f<F_fold; f++ ) {
// Split the dataset into train and test datasets
SplitDataTrainTest splitDataTrainTest = new SplitDataTrainTest(Xp_norm_2D, nbFert, tt_ratio);
Matrix X_train = splitDataTrainTest.getTrainMatrix();
Matrix X_test = splitDataTrainTest.getTestMatrix();
Matrix y_test = splitDataTrainTest.getTestLabels();
// Train the 2D dataset
GmmModel gmmModels = new GmmModel(X_train, K, unequalClassCoef, configId);
// Test the 2D dataset
Matrix y_est = gmmModels.classify(X_test);
// Compute the mean accuracy
mean_accuracy += getAccuracy(y_test, y_est, unequalClassCoef);
}
mean_accuracy = mean_accuracy/F_fold;
// Find the best accuracy
if (mean_accuracy > best_accuracy) {
best_accuracy = mean_accuracy;
best_K = K;
best_ex = ex;
best_ey = ey;
}
}
}
public double getBestAccuracy() {
return best_accuracy;
}
public int getBestK() {
return best_K;
}
public int getBestEx() {
return best_ex;
}
public int getBestEy() {
return best_ey;
}
// Compute the accuracy of the classification
public static double getAccuracy(Matrix y_test, Matrix y_est, double unequalClassCoef) {
double accuracy = unequalClassCoef * getFertAccuracy(y_test, y_est) +
(1.0-unequalClassCoef) * getUnfertAccuracy(y_test, y_est);
return accuracy;
}
// Compute the fertilized egg classified as unfertilized accuracy
public static double getFertAccuracy(Matrix y_test, Matrix y_est) {
double accuracy = 0;
int M_test = y_test.getColumnDimension();
int M_fert = 0;
int N_errors = 0; // compute the number of missclassified fertilized eggs
for (int j=0; j<M_test; j++)
if ( y_test.get(0, j) == 0 ) { // take the fertilized eggs
M_fert++;
if ( y_est.get(0, j) == 1 ) // take the classified as unfertilized
N_errors++;
}
accuracy = (double)(M_fert - N_errors)/M_fert;
return accuracy;
}
// Compute the unfertilized egg classified as fertilized accuracy
public static double getUnfertAccuracy(Matrix y_test, Matrix y_est) {
double accuracy = 0;
int M_test = y_test.getColumnDimension();
int M_unfert = 0;
int N_errors = 0; // compute the number of missclassified unfertilized eggs
for (int j=0; j<M_test; j++)
if ( y_test.get(0, j) == 1 ) { // take the unfertilized eggs
M_unfert++;
if ( y_est.get(0, j) == 0 ) // take the classified as fertilized
N_errors++;
}
accuracy = (double)(M_unfert - N_errors)/M_unfert;
return accuracy;
}
}
package ch.bionomous.eggsorter.controller.processing.fertilizeSorting;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import Jama.Matrix;
public class Kmeans {
// Constants
protected static final double SMALL_DIFF = 0.000001;
protected static final double MAX_DIST = 1.0;
protected static final int MAX_ITER = 100;
// Global variables
private int N, M;
private int K;
private int[] labels;
private Matrix mu;
private Matrix X;
// Constructor
public Kmeans(Matrix X, int K) {
this.N = X.getRowDimension();
this.M = X.getColumnDimension();
this.K = K;
this.X = X;
this.mu = new Matrix(N, K);
this.labels = new int[M];
// Step 1. Mu Initialization
kmeansInit();
Matrix mu_before = new Matrix(N, K);
int[][] r = new int[M][K]; // responsibility matrix
boolean cluster_empty = false;
int iter = 0;
// K-Means Algorithm
while(iter < MAX_ITER && getDiff(mu, mu_before) > SMALL_DIFF || iter==0 ) {
mu_before = mu.copy();
// Step 2. Distances from X to Mu
Matrix D = distX2Mu();
// Step 3. Assignment Step
// k responsibility
for (int j=0; j<M; j++) {
double min = 1000;
for (int k=0; k<K; k++)
if (D.get(k, j) < min) {
min = D.get(k, j);
labels[j] = k;
}
}
// r responsibility
for (int j=0; j<M; j++) {
if (K > 1)
for (int k=0; k<K; k++) {
if (labels[j] == k)
r[j][k] = 1;
else
r[j][k] = 0;
}
else
r[j][K-1] = 1;
}
// Step 4. Update Step: Recompute Mu
mu = new Matrix(N, K); // Set mu to a zero matrix
for (int k=0; k<K; k++) {
double sum_responsibility = 0;
for (int j=0; j<M; j++) {
sum_responsibility += r[j][k];
Matrix increment = X.getMatrix(0, N-1, j, j).times((double)r[j][k]);
mu.setMatrix(0, N-1, k, k, mu.getMatrix(0, N-1, k, k).plus(increment));
}
if (sum_responsibility > 0)
mu.setMatrix(0, N-1, k, k, mu.getMatrix(0, N-1, k, k).times(1/sum_responsibility));
else
cluster_empty = true;
}
if (cluster_empty) {
kmeansInit();
cluster_empty = false;
}
iter++;
} // End while loop
}
public Matrix getMu() {
return mu;
}
public int[] getLabels() {
return labels;
}
private double getDiff(Matrix mu, Matrix mu_before) {
return mu.minus(mu_before).normF();
}
// initialize the centroids on random datapoints
private void kmeansInit() {
Matrix X_shuffle = shuffleColumnMatrix(X.copy());
this.mu = X_shuffle.getMatrix(0, N-1, 0, K-1);
}
// Function to get the L2 distances between every datapoints and centroids
private Matrix distX2Mu() {
Matrix D = new Matrix(K, M); // distance matrix
for (int k=0; k<K; k++)
for (int j=0; j<M; j++) {
double distance = 0;
for (int i=0; i<N; i++)
distance += Math.pow(X.get(i, j) - mu.get(i, k), 2);
distance = Math.sqrt(distance);
D.set(k, j, distance);
}
return D;
}
// Implementing Fisher�Yates shuffle
private Matrix shuffleColumnMatrix(Matrix X) {
Random rnd = ThreadLocalRandom.current();
for (int j=M-1; j>0; j--) {
int index = rnd.nextInt(j + 1);
// Simple swap
Matrix x = X.getMatrix(0, N-1, index, index);
X.setMatrix(0, N-1, index, index, X.getMatrix(0, N-1, j, j));
X.setMatrix(0, N-1, j, j, x);
}
return X;
}
}
package ch.bionomous.eggsorter.controller.processing.fertilizeSorting;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import Jama.Matrix;
public class Kmeans {
// Constants
protected static final double SMALL_DIFF = 0.000001;
protected static final double MAX_DIST = 1.0;
protected static final int MAX_ITER = 100;
// Global variables
private int N, M;
private int K;
private int[] labels;
private Matrix mu;
private Matrix X;
// Constructor
public Kmeans(Matrix X, int K) {
this.N = X.getRowDimension();
this.M = X.getColumnDimension();
this.K = K;
this.X = X;
this.mu = new Matrix(N, K);
this.labels = new int[M];
// Step 1. Mu Initialization
kmeansInit();
Matrix mu_before = new Matrix(N, K);
int[][] r = new int[M][K]; // responsibility matrix
boolean cluster_empty = false;
int iter = 0;
// K-Means Algorithm
while(iter < MAX_ITER && getDiff(mu, mu_before) > SMALL_DIFF || iter==0 ) {
mu_before = mu.copy();
// Step 2. Distances from X to Mu
Matrix D = distX2Mu();
// Step 3. Assignment Step
// k responsibility
for (int j=0; j<M; j++) {
double min = 1000;
for (int k=0; k<K; k++)
if (D.get(k, j) < min) {
min = D.get(k, j);
labels[j] = k;
}
}
// r responsibility
for (int j=0; j<M; j++) {
if (K > 1)
for (int k=0; k<K; k++) {
if (labels[j] == k)
r[j][k] = 1;
else
r[j][k] = 0;
}
else
r[j][K-1] = 1;
}
// Step 4. Update Step: Recompute Mu
mu = new Matrix(N, K); // Set mu to a zero matrix
for (int k=0; k<K; k++) {
double sum_responsibility = 0;
for (int j=0; j<M; j++) {
sum_responsibility += r[j][k];
Matrix increment = X.getMatrix(0, N-1, j, j).times((double)r[j][k]);
mu.setMatrix(0, N-1, k, k, mu.getMatrix(0, N-1, k, k).plus(increment));
}
if (sum_responsibility > 0)
mu.setMatrix(0, N-1, k, k, mu.getMatrix(0, N-1, k, k).times(1/sum_responsibility));
else
cluster_empty = true;
}
if (cluster_empty) {
kmeansInit();
cluster_empty = false;
}
iter++;
} // End while loop
}
public Matrix getMu() {
return mu;
}
public int[] getLabels() {
return labels;
}
private double getDiff(Matrix mu, Matrix mu_before) {
return mu.minus(mu_before).normF();
}
// initialize the centroids on random datapoints
private void kmeansInit() {
Matrix X_shuffle = shuffleColumnMatrix(X.copy());
this.mu = X_shuffle.getMatrix(0, N-1, 0, K-1);
}
// Function to get the L2 distances between every datapoints and centroids
private Matrix distX2Mu() {
Matrix D = new Matrix(K, M); // distance matrix
for (int k=0; k<K; k++)
for (int j=0; j<M; j++) {
double distance = 0;
for (int i=0; i<N; i++)
distance += Math.pow(X.get(i, j) - mu.get(i, k), 2);
distance = Math.sqrt(distance);
D.set(k, j, distance);
}
return D;
}
// Implementing Fisher�Yates shuffle
private Matrix shuffleColumnMatrix(Matrix X) {
Random rnd = ThreadLocalRandom.current();
for (int j=M-1; j>0; j--) {
int index = rnd.nextInt(j + 1);
// Simple swap
Matrix x = X.getMatrix(0, N-1, index, index);
X.setMatrix(0, N-1, index, index, X.getMatrix(0, N-1, j, j));
X.setMatrix(0, N-1, j, j, x);
}
return X;
}
}
package ch.bionomous.eggsorter.controller.processing.fertilizeSorting;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import Jama.Matrix;
public class SplitDataTrainTest {
private int N;
private int M;
private double tt_ratio;
private Matrix X_tt;
public SplitDataTrainTest(Matrix X, int nbFert, double tt_ratio) {
this.tt_ratio = tt_ratio;
this.N = X.getRowDimension();
this.M = X.getColumnDimension();
// Put the dataset in a new matrix which contains the datapoints and the corresponding labels
Matrix X_tr_te = new Matrix(N+1, M);
X_tr_te.setMatrix(0, N-1, 0, M-1, X);
// Put the labels in the new matrix in corresponding column (label=0 for fertilized and label=1 for unfertilized)
for (int j=0; j<M; j++) {
if (j < nbFert)
X_tr_te.set(N, j, 0);
else
X_tr_te.set(N, j, 1);
}
// Shuffle the datapoints
X_tr_te = shuffleColumnMatrix(X_tr_te.copy(), N, M);
this.X_tt = X_tr_te.copy();
}
public Matrix getTrainMatrix() {
return X_tt.getMatrix(0, N, 0, (int)(M*tt_ratio)-1);
}
public Matrix getTestMatrix() {
int column_start = (int)(M*tt_ratio);
if (column_start <= M-1)
return X_tt.getMatrix(0, N, column_start, M-1);
else
return null;
}
public Matrix getTestLabels() {
int column_start = (int)(M*tt_ratio);
if (column_start <= M-1)
return X_tt.getMatrix(N, N, column_start, M-1);
else
return null;
}
// Implementing Fisher�Yates shuffle
private static Matrix shuffleColumnMatrix(Matrix X, int N, int M) {
Random rnd = ThreadLocalRandom.current();
for (int j=M-1; j>0; j--) {
int index = rnd.nextInt(j + 1);
// Simple swap
Matrix x = X.getMatrix(0, N, index, index);
X.setMatrix(0, N, index, index, X.getMatrix(0, N, j, j));
X.setMatrix(0, N, j, j, x);
}
return X;
}
}
package ch.bionomous.eggsorter.controller.processing.fertilizeSorting;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import Jama.Matrix;
public class SplitDataTrainTest {
private int N;
private int M;
private double tt_ratio;
private Matrix X_tt;
public SplitDataTrainTest(Matrix X, int nbFert, double tt_ratio) {
this.tt_ratio = tt_ratio;
this.N = X.getRowDimension();
this.M = X.getColumnDimension();
// Put the dataset in a new matrix which contains the datapoints and the corresponding labels
Matrix X_tr_te = new Matrix(N+1, M);
X_tr_te.setMatrix(0, N-1, 0, M-1, X);
// Put the labels in the new matrix in corresponding column (label=0 for fertilized and label=1 for unfertilized)
for (int j=0; j<M; j++) {
if (j < nbFert)
X_tr_te.set(N, j, 0);
else
X_tr_te.set(N, j, 1);
}
// Shuffle the datapoints
X_tr_te = shuffleColumnMatrix(X_tr_te.copy(), N, M);
this.X_tt = X_tr_te.copy();
}
public Matrix getTrainMatrix() {
return X_tt.getMatrix(0, N, 0, (int)(M*tt_ratio)-1);
}
public Matrix getTestMatrix() {
int column_start = (int)(M*tt_ratio);
if (column_start <= M-1)
return X_tt.getMatrix(0, N, column_start, M-1);
else
return null;
}
public Matrix getTestLabels() {
int column_start = (int)(M*tt_ratio);
if (column_start <= M-1)
return X_tt.getMatrix(N, N, column_start, M-1);
else
return null;
}
// Implementing Fisher�Yates shuffle
private static Matrix shuffleColumnMatrix(Matrix X, int N, int M) {
Random rnd = ThreadLocalRandom.current();
for (int j=M-1; j>0; j--) {
int index = rnd.nextInt(j + 1);
// Simple swap
Matrix x = X.getMatrix(0, N, index, index);
X.setMatrix(0, N, index, index, X.getMatrix(0, N, j, j));
X.setMatrix(0, N, j, j, x);
}
return X;
}
}
package ch.bionomous.eggsorter.controller.processing.fertilizeSorting;
import android.graphics.Bitmap;
import android.graphics.Color;
public class UnwrapImage {
Bitmap localImage;
protected static final int THETA_MAX = 360;
protected static final int SIZE_RESIZED_IMG = 360; // in pixels
protected static final int INTENSITY_THRESHOLD = 10;
// Constructor
public UnwrapImage(Bitmap inImage, int r_max) {
localImage = Bitmap.createBitmap(THETA_MAX, SIZE_RESIZED_IMG, Bitmap.Config.ARGB_8888);
int r_min =0;
for (int R=r_min; R<r_max; R++)
for (int theta=0; theta<THETA_MAX; theta++) {
int x = inImage.getWidth()/2 - 1 + (int)(R*Math.cos(Math.PI*theta/180.0));
int y = inImage.getHeight()/2 - 1 + (int)(R*Math.sin(Math.PI*theta/180.0));
if(x >= 0 && x < inImage.getWidth() && y >= 0 && y < inImage.getHeight())
localImage.setPixel(theta, (r_max-1)-R, inImage.getPixel(x, y));
else
localImage.setPixel(theta, (r_max-1)-R, Color.WHITE);
}
for (int R=r_max; R<SIZE_RESIZED_IMG; R++)
for (int theta=0; theta<THETA_MAX; theta++)
localImage.setPixel(theta, R, Color.WHITE);
}
public int findDirectionAngle() {
int x_left = 0, x_right = 0;
int x_middle = 0, y_middle = 0;
// Find direction angle from left
for (int y=0; y<localImage.getHeight(); y++) // for every image row
for (int x=0; x<localImage.getWidth(); x++) // for every image column
if (Color.red(localImage.getPixel(x, y_middle)) < INTENSITY_THRESHOLD && x_left*y_middle == 0) {
x_left = x;
y_middle = y;
}
// Find direction angle from right
for (int x=localImage.getWidth()-1; x>=0; x--) // for every image column
if (Color.red(localImage.getPixel(x, y_middle)) < INTENSITY_THRESHOLD && x_right == 0)
x_right = x;
x_middle = (x_left + x_right)/2;
return x_middle;
}
public void recenter(int angle) {
Bitmap inImage = localImage.copy(Bitmap.Config.ARGB_8888, false);
for (int outx=0; outx<localImage.getWidth(); outx++) // for every image column
for (int outy=0; outy<localImage.getHeight(); outy++) { // for every image row
int inx = outx - (localImage.getWidth()/2 - angle);
int iny = outy;
if (inx < 0)
inx += localImage.getWidth();
if (inx >= localImage.getWidth())
inx -= localImage.getWidth();
localImage.setPixel(outx, outy, inImage.getPixel(inx, iny));
}
}
public Bitmap reduceResolution(int reduction) {
// Past image and its past size
Bitmap inImage = localImage.copy(Bitmap.Config.ARGB_8888, false);
int inWidth = localImage.getWidth();
int inHeight = localImage.getHeight();
// New image with its new size
int outWidth = inWidth/reduction;
int outHeight = inHeight/reduction;
Bitmap outImage = Bitmap.createBitmap(outWidth, outHeight, Bitmap.Config.ARGB_8888);
// Reduce the spatial resolution
int size_block = reduction;
for (int x=0; x<outWidth; x++) // for every image column
for (int y=0; y<outHeight; y++) {// for every image row
int sum = 0;
for (int k=0; k<size_block; k++) // for every block column
for (int l=0; l<size_block; l++) {// for every block row
int bx = x*size_block + k;
int by = y*size_block + l;
if(bx>=0 && bx<inWidth && by>=0 && by<inHeight) {
int c = inImage.getPixel(bx, by);
sum += Color.red(c);
}
}
int mean = sum/(size_block*size_block);
int c_mean = Color.rgb(mean, mean, mean);
outImage.setPixel(x, y, c_mean);
}
return outImage;
}
}
package ch.bionomous.eggsorter.controller.processing.fertilizeSorting;
import android.graphics.Bitmap;
import android.graphics.Color;
public class UnwrapImage {
Bitmap localImage;
protected static final int THETA_MAX = 360;
protected static final int SIZE_RESIZED_IMG = 360; // in pixels
protected static final int INTENSITY_THRESHOLD = 10;
// Constructor
public UnwrapImage(Bitmap inImage, int r_max) {
localImage = Bitmap.createBitmap(THETA_MAX, SIZE_RESIZED_IMG, Bitmap.Config.ARGB_8888);
int r_min =0;
for (int R=r_min; R<r_max; R++)
for (int theta=0; theta<THETA_MAX; theta++) {
int x = inImage.getWidth()/2 - 1 + (int)(R*Math.cos(Math.PI*theta/180.0));
int y = inImage.getHeight()/2 - 1 + (int)(R*Math.sin(Math.PI*theta/180.0));
if(x >= 0 && x < inImage.getWidth() && y >= 0 && y < inImage.getHeight())
localImage.setPixel(theta, (r_max-1)-R, inImage.getPixel(x, y));
else
localImage.setPixel(theta, (r_max-1)-R, Color.WHITE);
}
for (int R=r_max; R<SIZE_RESIZED_IMG; R++)
for (int theta=0; theta<THETA_MAX; theta++)
localImage.setPixel(theta, R, Color.WHITE);
}
public int findDirectionAngle() {
int x_left = 0, x_right = 0;
int x_middle = 0, y_middle = 0;
// Find direction angle from left
for (int y=0; y<localImage.getHeight(); y++) // for every image row
for (int x=0; x<localImage.getWidth(); x++) // for every image column
if (Color.red(localImage.getPixel(x, y_middle)) < INTENSITY_THRESHOLD && x_left*y_middle == 0) {
x_left = x;
y_middle = y;
}
// Find direction angle from right
for (int x=localImage.getWidth()-1; x>=0; x--) // for every image column
if (Color.red(localImage.getPixel(x, y_middle)) < INTENSITY_THRESHOLD && x_right == 0)
x_right = x;
x_middle = (x_left + x_right)/2;
return x_middle;
}
public void recenter(int angle) {
Bitmap inImage = localImage.copy(Bitmap.Config.ARGB_8888, false);
for (int outx=0; outx<localImage.getWidth(); outx++) // for every image column
for (int outy=0; outy<localImage.getHeight(); outy++) { // for every image row
int inx = outx - (localImage.getWidth()/2 - angle);
int iny = outy;
if (inx < 0)
inx += localImage.getWidth();
if (inx >= localImage.getWidth())
inx -= localImage.getWidth();
localImage.setPixel(outx, outy, inImage.getPixel(inx, iny));
}
}
public Bitmap reduceResolution(int reduction) {
// Past image and its past size
Bitmap inImage = localImage.copy(Bitmap.Config.ARGB_8888, false);
int inWidth = localImage.getWidth();
int inHeight = localImage.getHeight();
// New image with its new size
int outWidth = inWidth/reduction;
int outHeight = inHeight/reduction;
Bitmap outImage = Bitmap.createBitmap(outWidth, outHeight, Bitmap.Config.ARGB_8888);
// Reduce the spatial resolution
int size_block = reduction;
for (int x=0; x<outWidth; x++) // for every image column
for (int y=0; y<outHeight; y++) {// for every image row
int sum = 0;
for (int k=0; k<size_block; k++) // for every block column
for (int l=0; l<size_block; l++) {// for every block row
int bx = x*size_block + k;
int by = y*size_block + l;
if(bx>=0 && bx<inWidth && by>=0 && by<inHeight) {
int c = inImage.getPixel(bx, by);
sum += Color.red(c);
}
}
int mean = sum/(size_block*size_block);
int c_mean = Color.rgb(mean, mean, mean);
outImage.setPixel(x, y, c_mean);
}
return outImage;
}
}
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array
name="end_slide_title">
<item>Removing eggs on the wheel...</item>
<item>Ejecting eggs</item>
<item>Cleaning and water removing</item>
<item>Unplug syringe</item>
<item>Open wheel</item>
<item>Remove water</item>
<item>See you soon...</item>
</array>
<array
name="end_slide_text">
<item>Do you want to eject remaining eggs in the system ?</item>
<item>The wheel is emptying</item>
<item>The system is performing auto-clean and removing water</item>
<item>You can unplug the syringe</item>
<item>You can open the wheel</item>
<item>Do not forget to remove water for containers and to clean filters</item>
<item>System is clean, you can safely shut it down</item>
</array>
<array
name="end_slide_gif">
<item></item>
<item></item>
<item></item>
<item></item>
<item></item>
<item></item>
<item></item>
</array>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array
name="end_slide_title">
<item>Removing eggs on the wheel...</item>
<item>Ejecting eggs</item>
<item>Cleaning and water removing</item>
<item>Unplug syringe</item>
<item>Open wheel</item>
<item>Remove water</item>
<item>See you soon...</item>
</array>
<array
name="end_slide_text">
<item>Do you want to eject remaining eggs in the system ?</item>
<item>The wheel is emptying</item>
<item>The system is performing auto-clean and removing water</item>
<item>You can unplug the syringe</item>
<item>You can open the wheel</item>
<item>Do not forget to remove water for containers and to clean filters</item>
<item>System is clean, you can safely shut it down</item>
</array>
<array
name="end_slide_gif">
<item></item>
<item></item>
<item></item>
<item></item>
<item></item>
<item></item>
<item></item>
</array>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array
name="slide_title">
<!-- Normal init process -->
<item>Let\'s get started...</item>
<item>Closing the wheel</item>
<item>Closing the output container</item>
<item>Adding water</item>
<item>Camera adjustment</item>
<item>Auto-check</item>
<item>Plug-in syringe</item>
<item>Put water into the syringe</item>
<item>Removing air bubbles</item>
<item>Just a moment</item>
<item>You\'re all set !</item>
</array>
<array
name="slide_text">
<item>...with a small initialization process\n\nIt only takes a few steps</item>
<item>First, place the wheel, then add the cover and ensure it\'s correctly closed</item>
<item>Insert the filter in the container\n\nTurn the lid to insure the circuit isolation</item>
<item>Fill the clean water tank located behind the sorting wheel\n\nPut the two tubes inside\n\nWarning: the system will pressurize automatically at the end of this step!</item>
<item>Rotate the camera module to position it in front of wheel slots</item>
<item>The EggSorter is doing some internal verifications...\n\nPlease wait...</item>
<item>Plug-in and screw the syringe tube,\nto insure the circuit isolation\nKeep the syringe out of its slot, it will reset</item>
<item>Pull the syringe to reach a water level of around 25 ml</item>
<item>Push the syringe while holding it vertically in order to remove the air bubbles inside\n\nPlace the syringe on its slot after the motor has stopped moving\n\nIf there is not enough water inside the syringe and you cannot place it inside the slot, go back to the previous step to fill the syringe again with 25 ml</item>
<item>Finishing dispenser initialization\n\nPlease wait...</item>
<item>Process is ready to start\n\n\nCheck a clean filter is placed at the input\n\nYon can now add a multi-well plate, please ensure that no object are present in the dispensing area\n\nYou can now insert your eggs into the device</item>
</array>
<array
name="slide_gif">
<item></item>
<item>@drawable/slide1</item>
<item>@drawable/slide2</item>
<item>@drawable/slide3</item>
<item>@drawable/slide4</item>
<item></item>
<item>@drawable/slide6</item>
<item>@drawable/slide7</item>
<item>@drawable/slide8</item>
</array>
<array
name="auto_check_tests_titles">
<item>Checking for LED state.</item>
<item>Checking for lens placement.</item>
<item>Adjustment of wheel position.</item>
<item>Checking for water level.</item>
<item>The Egg Sorter is ready.</item>
</array>
<array
name="auto_check_tests_desc">
<item>The LED seems to be off, or something is blocking the visibility between the camera and the LED, please check it.</item>
<item>The lens seems to not be in place, please align it with the wheel.</item>
<item>The wheel is adjusting its position...</item>
<item>The water level is finishing its adjustment</item>
<item></item>
</array>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array
name="slide_title">
<!-- Normal init process -->
<item>Let\'s get started...</item>
<item>Closing the wheel</item>
<item>Closing the output container</item>
<item>Adding water</item>
<item>Camera adjustment</item>
<item>Auto-check</item>
<item>Plug-in syringe</item>
<item>Put water into the syringe</item>
<item>Removing air bubbles</item>
<item>Just a moment</item>
<item>You\'re all set !</item>
</array>
<array
name="slide_text">
<item>...with a small initialization process\n\nIt only takes a few steps</item>
<item>First, place the wheel, then add the cover and ensure it\'s correctly closed</item>
<item>Insert the filter in the container\n\nTurn the lid to insure the circuit isolation</item>
<item>Fill the clean water tank located behind the sorting wheel\n\nPut the two tubes inside\n\nWarning: the system will pressurize automatically at the end of this step!</item>
<item>Rotate the camera module to position it in front of wheel slots</item>
<item>The EggSorter is doing some internal verifications...\n\nPlease wait...</item>
<item>Plug-in and screw the syringe tube,\nto insure the circuit isolation\nKeep the syringe out of its slot, it will reset</item>
<item>Pull the syringe to reach a water level of around 25 ml</item>
<item>Push the syringe while holding it vertically in order to remove the air bubbles inside\n\nPlace the syringe on its slot after the motor has stopped moving\n\nIf there is not enough water inside the syringe and you cannot place it inside the slot, go back to the previous step to fill the syringe again with 25 ml</item>
<item>Finishing dispenser initialization\n\nPlease wait...</item>
<item>Process is ready to start\n\n\nCheck a clean filter is placed at the input\n\nYon can now add a multi-well plate, please ensure that no object are present in the dispensing area\n\nYou can now insert your eggs into the device</item>
</array>
<array
name="slide_gif">
<item></item>
<item>@drawable/slide1</item>
<item>@drawable/slide2</item>
<item>@drawable/slide3</item>
<item>@drawable/slide4</item>
<item></item>
<item>@drawable/slide6</item>
<item>@drawable/slide7</item>
<item>@drawable/slide8</item>
</array>
<array
name="auto_check_tests_titles">
<item>Checking for LED state.</item>
<item>Checking for lens placement.</item>
<item>Adjustment of wheel position.</item>
<item>Checking for water level.</item>
<item>The Egg Sorter is ready.</item>
</array>
<array
name="auto_check_tests_desc">
<item>The LED seems to be off, or something is blocking the visibility between the camera and the LED, please check it.</item>
<item>The lens seems to not be in place, please align it with the wheel.</item>
<item>The wheel is adjusting its position...</item>
<item>The water level is finishing its adjustment</item>
<item></item>
</array>
</resources>
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega