Converting Mat to one dimensional float array for EM? - java

I'm trying to convert a Python code to Java. However, I'm unable to find a way to create the sample to train the Expectation Maximization as it should be a one-channel matrix with 2 values (S and V from HSV Color Space) as below:
row 0: S, V
row 1: S, V
row 2: S, V
row 3: S, V
In Python, I was able to do it as follow:
def convert_to_samples(image, height, width):
samples = []
for y in range(0, height):
for x in range(0, width):
samples.append(image[y, x])
samples = np.float32(np.vstack(samples))
return samples
I have tried as following without success as the result is not a Mat and I can't find a way to transform it back.
public double[][] convert_to_samples(Mat image) {
double[][] samples = new double[image.height()][];
for(int i = 0; i < image.height(); i++) {
for(int j = 0; j < image.width(); j++) {
samples[i] = image.get(i, j);
}
}
return sortRowWise(samples);
}
private static double[][] sortRowWise(double[][] m) {
for (double[] values : m) Arrays.sort(values);
return m;
}
Could someone help me transform the Mat?

public Mat convert_to_samples(Mat image) {
double[][] samples = new double[image.height()][];
for(int i = 0; i < image.height(); i++) {
for(int j = 0; j < image.width(); j++) {
samples[i] = image.get(i, j);
}
}
sortRowWise(samples);
Mat matSamples = new Mat(image.height(), 2, CvType.CV_64FC1);
for (int i = 0; i < image.height(); i++) {
matSamples.put(i, 0, samples[i]);
}
return matSamples;
}
private static void sortRowWise(double[][] m) {
for (double[] values : m) Arrays.sort(values);
}

Related

Java: Create a duplicate of an array without making it a reference

