I made a java implementation of the new perceptualy uniform color space JzAzBz. OSA publication is : https://www.osapublishing.org/oe/fulltext.cfm?uri=oe-25-13-15131&id=368272.
My java code is :
private double b = 1.15;
private double g = 0.66;
private double c1 = 3424 / Math.pow(2, 12);
private double c2 = 2413 / Math.pow(2, 7);
private double c3 = 2392 / Math.pow(2, 7);
private double n = 2610 / Math.pow(2, 14);
private double p = 1.7 * 2523 / Math.pow(2, 5);
private double d = -0.56;
private double d0 = 1.6295499532821566 * Math.pow(10, -11);
public void XYZToJab(double[] xyz, double[] jab) {
double[] XYZp = new double[3];
XYZp[0] = b * xyz[0] - ((b - 1) * xyz[2]);
XYZp[1] = g * xyz[1] - ((g - 1) * xyz[0]);
XYZp[2] = xyz[2];
double[] LMS = new double[3];
LMS[0] = 0.41478972 * XYZp[0] + 0.579999 * XYZp[1] + 0.0146480 * XYZp[2];
LMS[1] = -0.2015100 * XYZp[0] + 1.120649 * XYZp[1] + 0.0531008 * XYZp[2];
LMS[2] = -0.0166008 * XYZp[0] + 0.264800 * XYZp[1] + 0.6684799 * XYZp[2];
double[] LMSp = new double[3];
for (int i = 0; i < 3; i++) {
LMSp[i] = Math.pow((c1 + c2 * Math.pow((LMS[i] / 10000.0), n)) / (1 + c3 * Math.pow((LMS[i] / 10000.0), n)), p);
}
double[] Iab = new double[3];
Iab[0] = 0.5 * LMSp[0] + 0.5 * LMSp[1];
Iab[1] = 3.524000 * LMSp[0] - 4.066708 * LMSp[1] + 0.542708 * LMSp[2];
Iab[2] = 0.199076 * LMSp[0] + 1.096799 * LMSp[1] - 1.295875 * LMSp[2];
jab[0] = (((1 + d) * Iab[0]) / (1 + d * Iab[0])) - d0;
jab[1] = Iab[1];
jab[2] = Iab[2];
}
public void JabToXYZ(double[] jab, double[] xyz) {
double[] Iab = new double[3];
Iab[0] = (jab[0] + d0) / (1 + d - d * (jab[0] + d0));
Iab[1] = jab[1];
Iab[2] = jab[2];
double[] LMSp = new double[3];
LMSp[0] = 1.0 * Iab[0] + 0.13860504 * Iab[1] + 0.05804732 * Iab[2];
LMSp[1] = 1.0 * Iab[0] - 0.13860504 * Iab[1] - 0.05804732 * Iab[2];
LMSp[2] = 1.0 * Iab[0] - 0.09601924 * Iab[1] - 0.81189190 * Iab[2];
double[] LMS = new double[3];
for (int i = 0; i < 3; i++) {
LMS[i] = 10000 * Math.pow((c1 - Math.pow(LMSp[i], 1 / p)) / ((c3 * Math.pow(LMSp[i], 1 / p)) - c2), 1 / n);
}
double[] XYZp = new double[3];
XYZp[0] = 1.92422644 * LMS[0] - 1.00479231 * LMS[1] + 0.03765140 * LMS[2];
XYZp[1] = 0.35031676 * LMS[0] + 0.72648119 * LMS[1] - 0.06538442 * LMS[2];
XYZp[2] = -0.09098281 * LMS[0] - 0.31272829 * LMS[1] + 1.52276656 * LMS[2];
xyz[0] = (XYZp[0] + (b - 1) * XYZp[2]) / b;
xyz[1] = (XYZp[1] + (g - 1) * XYZp[0]) / g;
xyz[2] = XYZp[2];
}
When I test it running XYZToJab and then JabToXYZ I get a good precision for X and Z (delta order is E-9) but for Y I get a bad precision (delta order is 1-5%).
Is there anyone who can help me ?
The implementation is almost correct: The error lies in JabToXYZ where the prior to last line should be changed from
(XYZp[1] + (g - 1) * XYZp[0]) / g;
to
(XYZp[1] + (g - 1) * xyz[0]) / g;
However the fact that you are using rounded invert matrices to 6 decimal places in the JabToXYZ function will prevent you to get a clean inversion. You should try to compute the inverse at full double precision:
>>> import numpy as np
>>> np.set_printoptions(formatter={'float': '{:0.15f}'.format})
>>> import colour.models.jzazbz
>>> colour.models.jzazbz.JZAZBZ_IZAZBZ_TO_LMS_P_MATRIX
array([[1.000000000000000, 0.138605043271539, 0.058047316156119],
[1.000000000000000, -0.138605043271539, -0.058047316156119],
[1.000000000000000, -0.096019242026319, -0.811891896056039]])
>>> colour.models.jzazbz.JZAZBZ_LMS_TO_XYZ_MATRIX
array([[1.924226435787607, -1.004792312595365, 0.037651404030618],
[0.350316762094999, 0.726481193931655, -0.065384422948085],
[-0.090982810982848, -0.312728290523074, 1.522766561305260]])
My friend and I was having a lot of trouble trying to implement the perceptron algorithm, but then I found this tutorial, it goes through a java implementation and then has some example code. I substituted my own data structures for there ones in the tutorial, and it works! :)
HOWEVER
I made this substitution in the most simplistic possible way, manually enumerating my data structures. This works as a proof of concept, for my experimental "toy" data, but most certainly is not able to tackle the real data I want to consider. It's far too rigid.
Perhaps someone more proficient in abstract thinking and loops would be able to show me how I can improve this code.
The important data structure to consider is Map<File, int[] >, it looks like this:
/data/test/sports/t.s_1.txt, [0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0]
/data/test/politics/t.p_0.txt, [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
/data/test/atheism/t.a_0.txt, [0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
/data/test/science/t.s_0.txt, [1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0]
The code that needs to be generalized proceeds this sentence, you can also find the full programme on this github page.
Thank you for your consideration & happy Japanese/Chinese new year!
public static void perceptron( Set<String> GLOBO_DICT, Map<File, int[] > training_perceptron_input, Map<File, int[] > test_perceptron_input)
{
//number of features, number of x, y, z
int size_of_globo_dict = GLOBO_DICT.size();
//number of instances
int NUM_INSTANCES = training_perceptron_input.size();
//three variables (features) they enumerate by
//features, xyz, i also do that
double[] a00 = new double [NUM_INSTANCES];
double[] a01 = new double [NUM_INSTANCES];
double[] a02 = new double [NUM_INSTANCES];
double[] a03 = new double [NUM_INSTANCES];
double[] a04 = new double [NUM_INSTANCES];
double[] a05 = new double [NUM_INSTANCES];
double[] a06 = new double [NUM_INSTANCES];
double[] a07 = new double [NUM_INSTANCES];
double[] a08 = new double [NUM_INSTANCES];
double[] a09 = new double [NUM_INSTANCES];
double[] a10 = new double [NUM_INSTANCES];
double[] a11 = new double [NUM_INSTANCES];
double[] a12 = new double [NUM_INSTANCES];
double[] a13 = new double [NUM_INSTANCES];
double[] a14 = new double [NUM_INSTANCES];
double[] a15 = new double [NUM_INSTANCES];
double[] a16 = new double [NUM_INSTANCES];
double[] a17 = new double [NUM_INSTANCES];
double[] a18 = new double [NUM_INSTANCES];
double[] a19 = new double [NUM_INSTANCES];
double[] a20 = new double [NUM_INSTANCES];
double[] a21 = new double [NUM_INSTANCES];
double[] a22 = new double [NUM_INSTANCES];
double[] a23 = new double [NUM_INSTANCES];
double[] a24 = new double [NUM_INSTANCES];
double[] a25 = new double [NUM_INSTANCES];
double[] a26 = new double [NUM_INSTANCES];
double[] a27 = new double [NUM_INSTANCES];
double[] a28 = new double [NUM_INSTANCES];
double[] a29 = new double [NUM_INSTANCES];
double[] a30 = new double [NUM_INSTANCES];
//2d array for features
int x = 0;
int[][] feature_matrix = new int[ training_perceptron_input.size() ][ GLOBO_DICT.size() ];
String[][] output_label = new String[ training_perceptron_input.size() ][ 2 ];
for(Entry<File, int[]> entry : training_perceptron_input.entrySet())
{
int[] container =entry.getValue();
for(int j = 0; j < 4; j++)
{
feature_matrix[x][j] = container[j];
output_label[x][1] = entry.getKey().toString();
}
x++;
}
int[] outputs = new int [NUM_INSTANCES];
for(int g = 0; g < NUM_INSTANCES; g++)
{
a00[g] = feature_matrix[g][ 0];
a01[g] = feature_matrix[g][ 1];
a02[g] = feature_matrix[g][ 2];
a03[g] = feature_matrix[g][ 3];
a04[g] = feature_matrix[g][ 4];
a05[g] = feature_matrix[g][ 5];
a06[g] = feature_matrix[g][ 6];
a07[g] = feature_matrix[g][ 7];
a08[g] = feature_matrix[g][ 8];
a09[g] = feature_matrix[g][ 9];
a10[g] = feature_matrix[g][10];
a11[g] = feature_matrix[g][11];
a12[g] = feature_matrix[g][12];
a13[g] = feature_matrix[g][13];
a14[g] = feature_matrix[g][14];
a15[g] = feature_matrix[g][15];
a16[g] = feature_matrix[g][16];
a17[g] = feature_matrix[g][17];
a18[g] = feature_matrix[g][18];
a19[g] = feature_matrix[g][19];
a20[g] = feature_matrix[g][20];
a21[g] = feature_matrix[g][21];
a22[g] = feature_matrix[g][22];
a23[g] = feature_matrix[g][23];
a24[g] = feature_matrix[g][24];
a25[g] = feature_matrix[g][25];
a26[g] = feature_matrix[g][26];
a27[g] = feature_matrix[g][27];
a28[g] = feature_matrix[g][28];
a29[g] = feature_matrix[g][29];
a30[g] = feature_matrix[g][30];
if(output_label[g][1].equals( "/home/yamada/Workbench/SUTD/ISTD_50.570/assignments/practice_data/data/train/atheism/a_0.txt" ) )
{
outputs[g] = 1;
}
else
{
outputs[g] = 0;
}
}
double[] weights = new double[ GLOBO_DICT.size() + 1];// 32 for input variables and one for bias
double localError, globalError;
int i, p, iteration, output;
weights[ 0] = randomNumber(0,1);// w1
weights[ 1] = randomNumber(0,1);// w2
weights[ 2] = randomNumber(0,1);// w3
weights[ 3] = randomNumber(0,1);// w4
weights[ 4] = randomNumber(0,1);// w5
weights[ 5] = randomNumber(0,1);// w6
weights[ 6] = randomNumber(0,1);// w7
weights[ 7] = randomNumber(0,1);// w8
weights[ 8] = randomNumber(0,1);// w9
weights[ 9] = randomNumber(0,1);// w10
weights[10] = randomNumber(0,1);// w11
weights[11] = randomNumber(0,1);// w12
weights[12] = randomNumber(0,1);// w13
weights[13] = randomNumber(0,1);// w14
weights[14] = randomNumber(0,1);// w15
weights[15] = randomNumber(0,1);// w16
weights[16] = randomNumber(0,1);// w17
weights[17] = randomNumber(0,1);// w18
weights[18] = randomNumber(0,1);// w19
weights[19] = randomNumber(0,1);// w20
weights[20] = randomNumber(0,1);// w21
weights[21] = randomNumber(0,1);// w22
weights[22] = randomNumber(0,1);// w23
weights[23] = randomNumber(0,1);// w24
weights[24] = randomNumber(0,1);// w25
weights[25] = randomNumber(0,1);// w26
weights[26] = randomNumber(0,1);// w27
weights[27] = randomNumber(0,1);// w28
weights[28] = randomNumber(0,1);// w29
weights[29] = randomNumber(0,1);// w30
weights[30] = randomNumber(0,1);// w31
weights[31] = randomNumber(0,1);// this is the bias
iteration = 0;
do {
iteration++;
globalError = 0;
//loop through all instances (complete one epoch)
for (p = 0; p < NUM_INSTANCES; p++)
{
// calculate predicted class
output = calculateOutput(theta,
weights,
a00[p],
a01[p],
a02[p],
a03[p],
a04[p],
a05[p],
a06[p],
a07[p],
a08[p],
a09[p],
a10[p],
a11[p],
a12[p],
a13[p],
a14[p],
a15[p],
a16[p],
a17[p],
a18[p],
a19[p],
a20[p],
a21[p],
a22[p],
a23[p],
a24[p],
a25[p],
a26[p],
a27[p],
a28[p],
a29[p],
a30[p]);
// difference between predicted and actual class values
localError = outputs[p] - output;
//update weights and bias
weights[ 0] += LEARNING_RATE * localError * a00[p];
weights[ 1] += LEARNING_RATE * localError * a01[p];
weights[ 2] += LEARNING_RATE * localError * a02[p];
weights[ 3] += LEARNING_RATE * localError * a03[p];
weights[ 4] += LEARNING_RATE * localError * a04[p];
weights[ 5] += LEARNING_RATE * localError * a05[p];
weights[ 6] += LEARNING_RATE * localError * a06[p];
weights[ 7] += LEARNING_RATE * localError * a07[p];
weights[ 8] += LEARNING_RATE * localError * a08[p];
weights[ 9] += LEARNING_RATE * localError * a09[p];
weights[10] += LEARNING_RATE * localError * a10[p];
weights[11] += LEARNING_RATE * localError * a11[p];
weights[12] += LEARNING_RATE * localError * a12[p];
weights[13] += LEARNING_RATE * localError * a13[p];
weights[14] += LEARNING_RATE * localError * a14[p];
weights[15] += LEARNING_RATE * localError * a15[p];
weights[16] += LEARNING_RATE * localError * a16[p];
weights[17] += LEARNING_RATE * localError * a17[p];
weights[18] += LEARNING_RATE * localError * a18[p];
weights[19] += LEARNING_RATE * localError * a19[p];
weights[20] += LEARNING_RATE * localError * a20[p];
weights[21] += LEARNING_RATE * localError * a21[p];
weights[22] += LEARNING_RATE * localError * a22[p];
weights[23] += LEARNING_RATE * localError * a23[p];
weights[24] += LEARNING_RATE * localError * a24[p];
weights[25] += LEARNING_RATE * localError * a25[p];
weights[26] += LEARNING_RATE * localError * a26[p];
weights[27] += LEARNING_RATE * localError * a27[p];
weights[28] += LEARNING_RATE * localError * a28[p];
weights[29] += LEARNING_RATE * localError * a29[p];
weights[30] += LEARNING_RATE * localError * a30[p];
weights[31] += LEARNING_RATE * localError;
//summation of squared error (error value for all instances)
globalError += (localError*localError);
}
/* Root Mean Squared Error */
System.out.println("Iteration "+iteration+" : RMSE = "+Math.sqrt(globalError/NUM_INSTANCES));
}
while (globalError != 0 && iteration <= MAX_ITER);
System.out.println("\n=======\nDecision boundary equation:");
System.out.println(
" a00 *" +
weights[ 0] +
" a01 *" +
weights[ 1] +
" a02 *" +
weights[ 2] +
" a03 *" +
weights[ 3] +
" a04 *" +
weights[ 4] +
" a05 *" +
weights[ 5] +
" a06 *" +
weights[ 6] +
" a07 *" +
weights[ 7] +
" a08 *" +
weights[ 8] +
" a09 *" +
weights[ 9] +
" a10 *" +
weights[10] +
" a11 *" +
weights[11] +
" a12 *" +
weights[12] +
" a13 *" +
weights[13] +
" a14 *" +
weights[14] +
" a15 *" +
weights[15] +
" a16 *" +
weights[16] +
" a17 *" +
weights[17] +
" a18 *" +
weights[18] +
" a19 *" +
weights[19] +
" a20 *" +
weights[20] +
" a21 *" +
weights[21] +
" a22 *" +
weights[22] +
" a23 *" +
weights[23] +
" a24 *" +
weights[24] +
" a25 *" +
weights[25] +
" a26 *" +
weights[26] +
" a27 *" +
weights[27] +
" a28 *" +
weights[28] +
" a29 *" +
weights[29] +
" a30 *" +
weights[30] +
" bias: " +
weights[31]);
//2d array for features
int x_TEST = 0;
int[][] feature_matrix_TEST = new int[ test_perceptron_input.size() ][ GLOBO_DICT.size() ];
for(Entry<File, int[]> entry : test_perceptron_input.entrySet())
{
int[] container =entry.getValue();
for(int jj = 0; jj < 4; jj++)
{
feature_matrix_TEST[x_TEST][jj] = container[jj];
}
x_TEST++;
}
//three variables (features) they enumerate by
//features, xyz, i also do that
double[] z00 = new double [NUM_INSTANCES];
double[] z01 = new double [NUM_INSTANCES];
double[] z02 = new double [NUM_INSTANCES];
double[] z03 = new double [NUM_INSTANCES];
double[] z04 = new double [NUM_INSTANCES];
double[] z05 = new double [NUM_INSTANCES];
double[] z06 = new double [NUM_INSTANCES];
double[] z07 = new double [NUM_INSTANCES];
double[] z08 = new double [NUM_INSTANCES];
double[] z09 = new double [NUM_INSTANCES];
double[] z10 = new double [NUM_INSTANCES];
double[] z11 = new double [NUM_INSTANCES];
double[] z12 = new double [NUM_INSTANCES];
double[] z13 = new double [NUM_INSTANCES];
double[] z14 = new double [NUM_INSTANCES];
double[] z15 = new double [NUM_INSTANCES];
double[] z16 = new double [NUM_INSTANCES];
double[] z17 = new double [NUM_INSTANCES];
double[] z18 = new double [NUM_INSTANCES];
double[] z19 = new double [NUM_INSTANCES];
double[] z20 = new double [NUM_INSTANCES];
double[] z21 = new double [NUM_INSTANCES];
double[] z22 = new double [NUM_INSTANCES];
double[] z23 = new double [NUM_INSTANCES];
double[] z24 = new double [NUM_INSTANCES];
double[] z25 = new double [NUM_INSTANCES];
double[] z26 = new double [NUM_INSTANCES];
double[] z27 = new double [NUM_INSTANCES];
double[] z28 = new double [NUM_INSTANCES];
double[] z29 = new double [NUM_INSTANCES];
double[] z30 = new double [NUM_INSTANCES];
for(int g = 0; g < NUM_INSTANCES; g++)
{
z00[g] = feature_matrix_TEST[g][ 0];
z01[g] = feature_matrix_TEST[g][ 1];
z02[g] = feature_matrix_TEST[g][ 2];
z03[g] = feature_matrix_TEST[g][ 3];
z04[g] = feature_matrix_TEST[g][ 4];
z05[g] = feature_matrix_TEST[g][ 5];
z06[g] = feature_matrix_TEST[g][ 6];
z07[g] = feature_matrix_TEST[g][ 7];
z08[g] = feature_matrix_TEST[g][ 8];
z09[g] = feature_matrix_TEST[g][ 9];
z10[g] = feature_matrix_TEST[g][10];
z11[g] = feature_matrix_TEST[g][11];
z12[g] = feature_matrix_TEST[g][12];
z13[g] = feature_matrix_TEST[g][13];
z14[g] = feature_matrix_TEST[g][14];
z15[g] = feature_matrix_TEST[g][15];
z16[g] = feature_matrix_TEST[g][16];
z17[g] = feature_matrix_TEST[g][17];
z18[g] = feature_matrix_TEST[g][18];
z19[g] = feature_matrix_TEST[g][19];
z20[g] = feature_matrix_TEST[g][20];
z21[g] = feature_matrix_TEST[g][21];
z22[g] = feature_matrix_TEST[g][22];
z23[g] = feature_matrix_TEST[g][23];
z24[g] = feature_matrix_TEST[g][24];
z25[g] = feature_matrix_TEST[g][25];
z26[g] = feature_matrix_TEST[g][26];
z27[g] = feature_matrix_TEST[g][27];
z28[g] = feature_matrix_TEST[g][28];
z29[g] = feature_matrix_TEST[g][29];
z30[g] = feature_matrix_TEST[g][30];
}
int output_TEST;
// calculate predicted class TEST
output_TEST = calculateOutput(theta,
weights,
z00[2],
z01[2],
z02[2],
z03[2],
z04[2],
z05[2],
z06[2],
z07[2],
z08[2],
z09[2],
z10[2],
z11[2],
z12[2],
z13[2],
z14[2],
z15[2],
z16[2],
z17[2],
z18[2],
z19[2],
z20[2],
z21[2],
z22[2],
z23[2],
z24[2],
z25[2],
z26[2],
z27[2],
z28[2],
z29[2],
z30[2]);
System.out.println("\n=======\nTEST Point:");
System.out.println(
"z00[0]:" + z00[0] +
"z01[0]:" + z01[0] +
"z02[0]:" + z02[0] +
"z03[0]:" + z03[0] +
"z04[0]:" + z04[0] +
"z05[0]:" + z05[0] +
"z06[0]:" + z06[0] +
"z07[0]:" + z07[0] +
"z08[0]:" + z08[0] +
"z09[0]:" + z09[0] +
"z10[0]:" + z10[0] +
"z11[0]:" + z11[0] +
"z12[0]:" + z12[0] +
"z13[0]:" + z13[0] +
"z14[0]:" + z14[0] +
"z15[0]:" + z15[0] +
"z16[0]:" + z16[0] +
"z17[0]:" + z17[0] +
"z18[0]:" + z18[0] +
"z19[0]:" + z19[0] +
"z20[0]:" + z20[0] +
"z21[0]:" + z21[0] +
"z22[0]:" + z22[0] +
"z23[0]:" + z23[0] +
"z24[0]:" + z24[0] +
"z25[0]:" + z25[0] +
"z26[0]:" + z26[0] +
"z27[0]:" + z27[0] +
"z28[0]:" + z28[0] +
"z29[0]:" + z29[0] +
"z30[0]:" + z30[0]
);
System.out.println("class = "+output_TEST);
}
//end main
/**
* returns a random double value within a given range
* #param min the minimum value of the required range (int)
* #param max the maximum value of the required range (int)
* #return a random double value between min and max
*/
public static double randomNumber(int min , int max) {
DecimalFormat df = new DecimalFormat("#.####");
double d = min + Math.random() * (max - min);
String s = df.format(d);
double x = Double.parseDouble(s);
return x;
}
/**
* returns either 1 or 0 using a threshold function
* theta is 0range
* #param theta an integer value for the threshold
* #param weights[] the array of weights
* #param x the x input value
* #param y the y input value
* #param z the z input value
* #return 1 or 0
*/
static int calculateOutput(int theta,
double weights[],
double a00,
double a01,
double a02,
double a03,
double a04,
double a05,
double a06,
double a07,
double a08,
double a09,
double a10,
double a11,
double a12,
double a13,
double a14,
double a15,
double a16,
double a17,
double a18,
double a19,
double a20,
double a21,
double a22,
double a23,
double a24,
double a25,
double a26,
double a27,
double a28,
double a29,
double a30)
{
double sum = a00 *
weights[ 0] +
a01 *
weights[ 1] +
a02 *
weights[ 2] +
a03 *
weights[ 3] +
a04 *
weights[ 4] +
a05 *
weights[ 5] +
a06 *
weights[ 6] +
a07 *
weights[ 7] +
a08 *
weights[ 8] +
a09 *
weights[ 9] +
a10 *
weights[10] +
a11 *
weights[11] +
a12 *
weights[12] +
a13 *
weights[13] +
a14 *
weights[14] +
a15 *
weights[15] +
a16 *
weights[16] +
a17 *
weights[17] +
a18 *
weights[18] +
a19 *
weights[19] +
a20 *
weights[20] +
a21 *
weights[21] +
a22 *
weights[22] +
a23 *
weights[23] +
a24 *
weights[24] +
a25 *
weights[25] +
a26 *
weights[26] +
a27 *
weights[27] +
a28 *
weights[28] +
a29 *
weights[29] +
a30 *
weights[30] +
weights[31];
return (sum >= theta) ? 1 : 0;
}
}
Here is a more generalized version your Perceptron class, simplified to reduce code duplication. Though untested, this is mechanically equivalent to the code you presented in your question.
class Perceptron {
static final int MAX_ITER = 100;
static final double LEARNING_RATE = 0.1;
static final int THETA = 0;
static final String FILEPATH =
"/home/yamada/Workbench/SUTD/ISTD_50.570/assignments/practice_data/data/train/atheism/a_0.txt";
public static void perceptron(Set<String> globoDict,
Map<File, int[]> trainingPerceptronInput,
Map<File, int[]> testPerceptronInput)
{
final int globoDictSize = globoDict.size(); // number of features (x, y, z)
// weights total 32 (31 for input variables and one for bias)
double[] weights = new double[globoDictSize + 1];
for (int i = 0; i < weights.length; i++) {
weights[i] = Math.floor(Math.random() * 10000) / 10000;
}
int inputSize = trainingPerceptronInput.size();
int[] outputs = new int[inputSize];
final double[][] a =
initializeOutput(trainingPerceptronInput, globoDictSize, outputs);
double globalError;
int iteration = 0;
do {
iteration++;
globalError = 0;
// loop through all instances (complete one epoch)
for (int p = 0; p < inputSize; p++) {
// calculate predicted class
int output = calculateOutput(THETA, weights, a, p);
// difference between predicted and actual class values
double localError = outputs[p] - output;
int i;
for (i = 0; i < a.length; i++) {
weights[i] += LEARNING_RATE * localError * a[i][p];
}
weights[i] += LEARNING_RATE * localError;
// summation of squared error (error value for all instances)
globalError += localError * localError;
}
/* Root Mean Squared Error */
System.out.println("Iteration "
+ iteration + " : RMSE = " + Math.sqrt(globalError
/ inputSize));
} while (globalError != 0 && iteration <= MAX_ITER);
System.out.println("\n=======\nDecision boundary equation:");
int i;
for (i = 0; i < a.length; i++) {
System.out.print(" a");
if (i < 10) System.out.print(0);
System.out.print(i + " *" + weights[i]);
}
System.out.println(" bias: " + weights[i]);
inputSize = testPerceptronInput.size();
outputs = new int[inputSize];
double[][] z = initializeOutput(testPerceptronInput, globoDictSize, outputs);
// calculate predicted class TEST
int output = calculateOutput(THETA, weights, z, 2);
System.out.println("\n=======\nTEST Point:");
for (i = 0; i < z.length; i++) {
System.out.print(" z");
if (i < 10) System.out.print(0);
System.out.print(i + "[0]" + z[i][0]);
}
System.out.println();
System.out.println("class = " + output);
}
static double[][] initializeOutput(
Map<File, int[]> perceptronInput, int size, int[] outputs)
{
final int inputSize = perceptronInput.size();
final double[][] a = new double[size][inputSize];
// 2d array for features
int[][] feature_matrix = new int[inputSize][size];
String[] output_label = new String[inputSize];
int x = 0;
for (Entry<File, int[]> entry : perceptronInput.entrySet()) {
int[] container = entry.getValue();
for (int j = 0; j < container.length; j++) {
feature_matrix[x][j] = container[j];
output_label[x] = String.valueOf(entry.getKey());
}
x++;
}
for (x = 0; x < inputSize; x++) {
for (int i = 0; i < a.length; i++) {
a[i][x] = feature_matrix[x][i];
}
outputs[x] = output_label[x].equals(FILEPATH) ? 1 : 0;
}
return a;
}
/**
* returns either 1 or 0 using a threshold function
* theta is 0range
* #param theta an integer value for the threshold
* #param weights the array of weights
* #param a the array of inputs
* #return 1 or 0
*/
static int calculateOutput(int theta, double[] weights, double[][] a, int index)
{
double sum = 0;
int i;
for (i = 0; i < a.length; i++) {
sum += weights[i] * a[i][index];
}
sum += weights[i];
return (sum >= theta) ? 1 : 0;
}
}
I hope this is instructional for you.
I have a question regarding java's initializing, and I do not know why java thinks that the double in my program is not initialized, even though I have initialized it. Can someone please explain to me how to resolve this problem? In the code below, java says that double "inC" is not initialized.
package tempconverter;
import java.awt.Color;
import javax.swing.*;
import java.awt.event.*;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.BorderLayout;
public class TempConverter extends JFrame implements ActionListener, ItemListener
{
static String[] choices = { "From Celsius", "From Fahrenheit", "From Kelvin", "From Rankine" };
static JFrame f = new JFrame("Temperature Converter");
static JTextField enter = new JTextField(5);
static JButton confirm = new JButton("Convert");
static JComboBox choose = new JComboBox(choices);
static JFrame tell = new JFrame();
static JLabel one = new JLabel();
static JLabel two = new JLabel();
static JLabel three = new JLabel();
public static void main(String[] args)
{
Font main = new Font("Comic Sans", Font.PLAIN, 12);
confirm.addActionListener(new TempConverter());
confirm.setFont(main);
choose.setFont(main);
enter.setFont(main);
choose.addItemListener(new TempConverter());
f.setBackground(Color.WHITE);
f.setLayout(new FlowLayout());
f.setSize(340, 60);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(enter);
f.add(confirm);
f.add(choose);
tell.setLayout(new BorderLayout());
tell.add(one, BorderLayout.NORTH);
tell.add(two, BorderLayout.WEST);
tell.add(three, BorderLayout.SOUTH);
tell.setSize(160, 65);
tell.setLocationRelativeTo(null);
f.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e)
{
double toConvert = Double.parseDouble(enter.getText());
double inF, inK, inC, tempF = 0, tempK, inR, tempR;
double tempC;
if (choose.getSelectedItem().equals("From Celsius"))
{
tempF = toConvert * 1.8 + 32;
tempK = toConvert + 273.15;
tempR = (toConvert + 273.15) * 1.8;
inF = Math.round(tempF * 100.00) / 100.00;
inK = Math.round(tempK * 100.00) / 100.00;
inR = Math.round(tempR * 100.00) / 100.00;
one.setText(toConvert + "°C = " + inF + "°F");
two.setText(toConvert + "°C = " + inK + "°K");
three.setText(toConvert + "°C = " + inR + "°R");
tell.setVisible(true);
}
if (choose.getSelectedItem().equals("From Fahrenheit"))
{
if (toConvert == 32)
{
inC = 0;
inK = 273.15;
inR = toConvert + 459.67;
one.setText(toConvert + "°F = " + inC + "°C");
two.setText(toConvert + "°F = " + inK + "°K");
three.setText(toConvert + "°F = " + inR + "°R");
}
else
tempC = (toConvert - 32) / 1.8;
tempK = (toConvert - 32) / 1.8 + 273.15;
tempR = toConvert + 459.67;
inC = Math.round(tempC * 100.00) / 100.00;
inK = Math.round(tempK * 100.00) / 100.00;
inR = Math.round(tempR * 100.00) / 100.00;
one.setText(toConvert + "°F = " + inC + "°C");
two.setText(toConvert + "°F = " + inK + "°K");
three.setText(toConvert + "°F = " + inR + "°R");
tell.setVisible(true);
}
if (choose.getSelectedItem().equals("From Kelvin"))
{
tempC = toConvert - 273.15;
tempF = tempC * 1.8 + 32;
tempR = toConvert * 1.8;
inC = Math.round(tempC * 100.00) / 100.00;
inF = Math.round(tempF * 100.00) / 100.00;
inR = Math.round(tempR * 100.00) / 100.00;
one.setText(toConvert + "°K = " + inC + "°C");
two.setText(toConvert + "°K = " + inF + "°F");
three.setText(toConvert + "°K = " + inR + "°R");
tell.setVisible(true);
}
if (choose.getSelectedItem().equals("From Rankine"))
{
if (toConvert == 0)
{
tempF = toConvert - 459.67;
tempK = toConvert * (5 / 9);
inF = Math.round(tempF * 100.00) / 100.00;
inR = Math.round(tempK * 100.00) / 100.00;
one.setText("0°R = -273.15°C");
two.setText("0°R = " + inF + "°F");
three.setText("0°R = " + inR + "°K");
tell.setVisible(true);
}
else
tempC = (toConvert - 491.67) * (5 / 9);
tempF = toConvert - 459.67;
tempK = toConvert * (5 / 9);
inC = Math.round(tempC * 100.00) / 100.00;
inF = Math.round(tempF * 100.00) / 100.00;
inR = Math.round(tempK * 100.00) / 100.00;
one.setText(toConvert + "°R = " + inC + "°C");
two.setText(toConvert + "°R = " + inF + "°F");
three.setText(toConvert + "°R = " + inR + "°K");
tell.setVisible(true);
}
}
#Override
public void itemStateChanged(ItemEvent e)
{
repaint();
}
}
Java points out that I have not initialized "inC" in the else statement of the "From Fahrenheit" and the "From Rankine" method. However, when I initialize it in the variable declaration, it doesn't change when I try to change it in the if-else statement and the methods. How do I fix this?
I have copied yout example and i get the message at tempC. The reason is a missing } at the else path.
Change :
else
tempC = (toConvert - 491.67) * (5 / 9);
tempF = toConvert - 459.67;
tempK = toConvert * (5 / 9);
inC = Math.round(tempC * 100.00) / 100.00;
inF = Math.round(tempF * 100.00) / 100.00;
inR = Math.round(tempK * 100.00) / 100.00;
one.setText(toConvert + "°R = " + inC + "°C");
two.setText(toConvert + "°R = " + inF + "°F");
three.setText(toConvert + "°R = " + inR + "°K");
tell.setVisible(true);
TO:
else {
tempC = (toConvert - 491.67) * (5 / 9);
tempF = toConvert - 459.67;
tempK = toConvert * (5 / 9);
inC = Math.round(tempC * 100.00) / 100.00;
inF = Math.round(tempF * 100.00) / 100.00;
inR = Math.round(tempK * 100.00) / 100.00;
one.setText(toConvert + "°R = " + inC + "°C");
two.setText(toConvert + "°R = " + inF + "°F");
three.setText(toConvert + "°R = " + inR + "°K");
tell.setVisible(true);
}
As pointed out above the easiest thing would be to simply assign a value to it when you declare it.
The reason that Java thinks that it has not been initialized is that it might actually not have. You only ever assign it a value in one of the 4 outer most if-statements. If none of these four conditions are true, the variable will never be initialized.
And as Jens has also pointed out, you are missing a { after the "else".
The actual cause of the error is dull: you're missing a brace.
But, let's look at tempK = toConvert * (5 / 9);. This will not do what you want since (5 / 9) will evaluate to 0 as the parentheses mean this is evaluated on its own and in integer arithmetic. To solve this, the easiest thing to do is remove the parentheses:
tempK = toConvert * 5 / 9;
so everything is computed in floating point. (Note that * and / have identical precedence).
You make this error a couple of times in your program.
I have an algorithm in JavaScript which I want to transform into Java.
Here is the JavaScript code:
function downScaleCanvas(cv, scale) {
if (!(scale < 1) || !(scale > 0)) throw ('scale must be a positive number <1 ');
var sqScale = scale * scale; // square scale = area of source pixel within target
var sw = cv.width; // source image width
var sh = cv.height; // source image height
var tw = Math.ceil(sw * scale); // target image width
var th = Math.ceil(sh * scale); // target image height
var sx = 0, sy = 0, sIndex = 0; // source x,y, index within source array
var tx = 0, ty = 0, yIndex = 0, tIndex = 0; // target x,y, x,y index within target array
var tX = 0, tY = 0; // rounded tx, ty
var w = 0, nw = 0, wx = 0, nwx = 0, wy = 0, nwy = 0; // weight / next weight x / y
// weight is weight of current source point within target.
// next weight is weight of current source point within next target's point.
var crossX = false; // does scaled px cross its current px right border ?
var crossY = false; // does scaled px cross its current px bottom border ?
var sBuffer = cv.getContext('2d').getImageData(0, 0, sw, sh).data; // source buffer 8 bit rgba
var tBuffer = new Float32Array(4 * sw * sh); // target buffer Float32 rgb
var sR = 0, sG = 0, sB = 0; // source's current point r,g,b
// untested !
var sA = 0; //source alpha
for (sy = 0; sy < sh; sy++) {
ty = sy * scale; // y src position within target
tY = 0 | ty; // rounded : target pixel's y
yIndex = 4 * tY * tw; // line index within target array
crossY = (tY != (0 | ty + scale));
if (crossY) { // if pixel is crossing botton target pixel
wy = (tY + 1 - ty); // weight of point within target pixel
nwy = (ty + scale - tY - 1); // ... within y+1 target pixel
}
for (sx = 0; sx < sw; sx++, sIndex += 4) {
tx = sx * scale; // x src position within target
tX = 0 | tx; // rounded : target pixel's x
tIndex = yIndex + tX * 4; // target pixel index within target array
crossX = (tX != (0 | tx + scale));
if (crossX) { // if pixel is crossing target pixel's right
wx = (tX + 1 - tx); // weight of point within target pixel
nwx = (tx + scale - tX - 1); // ... within x+1 target pixel
}
sR = sBuffer[sIndex ]; // retrieving r,g,b for curr src px.
sG = sBuffer[sIndex + 1];
sB = sBuffer[sIndex + 2];
sA = sBuffer[sIndex + 3];
if (!crossX && !crossY) { // pixel does not cross
// just add components weighted by squared scale.
tBuffer[tIndex ] += sR * sqScale;
tBuffer[tIndex + 1] += sG * sqScale;
tBuffer[tIndex + 2] += sB * sqScale;
tBuffer[tIndex + 3] += sA * sqScale;
} else if (crossX && !crossY) { // cross on X only
w = wx * scale;
// add weighted component for current px
tBuffer[tIndex ] += sR * w;
tBuffer[tIndex + 1] += sG * w;
tBuffer[tIndex + 2] += sB * w;
tBuffer[tIndex + 3] += sA * w;
// add weighted component for next (tX+1) px
nw = nwx * scale;
tBuffer[tIndex + 4] += sR * nw; // not 3
tBuffer[tIndex + 5] += sG * nw; // not 4
tBuffer[tIndex + 6] += sB * nw; // not 5
tBuffer[tIndex + 7] += sA * nw; // not 6
} else if (crossY && !crossX) { // cross on Y only
w = wy * scale;
// add weighted component for current px
tBuffer[tIndex ] += sR * w;
tBuffer[tIndex + 1] += sG * w;
tBuffer[tIndex + 2] += sB * w;
tBuffer[tIndex + 3] += sA * w;
// add weighted component for next (tY+1) px
nw = nwy * scale;
tBuffer[tIndex + 4 * tw ] += sR * nw; // *4, not 3
tBuffer[tIndex + 4 * tw + 1] += sG * nw; // *4, not 3
tBuffer[tIndex + 4 * tw + 2] += sB * nw; // *4, not 3
tBuffer[tIndex + 4 * tw + 3] += sA * nw; // *4, not 3
} else { // crosses both x and y : four target points involved
// add weighted component for current px
w = wx * wy;
tBuffer[tIndex ] += sR * w;
tBuffer[tIndex + 1] += sG * w;
tBuffer[tIndex + 2] += sB * w;
tBuffer[tIndex + 3] += sA * w;
// for tX + 1; tY px
nw = nwx * wy;
tBuffer[tIndex + 4] += sR * nw; // same for x
tBuffer[tIndex + 5] += sG * nw;
tBuffer[tIndex + 6] += sB * nw;
tBuffer[tIndex + 7] += sA * nw;
// for tX ; tY + 1 px
nw = wx * nwy;
tBuffer[tIndex + 4 * tw ] += sR * nw; // same for mul
tBuffer[tIndex + 4 * tw + 1] += sG * nw;
tBuffer[tIndex + 4 * tw + 2] += sB * nw;
tBuffer[tIndex + 4 * tw + 3] += sA * nw;
// for tX + 1 ; tY +1 px
nw = nwx * nwy;
tBuffer[tIndex + 4 * tw + 4] += sR * nw; // same for both x and y
tBuffer[tIndex + 4 * tw + 5] += sG * nw;
tBuffer[tIndex + 4 * tw + 6] += sB * nw;
tBuffer[tIndex + 4 * tw + 7] += sA * nw;
}
} // end for sx
} // end for sy
// create result canvas
var resCV = document.createElement('canvas');
resCV.width = tw;
resCV.height = th;
var resCtx = resCV.getContext('2d');
var imgRes = resCtx.getImageData(0, 0, tw, th);
var tByteBuffer = imgRes.data;
// convert float32 array into a UInt8Clamped Array
var pxIndex = 0; //
for (sIndex = 0, tIndex = 0; pxIndex < tw * th; sIndex += 4, tIndex += 4, pxIndex++) {
tByteBuffer[tIndex] = Math.ceil(tBuffer[sIndex]);
tByteBuffer[tIndex + 1] = Math.ceil(tBuffer[sIndex + 1]);
tByteBuffer[tIndex + 2] = Math.ceil(tBuffer[sIndex + 2]);
tByteBuffer[tIndex + 3] = Math.ceil(tBuffer[sIndex + 3]);
}
// writing result to canvas.
resCtx.putImageData(imgRes, 0, 0);
return resCV;
}
Here is what I did so far in Java:
public static final CanvasElement scaleCanvas(CanvasElement cv, double scale) {
if (!(scale < 1) || !(scale > 0)) {
// throw new Exception("scale must be a positive number <1 ");
}
double sqScale = scale * scale; // square scale = area of source pixel within target
int sw = cv.getWidth(); // source image width
int sh = cv.getHeight(); // source image height
double tw = Math.ceil(sw * scale); // target image width
double th = Math.ceil(sh * scale); // target image height
int sx = 0, sy = 0, sIndex = 0; // source x,y, index within source array
double tx = 0, ty = 0;
int yIndex = 0, tIndex = 0; // target x,y, x,y index within target array
double tX = 0, tY = 0; // rounded tx, ty
double w = 0, nw = 0, wx = 0, nwx = 0, wy = 0, nwy = 0; // weight / next weight x / y
// weight is weight of current source point within target.
// next weight is weight of current source point within next target's point.
boolean crossX = false; // does scaled px cross its current px right border ?
boolean crossY = false; // does scaled px cross its current px bottom border ?
CanvasPixelArray sBuffer = cv.getContext2d().getImageData(0, 0, sw, sh).getData(); // source buffer 8 bit rgba
Float32Array tBuffer = TypedArrays.createFloat32Array(4 * sw * sh);
double sR = 0, sG = 0, sB = 0; // source's current point r,g,b
// untested !
double sA = 0; //source alpha
for (sy = 0; sy < sh; sy++) {
GWT.log("sy: "+sy+" sh: "+sh);
ty = sy * scale; // y src position within target
tY = (long)ty; // rounded : target pixel's y // ?????
yIndex = (int)Math.floor(4 * tY * tw); // line index within target array
crossY = (tY != ( (long)(ty + scale) )); // ?????
if (crossY) { // if pixel is crossing botton target pixel
wy = (tY + 1 - ty); // weight of point within target pixel
nwy = (ty + scale - tY - 1); // ... within y+1 target pixel
}
for (sx = 0; sx < sw; sx++, sIndex += 4) {
tx = sx * scale; // x src position within target
tX = (long)tx; // rounded : target pixel's x // ?????
tIndex = (int)Math.floor(yIndex + tX * 4); // target pixel index within target array // ?????
crossX = (tX != ((int)Math.floor(tx + scale)));
if (crossX) { // if pixel is crossing target pixel's right
wx = (tX + 1 - tx); // weight of point within target pixel
nwx = (tx + scale - tX - 1); // ... within x+1 target pixel
}
sR = sBuffer.get(sIndex); // retrieving r,g,b for curr src px.
sG = sBuffer.get(sIndex + 1);
sB = sBuffer.get(sIndex + 2);
sA = sBuffer.get(sIndex + 3);
if (!crossX && !crossY) { // pixel does not cross
// just add components weighted by squared scale.
tBuffer.set(tIndex , (float)(tBuffer.get(tIndex) + sR * sqScale));
tBuffer.set(tIndex + 1, (float)(tBuffer.get(tIndex + 1) + sG * sqScale));
tBuffer.set(tIndex + 2, (float)(tBuffer.get(tIndex + 2) + sB * sqScale));
tBuffer.set(tIndex + 3, (float)(tBuffer.get(tIndex + 3) + sA * sqScale));
} else if (crossX && !crossY) { // cross on X only
w = wx * scale;
// add weighted component for current px
tBuffer.set(tIndex , (float)(tBuffer.get(tIndex) + sR * w));
tBuffer.set(tIndex + 1, (float)(tBuffer.get(tIndex + 1) + sG * w));
tBuffer.set(tIndex + 2, (float)(tBuffer.get(tIndex + 2) + sB * w));
tBuffer.set(tIndex + 3, (float)(tBuffer.get(tIndex + 3) + sA * w));
// add weighted component for next (tX+1) px
nw = nwx * scale;
tBuffer.set(tIndex + 4, (float)(tBuffer.get(tIndex + 4) + sR * nw)); // not 3
tBuffer.set(tIndex + 5, (float)(tBuffer.get(tIndex + 5) + sG * nw)); // not 4
tBuffer.set(tIndex + 6, (float)(tBuffer.get(tIndex + 6) + sB * nw)); // not 5
tBuffer.set(tIndex + 7, (float)(tBuffer.get(tIndex + 7) + sA * nw)); // not 6
} else if (crossY && !crossX) { // cross on Y only
w = wy * scale;
// add weighted component for current px
tBuffer.set(tIndex , (float)(tBuffer.get(tIndex) + sR * w));
tBuffer.set(tIndex + 1, (float)(tBuffer.get(tIndex + 1) + sG * w));
tBuffer.set(tIndex + 2, (float)(tBuffer.get(tIndex + 2) + sB * w));
tBuffer.set(tIndex + 3, (float)(tBuffer.get(tIndex + 3) + sA * w));
// add weighted component for next (tY+1) px
nw = nwy * scale;
tBuffer.set((int)Math.floor(tIndex + 4 * tw) , (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw)) + sR * nw)); // *4, not 3
tBuffer.set((int)Math.floor(tIndex + 4 * tw + 1), (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw + 1)) + sG * nw)); // *4, not 3
tBuffer.set((int)Math.floor(tIndex + 4 * tw + 2), (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw + 2)) + sB * nw)); // *4, not 3
tBuffer.set((int)Math.floor(tIndex + 4 * tw + 3), (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw + 3)) + sA * nw)); // *4, not 3
} else { // crosses both x and y : four target points involved
// add weighted component for current px
w = wx * wy;
tBuffer.set(tIndex , (float)(tBuffer.get(tIndex) + sR * w));
tBuffer.set(tIndex + 1, (float)(tBuffer.get(tIndex + 1) + sG * w));
tBuffer.set(tIndex + 2, (float)(tBuffer.get(tIndex + 2) + sB * w));
tBuffer.set(tIndex + 3, (float)(tBuffer.get(tIndex + 3) + sA * w));
// for tX + 1; tY px
nw = nwx * wy;
tBuffer.set(tIndex + 4, (float)(tBuffer.get(tIndex + 4) + sR * nw)); // same for x
tBuffer.set(tIndex + 5, (float)(tBuffer.get(tIndex + 5) + sG * nw));
tBuffer.set(tIndex + 6, (float)(tBuffer.get(tIndex + 6) + sB * nw));
tBuffer.set(tIndex + 7, (float)(tBuffer.get(tIndex + 7) + sA * nw));
// for tX ; tY + 1 px
nw = wx * nwy;
tBuffer.set((int)Math.floor(tIndex + 4 * tw) , (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw)) + sR * nw)); // same for mul
tBuffer.set((int)Math.floor(tIndex + 4 * tw + 1), (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw + 1)) + sG * nw));
tBuffer.set((int)Math.floor(tIndex + 4 * tw + 2), (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw + 2)) + sB * nw));
tBuffer.set((int)Math.floor(tIndex + 4 * tw + 3), (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw + 3)) + sA * nw));
// for tX + 1 ; tY +1 px
nw = nwx * nwy;
tBuffer.set((int)Math.floor(tIndex + 4 * tw + 4), (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw + 4)) + sR * nw)); // same for both x and y
tBuffer.set((int)Math.floor(tIndex + 4 * tw + 5), (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw + 5)) + sG * nw));
tBuffer.set((int)Math.floor(tIndex + 4 * tw + 6), (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw + 6)) + sB * nw));
tBuffer.set((int)Math.floor(tIndex + 4 * tw + 7), (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw + 7)) + sA * nw));
}
} // end for sx
} // end for sy
// create result canvas
Canvas resCV = Canvas.createIfSupported();
resCV.getCanvasElement().setWidth((int)Math.floor(tw));
resCV.getCanvasElement().setHeight((int)Math.floor(th));
Context2d resCtx = resCV.getContext2d();
ImageData imgRes = resCtx.getImageData(0, 0, tw, th);
CanvasPixelArray tByteBuffer = imgRes.getData();
// convert float32 array into a UInt8Clamped Array
int pxIndex = 0;
for (sIndex = 0, tIndex = 0; pxIndex < tw * th; sIndex += 4, tIndex += 4, pxIndex++) {
tByteBuffer.set(tIndex, (int)Math.ceil(tBuffer.get(sIndex)));
tByteBuffer.set(tIndex + 1, (int)Math.ceil(tBuffer.get(sIndex + 1)));
tByteBuffer.set(tIndex + 2, (int)Math.ceil(tBuffer.get(sIndex + 2)));
tByteBuffer.set(tIndex + 3, (int)Math.ceil(tBuffer.get(sIndex + 3)));
}
// writing result to canvas.
resCtx.putImageData(imgRes, 0, 0);
return resCV.getCanvasElement();
}
I am not sure how to write an expression like thit tY = 0 | ty in Java. I am also not sure if canvas.width(value); transforms into canvas.setCoordinateSpaceWidth(value);
Edit:
Is (0 | ty + scale) in JS is ((long)ty + scale) in Java?
What is the translation of
var sBuffer = cv.getContext('2d').getImageData(0, 0, sw, sh).data
is it CanvasPixelArray
CanvasPixelArray sBuffer = cv.getContext2d().getImageData(0, 0, sw, sh).getData()
Can someone help me with the translation?
Edit: It turns out that my Java code is very slow. I cannot run it in dev mode. In prod mode it is event slower than the JavaScript code. Why is this code slower?
0 | tY is rounding a JS Number (equivalent to a Java double) to an integer value; equivalent to Math.floor(tY) or (long) tY (int is too small for all integer values that can be expressed in a double, but might be OK in this specific case).
canvas.width maps to Canvas#getCoordinateSpaceWidth, as you can see in GWT sources.
Finally, new Float32Array(n) maps to TypedArrays.createFloat32Array.
I am doing a javafx visualisation application for 3d points. As I am new to javafx, I started from the tutorial provided in the oracle website:
http://docs.oracle.com/javase/8/javafx/graphics-tutorial/javafx-3d-graphics.htm#JFXGR256
The example above runs perfect on my Mac, But after adding more points, the mouse drag, which causes the camera to rotate and thus people can view the objects from different angle, became very slow and simply not applicable any more.
I currently have a data for a rabbit with about 40000 points:
The code I used to rotate camera:
cameraXform.ry.setAngle(cameraXform.ry.getAngle() - mouseDeltaX * MOUSE_SPEED * modifier * ROTATION_SPEED);
cameraXform.rx.setAngle(cameraXform.rx.getAngle() + mouseDeltaY * MOUSE_SPEED * modifier * ROTATION_SPEED);
which is the same as in the oracle example.
What I have tried:
set JVM flag -Djavafx.animation.fullspeed=true, this helped a bit, but not significant.
set JVM flag -Djavafx.autoproxy.disable=true, this did not help.
set Cache to true and CacheHint to Cache.SPEED, this did not make much difference.
create another thread to do the rotation, and sync back after calculation, this did not help neither.
Any help is appreciated.Thanks in advance!
Here is how I made a point cloud using tetrahedrons in a triangle mesh. seems to run faster than using spheres or squares. this code helped me scalafx google code
import java.util.ArrayList;
import javafx.scene.shape.TriangleMesh;
public class TetrahedronMesh extends TriangleMesh {
private ArrayList<Point3i> vertices;
private int[] facesLink;
public TetrahedronMesh(double length, ArrayList<Point3i> v) {
this.vertices = v;
if (length > 0.0) {
float[] points = new float[vertices.size() * 12];
int[] faces = new int[vertices.size() * 24];
facesLink = new int[vertices.size() * 4];
float[] texCoords = new float[vertices.size() * 12];
int vertexCounter = 0;
int primitiveCounter = 0;
int pointCounter = 0;
int facesCounter = 0;
int texCounter = 0;
for (Point3i vertex : vertices) {
vertex.scale(100);
points[primitiveCounter] = vertex.x;
points[primitiveCounter + 1] = (float) (vertex.y - (length
* Math.sqrt(3.0) / 3.0));
points[primitiveCounter + 2] = -vertex.z;
points[primitiveCounter + 3] = (float) (vertex.x + (length / 2.0));
points[primitiveCounter + 4] = (float) (vertex.y + (length
* Math.sqrt(3.0) / 6.0));
points[primitiveCounter + 5] = -vertex.z;
points[primitiveCounter + 6] = (float) (vertex.x - (length / 2.0));
points[primitiveCounter + 7] = (float) (vertex.y + (length
* Math.sqrt(3.0) / 6.0));
points[primitiveCounter + 8] = -vertex.z;
points[primitiveCounter + 9] = vertex.x;
points[primitiveCounter + 10] = vertex.y;
points[primitiveCounter + 11] = (float) -(vertex.z - (length * Math
.sqrt(2.0 / 3.0)));
faces[facesCounter] = pointCounter + 0;
faces[facesCounter + 1] = pointCounter + 0;
faces[facesCounter + 2] = pointCounter + 1;
faces[facesCounter + 3] = pointCounter + 1;
faces[facesCounter + 4] = pointCounter + 2;
faces[facesCounter + 5] = pointCounter + 2;
faces[facesCounter + 6] = pointCounter + 1;
faces[facesCounter + 7] = pointCounter + 1;
faces[facesCounter + 8] = pointCounter + 0;
faces[facesCounter + 9] = pointCounter + 0;
faces[facesCounter + 10] = pointCounter + 3;
faces[facesCounter + 11] = pointCounter + 3;
faces[facesCounter + 12] = pointCounter + 2;
faces[facesCounter + 13] = pointCounter + 2;
faces[facesCounter + 14] = pointCounter + 1;
faces[facesCounter + 15] = pointCounter + 1;
faces[facesCounter + 16] = pointCounter + 3;
faces[facesCounter + 17] = pointCounter + 4;
faces[facesCounter + 18] = pointCounter + 0;
faces[facesCounter + 19] = pointCounter + 0;
faces[facesCounter + 20] = pointCounter + 2;
faces[facesCounter + 21] = pointCounter + 2;
faces[facesCounter + 22] = pointCounter + 3;
faces[facesCounter + 23] = pointCounter + 5;
facesLink[pointCounter] = vertexCounter;
facesLink[pointCounter + 1] = vertexCounter;
facesLink[pointCounter + 2] = vertexCounter;
facesLink[pointCounter + 3] = vertexCounter;
texCoords[texCounter] = 0.5f;
texCoords[texCounter + 1] = 1.0f;
texCoords[texCounter + 2] = 0.75f;
texCoords[texCounter + 3] = (float) (1.0 - Math.sqrt(3.0) / 4.0);
texCoords[texCounter + 4] = 0.25f;
texCoords[texCounter + 5] = (float) (1.0 - Math.sqrt(3.0) / 4.0);
texCoords[texCounter + 6] = 1.0f;
texCoords[texCounter + 7] = 1.0f;
texCoords[texCounter + 8] = 0.5f;
texCoords[texCounter + 9] = (float) (1.0 - Math.sqrt(3.0) / 2.0);
texCoords[texCounter + 10] = 0.0f;
texCoords[texCounter + 11] = 1.0f;
vertexCounter++;
primitiveCounter += 12;
pointCounter += 4;
facesCounter += 24;
texCounter += 12;
}
getPoints().setAll(points);
getFaces().setAll(faces);
getTexCoords().setAll(texCoords);
// getFaceSmoothingGroups().setAll(0, 1, 2, 3);
}
}
public Point3i getPointFromFace(int faceId) {
return vertices.get(facesLink[faceId]);
}
}
Point3i code as follows
public class Point3i {
public int x;
public int y;
public int z;
public Point3i() {
x = 0;
y = 0;
z = 0;
}
}
Picking the point using the scene
scene.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent me) {
PickResult pr = me.getPickResult();
int faceId = pr.getIntersectedFace();
if (faceId != -1) {
Point3i p = tetrahedronMesh.getPointFromFace(faceId);
}
}
});
I know this is old, But for others ..
Instead of creating a new shape all together, each of the predefined shapes
Sphere, Box, Cylinder, allow you to set the number of divisions in the constructor.
Sphere for example defaults to 64 divisions, 32 for longitude, 32 for latitude.
you can easily do ... = new Sphere(radius, divisions); (4 is the minimum I believe for Sphere).
Something that helps a lot is to set the mouse transparent on the root with:
root3D.setMouseTransparent(true);
This obviously disables clicking or hovering on objects of the view (i.e PickResult is null). The solution for that is to temporarily enable it when there is a click for example and simulate another identical click with impl_processMouseEvent.
#Override
public void handle(MouseEvent event) {
try {
if (event.getEventType() == MouseEvent.MOUSE_CLICKED
&& event.isStillSincePress()
&& (event.getTarget() == scene3d || event.getTarget() instanceof Shape3D)) {
Parent root3D = scene3d.getRoot();
// if the 3D scene has been set to mouse transparent,
// then we send another event and we disable the transparency temporarily
if (root3D.isMouseTransparent()) {
root3D.setMouseTransparent(false);
try {
scene3d.impl_processMouseEvent(event);
}
finally {
root3D.setMouseTransparent(true);
}
}
else {
// here you get the pick result you need :)
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}