I have written a series of matrix operations where I take a 2 dimensional float array, treat it as a matrix, and perform matrix operations on it to acquire an inverse. My problem has been that although the array I am using with the class methods isn't part of the class, every time I run the method with the array as the parameter, the array itself also becomes modified.
First I will describe how I got the inverse of my matrix and then I will show the output.
The steps to taking the inverse of a matrix are as follows:
Get the cofactor matrix (i.e. create a matrix of matrix minors of the original matrix and then negate every other entry. If C = Cofactor Matrix, M = Matrix of Minors, i is the current row, and j is the current column, then C[ i ][ j ] = M[ i ][ j ]*( -1 )^( i + j )
Convert the cofactor matrix to the adjugate (also known as adjoint) matrix by transposing (replacing row, column entry by its analogous column, row entry and vice versa) the cofactor matrix. If C = Cofactor Matrix, A = Adjugate Matrix, i is the current row, and j is the current column, then A[ i ][ j ] = C[ j ][ i ]
Finally, take one over determinant of the original matrix and multiply the adjugate matrix by that value. If I = Inverse Matrix, A = Adjugate Matrix and D = Determinant, then I = (1/D)*A
In order to test if you have truly acquired the Matrix Inverse of a Matrix, one can multiply the original matrix by its inverse to get the identity matrix.
If I = Inverse, O = Original Matrix, and id = Identity Matrix then O*I = id
Now I will present the code where I implement these operations. For the sake of conciseness, I will not describe how to get the Matrix of Minors or the Determinant, but the problem I have been encountering will become apparent anyways.
public class MatrixOperations {
//Note: this method works fine. There are no problems.
public float determinant(float [][] a)
{
float [][] temp_mat;
float res = 0;
//assuming a square matrix
/*If it's a 2X2, then use the formula for a determinant of
2X2 matrices.*/
if(a.length == 2)
{
return a[0][0]*a[1][1]-a[0][1]*a[1][0];
}
/*Otherwise do the determinant formula recursively until your
determinant is made up of 2X2 matrix determinants and scalar products*/
else
{
temp_mat = new float[a.length-1][a.length-1];
int placej = 0;
int placei = 0;
for(int k = 0; k<a.length;k++)
{
for(int j = 0; j<a.length; j++)
{
for(int i = 1; i < a.length; i++)
{
placei = i-1;
if(j != k)
{
if(j < k)
{
temp_mat[placei][j] = a[i][j];
}
else if(j > k)
{
if (i == 1){
placej = j-1;
}
temp_mat[placei][placej] = a[i][j];
}
}
}
}
res+=a[0][k]*determinant(temp_mat)*(int)Math.pow(-1, k);
}
return res;
}
}
//Note: this method also works fine
//Scalar product method
public float[][] mul(float[][] m, float r)
{
float[][] res = new float[m.length][m.length];
for(int i = 0; i < m.length; i++)
{
for(int j = 0; j < m.length; j++)
{
res[i][j]= m[i][j]*r;
}
}
return res;
}
//Note: This method also works fine
public float[][] mul(float[][] m,float[][] n)
{
float[][] res = new float[m.length][m.length];
for(int i = 0; i < m.length; i++)
{
for(int j = 0; j < m.length; j++)
{
for(int k = 0; k < m.length; k++)
{
res[i][j] += m[i][k]*m[k][i];
}
}
}
return res;
}
//The method for creating a matrix of minors
//Here I start having problems
public float[][] minor(float [][] m)
{
float [][] minor_mat = new float [m.length][m.length];
//If the matrix is greater than a 2X2, use this to generate a matrix of minors
if(m.length > 2)
{
float [][] current_minor = new float [m.length-1][m.length-1];
int placei = 0;
int placej = 0;
for(int i = 0; i < m.length; i++)
{
for(int j = 0; j < m.length; j++)
{
for(int k = 0; k < m.length; k++)
{
for(int l = 0; l < m.length; l++)
{
if(i != k && j != l)
{
if(k<i)
placei = k;
else if(k>i)
placei = k-1;
if(l<j)
placej = l;
else if(l>j)
placej = l-1;
current_minor[placei][placej] = m[k][l];
}
}
}
minor_mat[i][j] = this.determinant(current_minor);
}
}
}
//otherwise use the definition for 2X2 matrix of minors
else
{
//even though minor_mat is using m.clone() rather than m, when I return the result, m has still been modified for some reason.
minor_mat = m.clone()
float temp;
temp = minor_mat[0][0];
minor_mat[0][0] = minor_mat[1][1];
minor_mat[1][1] = temp;
temp = minor_mat[0][1];
minor_mat[0][1] = minor_mat[1][0];
minor_mat[1][0] = temp;
}
return minor_mat;
}
//the same problem occurs here as it did in the minor method
//m appears to get modified even though I only use m.clone()
public float[][] cofactor(float [][] m)
{
float[][] res = m.clone();
res = this.minor(res)
for(int i = 0; i < m.length; i++)
{
for(int j = 0; j < m.length; j++)
{
res[i][j] = res[i][j]*(int)Math.pow(-1, i + j);
}
}
return res;
}
//The following transpose, adjugate, and inverse methods have the same problem
public float[][] transpose(float[][] m)
{
float[][] res = new float[m.length][m.length];
float temp = 0;
for(int i = 0; i < m.length; i++)
{
for(int j = 0; j < m.length; j++)
{
temp = m[i][j];
res[i][j] = m[j][i];
res[j][i] = temp;
}
}
return res;
}
public float[][] adjugate(float[][] m)
{
float[][] res = this.transpose(this.cofactor(m));
return res;
}
public float[][] inverse(float[][] m)
{
float[][] res = this.mul(this.adjugate(m), (1/this.determinant(m)));
return res;
}
//print out the matrix in square form
public void matrixprint(float [][] m)
{
for(int i = 0; i < m.length; i++)
{
System.out.println("");
for(int j = 0; j < m[i].length; j++){
System.out.print(m[i][j] + " ");
}
}
System.out.println("\n");
}
}
Now the main class and the main method that creates an instance of the MatrixOperations class and uses its methods on a 2X2 matrix.
public class Main {
public static void main(String[] args) {
MatrixOperations mo = new MatrixOperations();
//Create a 2X2 matrix called "matrix" and set its elements
//Then perform each step on "matrix" and finally test if you have acquired the correct inverse
float [][] matrix = new float[2][2];
matrix[0][0] = 2;
matrix [0][1] = 5;
matrix [1][0] = 4;
matrix [1][1] = 3;
System.out.println("Matrix = ");
mo.matrixprint(matrix);
System.out.println("Minor = ");
mo.matrixprint(mo.minor(matrix));
System.out.println("Matrix = ");
mo.matrixprint(matrix);
System.out.println("Cofactor = ");
mo.matrixprint(mo.cofactor(matrix));
System.out.println("Matrix = ");
mo.matrixprint(matrix);
System.out.println("Adjugate = ");
mo.matrixprint(mo.adjugate(matrix));
System.out.println("Matrix = ");
mo.matrixprint(matrix);
System.out.println("Determinant = ");
System.out.println(mo.determinant(matrix));
System.out.println("Matrix = ");
mo.matrixprint(matrix);
System.out.println("Inverse = ");
mo.matrixprint(mo.inverse(matrix));
System.out.println("Matrix = ");
mo.matrixprint(matrix);
System.out.println("Identity = ");
mo.matrixprint(mo.mul(mo.inverse(matrix), matrix));
}
}
Now you will see that when I show the output, every time I use a method on "matrix", and reprint "matrix", "matrix" itself has been modified even though my methods only use a copy of "matrix" and not "matrix" itself.
Output:
Matrix =
2.0 5.0
4.0 3.0
Minor =
3.0 4.0
5.0 2.0
Matrix =
3.0 4.0
5.0 2.0
Cofactor =
3.0 -4.0
-5.0 2.0
Matrix =
3.0 -4.0
-5.0 2.0
Adjugate =
3.0 5.0
4.0 2.0
Matrix =
3.0 4.0
5.0 2.0
Determinant =
-14.0
Matrix =
3.0 4.0
5.0 2.0
Inverse =
-0.21428573 0.35714287
0.2857143 -0.14285715
Matrix =
3.0 -4.0
-5.0 2.0
Identity =
0.1479592 0.1479592
0.12244898 0.12244898
Any help/explanation as to why this happens would be appreciated.
This line does a shallow clone;
float[][] res = m.clone();
This copies the res which is array fo references to arrays. but not any of the arrays res points to. Most likely what you wanted is
float[][] res = new float[m.length][];
for (int i = 0; i < m.length; i++)
res[i] = m[i].clone();
It's because you are passing reference of matrix object in the methods of MatrixOperations class. It's not a copy of matrix object.
From Java doc:
Reference data type parameters, such as objects, are also passed into
methods by value. This means that when the method returns, the
passed-in reference still references the same object as before.
A two-dimensional array is just an array of arrays.
clone() on an array just does a shallow clone.
So you have a new cloned outer array, but it references the same entries (the inner arrays).
After cloning the outer array, iterate over the outer array and clone all inner arrays to get a deep clone.

ImageJ - Cumulative histograms and Histograms

I have run into a small problem with my program as it seems unable to find the highest value in a histogram to calculate the scale the histogram is supposed to be so now the entire histogram is way out of bounds
I really hope someone can help me out since it's driving me crazy
import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.filter.*;
public class Oblig3_Oppg2 implements PlugInFilter {
public int setup(String arg, ImagePlus im) {;
return DOES_8G + NO_CHANGES;
}
public void run(ImageProcessor ip) {
final int W = 256;
final int H = 100;
final int H1 = 140;
int[] hist = ip.getHistogram();
int[] KH = new int[W]; //Cumulative Histogram Array
int maxVal;
//Calculates the highest pixel count in the Histogram
for (int i = 0; i < W; i++){
if (hist[i] > maxVal){
maxVal = i;
}
}
KH[0] = hist[0];
for(int i = 1; i < W; i++) {
KH[i] = KH[i-1] + hist[i];
}
ImageProcessor histIp = new ByteProcessor(W, H1);
histIp.setValue(255);
histIp.fill();
int max = KH[255];
for(int j = 0; j < W; j++){
KH[j] = (KH[j]*100)/max; //Scales the Cumulative Histogram
hist[j] = (hist[j]*100)/maxVal; // Scales the Histogram
}
for (int k = 0; k < W; k++){
histIp.setValue(0);
histIp.drawLine(k, H, k, H-KH[k]);
}
for (int k = 0; k < W; k++){
histIp.setValue(0);
histIp.drawLine(k, H, k, H-hist[k]);
}
for (int l = 0; l < W; l++){
histIp.setValue(l);
histIp.drawLine(l, 140, l, 102);
}
histIp.setValue(0);
histIp.drawLine(W, H, W, 0);
// Display the histogram image:
String hTitle = "Histogram";
ImagePlus histIm = new ImagePlus(hTitle, histIp);
histIm.show();
}
}
You should set maxVal to the actual value, not the current index in your loop:
for (int i = 0; i < W; i++){
if (hist[i] > maxVal){
maxVal = hist[i]; // <-- here
}
}
Furthermore, it might be better to limit the loop to hist.length instead of W. That would prevent errors in case you set W to some value different from the array length that ip.getHistogram() returns.
Since you don't provide a runnable example (i.e. the entire Java class; I assume you implement ij.plugin.filter.PlugInFilter), I didn't test the code, and it's not entirely clear to me what you want to achieve.

Java Matrices - Transpose & Sum

I am working on a Matrix program on eclipse and I am currently stuck on 2 methods in which I thought were the most simplest of all. The first method that I am working on is to take the sum of 2 different 2D arrays from the #Test cases and returning the sum in a new 2D array. I already have an 2D array instance variable. The reason I am stuck is because the of the parameter in the method. The parameter doesn't give any variable other than the class (Matrix) and the variable (other). So I was wondering how to go about getting this method started and most importantly returning the sum array.
The other method I am stuck on is the transpose method where you must flip the rows and columns of the given 2D array. I know I must create a temp 2D array in order to store the content back into the original 2D array but for some reason it is not passing the test cases. If someone could please help me with these two methods, it would be much appreciated.
import java.util.Arrays;
public class Matrix {
private int[][] array;
private int[][] array2;
private int theRow;
private int theCol;
public Matrix(int[][] arrayOfArrays) {
// TODO Auto-generated constructor stub
array = new int[arrayOfArrays.length][arrayOfArrays[0].length];
for (int r = 0; r < arrayOfArrays.length; r++) {
for (int c = 0; c < arrayOfArrays[r].length; c++) {
array[r][c] = arrayOfArrays[r][c];
}
}
}
public int get(int row, int column) {
return array[row][column];
}
public int getNumberOfRows() {
int nRows = array.length;
return nRows;
}
public int getNumberOfColumns() {
int nCols = array[0].length;
return nCols;
}
public String toString() {
String res = "";
for (int r = 0; r < array.length; r++) {
for (int c = 0; c < array[r].length; c++)
res = res + array[r][c];
}
return res;
}
public Matrix sum(Matrix other) {
return sum;
}
public void scalarMultiply(int scalar) {
for (int r = 0; r < array.length; r++) {
for (int c = 0; c < array[0].length; c++) {
array[r][c] = array[r][c] * scalar;
}
}
}
public void transpose() {
int m = array.length;
int n = array[0].length;
int[][] transpose = new int [n][m];
int temp;
for (int r = 0; r < m; r++) {
for (int c = 0; c < n; c++) {
transpose[c][r] = array[r][c];
array[r][c] = array[c][r];
array[c][r] = transpose[c][r];
}
}
}
//The test cases for sum method and transpose method
#Test
public void testSum() {
int[][] a1 = { { 1, 2, 3 },
{ 5, 6, 7 } };
Matrix a = new Matrix(a1);
int[][] a2 = { { -2, -2, -2 },
{ 4, 4, 4 } };
Matrix b = new Matrix(a2);
Matrix c = a.sum(b);
assertEquals(-1, c.get(0, 0));
assertEquals(0, c.get(0, 1));
assertEquals(1, c.get(0, 2));
assertEquals(9, c.get(1, 0));
assertEquals(10, c.get(1, 1));
assertEquals(11, c.get(1, 2));
}
#Test
public void testTranspose() {
int[][] a1 = { { 1, 3, 5 },
{ 2, 4, 6 } };
Matrix a = new Matrix(a1);
a.transpose();
assertEquals(1, a.get(0, 0));
assertEquals(2, a.get(0, 1));
assertEquals(3, a.get(1, 0));
assertEquals(4, a.get(1, 1));
assertEquals(5, a.get(2, 0));
assertEquals(6, a.get(2, 1));
}
You need change the dimensions, for example, 2x3 -> 3x2.
import java.util.Arrays;
public class Matrix {
private int[][] array;
private int[][] array2;// remove this
private int theRow;// remove this
private int theCol;// remove this
public void transpose() {
int m = array.length;
int n = array[0].length;
int[][] transpose = new int [n][m];
for (int r = 0; r < m; r++) {
for (int c = 0; c < n; c++) {
transpose[c][r] = array[r][c];
}
}
array = transpose;
}
}

Image Enhancement using FFT in java

I am working on fingerprint image enhancement with Fast Fourier Transformation. I got the idea from this site.
I have implemented the FFT function using 32*32 window, and after that as the referral site suggested, I want to multiply power spectrum with the FFT. But I do not get,
How do I calculate Power Spectrum for an image? Or is there any ideal value for Power Spectrum ?
Code for FFT:
public FFT(int[] pixels, int w, int h) {
// progress = 0;
input = new TwoDArray(pixels, w, h);
intermediate = new TwoDArray(pixels, w, h);
output = new TwoDArray(pixels, w, h);
transform();
}
void transform() {
for (int i = 0; i < input.size; i+=32) {
for(int j = 0; j < input.size; j+=32){
ComplexNumber[] cn = recursiveFFT(input.getWindow(i,j));
output.putWindow(i,j, cn);
}
}
for (int j = 0; j < output.values.length; ++j) {
for (int i = 0; i < output.values[0].length; ++i) {
intermediate.values[i][j] = output.values[i][j];
input.values[i][j] = output.values[i][j];
}
}
}
static ComplexNumber[] recursiveFFT(ComplexNumber[] x) {
int N = x.length;
// base case
if (N == 1) return new ComplexNumber[] { x[0] };
// radix 2 Cooley-Tukey FFT
if (N % 2 != 0) { throw new RuntimeException("N is not a power of 2"); }
// fft of even terms
ComplexNumber[] even = new ComplexNumber[N/2];
for (int k = 0; k < N/2; k++) {
even[k] = x[2*k];
}
ComplexNumber[] q = recursiveFFT(even);
// fft of odd terms
ComplexNumber[] odd = even; // reuse the array
for (int k = 0; k < N/2; k++) {
odd[k] = x[2*k + 1];
}
ComplexNumber[] r = recursiveFFT(odd);
// combine
ComplexNumber[] y = new ComplexNumber[N];
for (int k = 0; k < N/2; k++) {
double kth = -2 * k * Math.PI / N;
ComplexNumber wk = new ComplexNumber(Math.cos(kth), Math.sin(kth));
ComplexNumber tmp = ComplexNumber.cMult(wk, r[k]);
y[k] = ComplexNumber.cSum(q[k], tmp);
ComplexNumber temp = ComplexNumber.cMult(wk, r[k]);
y[k + N/2] = ComplexNumber.cDif(q[k], temp);
}
return y;
}
I'm thinking that the power spectrum is the square of the output of the Fourier transform.
power#givenFrequency = x(x*) where x* is the complex conjugate
The total power in the image block would then be the sum over all frequency and space.
I have no idea if this helps.

Rotating Matrix

I have a matrixA like that
[0][1]
[2][3]
[4][5]
And after my custom rotation (different numbering) becomes matrixB like this:
[0][1][2]
[3][4][5]
What i want is to map the numberings of the matrix A to B when i look the matrixA from the left->right.
To explain: matrixA looking from the left->right looks like this.
[1][3][5]
[0][2][4]
And matrixB is as it is
[0][1][2]
[3][4][5]
So i want to map, preferably with an equation these values
1->0
3->1
5->2
0->3
2->4
4->5
The real matrix is much larger so please don't focus to the size of this matrix
If anyone has any suggestions to find an equation for this mappings or some other way to do the mapping described? i would appreciate it
Here is some code I use sometimes. This rotates the matrix by 90 or -90 degrees. This might be a start for your problem:
public int[][] rotateMatrixRight(int[][] matrix)
{
/* W and H are already swapped */
int w = matrix.length;
int h = matrix[0].length;
int[][] ret = new int[h][w];
for (int i = 0; i < h; ++i) {
for (int j = 0; j < w; ++j) {
ret[i][j] = matrix[w - j - 1][i];
}
}
return ret;
}
public int[][] rotateMatrixLeft(int[][] matrix)
{
/* W and H are already swapped */
int w = matrix.length;
int h = matrix[0].length;
int[][] ret = new int[h][w];
for (int i = 0; i < h; ++i) {
for (int j = 0; j < w; ++j) {
ret[i][j] = matrix[j][h - i - 1];
}
}
return ret;
}
Here you can find ten different formulas for your sequence 3,0,4,1,5,2.
Always consult OEIS when you need an integer sequence!
int height = 2, width = 3; // of matrix B
int [][] a = {{0,1}, {2, 3}, {4, 5}};
int [][] b = {{0,1,2}, {3,4,5}};
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
int b_val = b[i][j];
int a_val = a[j][height - i - 1];
map.put(a_val, b_val);
}
}
Set<Map.Entry<Integer, Integer>> entries = map.entrySet();
Iterator<Map.Entry<Integer, Integer>> it = entries.iterator();
while(it.hasNext()) {
Map.Entry<Integer, Integer> e = it.next();
System.out.println(e.getKey() + " -> " + e.getValue());
}
See here in action.
Maybe something like this:
map(matrixA,x,y)
w=width of matrix A
h=height of matrix A
n=y*w+x
from=matrixA(x,y)
to=matrixA(n mod h, n / h)
return (from, to)
To make a map, just iterate over all x and y and make a mapping of all those variables.
in place C solution follows
void rotateRight(int matrix[][SIZE], int length) {
int layer = 0;
for (int layer = 0; layer < length / 2; ++layer) {
int first = layer;
int last = length - 1 - layer;
for (int i = first; i < last; ++i) {
int topline = matrix[first][i];
int rightcol = matrix[i][last];
int bottomline = matrix[last][length - layer - 1 - i];
int leftcol = matrix[length - layer - 1 - i][first];
matrix[first][i] = leftcol;
matrix[i][last] = topline;
matrix[last][length - layer - 1 - i] = rightcol;
matrix[length - layer - 1 - i][first] = bottomline;
}
}
}

Categories