Java tutorial
/******************************************************************************* * @Author David Helekal * Platelocator * * Copyright (C) 2014 David Helekal * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package outlineDescriptor; import ij.IJ; import ij.process.ImageProcessor; import org.apache.commons.math3.distribution.NormalDistribution; @SuppressWarnings("unused") /** * A matrix representing the directional field of the supplied image */ final class CellArray { private final int directions; private final int[][] imgData; private final Cell[][] array; private boolean wasFinalized = false; private int rowDimension; private int columnDimension; private int cellSide; private EllipticalKernelGenerator kernelGenerator; private NormalDistribution distribution; private int[][] directionalArray = null; private double[][] coherenceMap = null; /** * @param ip corresponding ImageProcessor * @param columnDimension Array resolution * @param majorAxes voting kernel parameters * @param minorAxes voting kernel parameters * @param ev1 main eigenvalue * @param ev2 secondary eigenvalue */ public CellArray(ImageProcessor ip, int columnDimension, int majorAxes, int minorAxes, double ev1, double ev2) { this.directions = OutlineDescriptor_.getDirections(); this.kernelGenerator = new EllipticalKernelGenerator(majorAxes, minorAxes, ev1, ev2, directions); this.imgData = ip.getIntArray(); this.columnDimension = columnDimension; this.array = splitToCells(ip); this.distribution = new NormalDistribution(); } private Cell[][] splitToCells(ImageProcessor ip) { this.cellSide = (ip.getWidth() - 1) / this.columnDimension; this.rowDimension = ((ip.getHeight() - 1) / this.cellSide); Cell[][] temp = new Cell[this.columnDimension][this.rowDimension]; for (int w = 0; w < this.columnDimension; w++) { for (int h = 0; h < this.getRowDimension(); h++) { int adjustedHeight = cellSide; int adjustedWidth = cellSide; if (this.columnDimension - w == 1) { adjustedWidth = ip.getWidth() - ((w + 1) * cellSide); } if (this.columnDimension - h == 1) { adjustedHeight = ip.getHeight() - ((h + 1) * cellSide); } temp[w][h] = new Cell(w * (ip.getWidth() / this.columnDimension), h * (ip.getHeight() / this.rowDimension), adjustedWidth, adjustedHeight, w, h, this); } } return temp; } private void finalizeArray() { int[][] directionalArray = new int[columnDimension][rowDimension]; double[][] coherenceMap = new double[columnDimension][rowDimension]; for (int x = 0; x < columnDimension; x++) { for (int y = 0; y < rowDimension; y++) { double[] result = array[x][y].getResult(); directionalArray[x][y] = (int) result[0]; coherenceMap[x][y] = result[1]; } } this.coherenceMap = coherenceMap; this.directionalArray = directionalArray; wasFinalized = true; } /** * Analyzes the directional signature of the image data supplied by the ImageProcessor upon construction */ public void analyzeCells() { int yCounter = 1; for (int x = 0; x < this.columnDimension; x++) { for (int y = 0; y < this.rowDimension; y++) { array[x][y].selfEval(); IJ.showProgress((x + 1) * (yCounter), this.rowDimension); } yCounter++; } } public void incrementBinAt(int x, int y, int binNo, double increment) { array[x][y].incrementBin(binNo, increment); } /** * Applies data from a lower resolution array to this array * * @param lowerRes Lower resolution array * @param weight Weighting value */ public void mergeArray(CellArray lowerRes, double weight) { this.normalizeBins(); lowerRes.normalizeBins(); for (int x = 0; x < lowerRes.getColumnDimension(); x++) { for (int y = 0; y < lowerRes.getRowDimension(); y++) { int scaleFactor = this.getColumnDimension() / lowerRes.getColumnDimension(); double[] bins1 = lowerRes.getCell(x, y).getBins(); for (int x1 = 0; x1 < scaleFactor; x1++) { for (int y1 = 0; y1 < scaleFactor; y1++) { double bins2[] = this.array[x * scaleFactor + x1][y * scaleFactor + y1].getBins(); for (int i = 0; i < bins1.length; i++) { this.array[x * scaleFactor + x1][y * scaleFactor + y1].incrementBin(i, bins1[i] * weight + bins2[i]); } } } } } } /** * Normalizes bin data within this array so that they range from 0 to 1 */ public void normalizeBins() { double constant; double max = Double.MIN_VALUE; for (int x = 0; x < columnDimension; x++) { for (int y = 0; y < rowDimension; y++) { double[] bins = array[x][y].getBins(); for (double bin : bins) { max = Math.max(bin, max); } } } constant = 1 / max; for (int x = 0; x < columnDimension; x++) { for (int y = 0; y < rowDimension; y++) { double[] bins = array[x][y].getBins(); for (int i = 0; i < bins.length; i++) { double bin = bins[i]; bins[i] = bin * constant; } array[x][y].setBins(bins); } } } public double[][] getCoherenceMap() { if (!wasFinalized) { finalizeArray(); } return coherenceMap.clone(); } public int[][] getDirectionalArray() { if (!wasFinalized) { finalizeArray(); } return directionalArray.clone(); } public Cell[] getRow(int r) { Cell[] row = new Cell[columnDimension]; for (int i = 0; i < columnDimension; i++) { row[i] = array[i][r]; } return row; } public Cell[] getColumn(int c) { return array[c]; } public Cell getCell(int x, int y) { return array[x][y]; } public double getDistributionDensityAt(double x) { return distribution.density(x); } public int getDirections() { return directions; } public int getRowDimension() { return rowDimension; } public int getColumnDimension() { return columnDimension; } public int getCellSide() { return cellSide; } public EllipticalKernelGenerator getKernelGenerator() { return kernelGenerator; } public int getImgWidth() { return imgData.length; } public int getImgHeight() { return imgData[0].length; } public int[][] getImgData() { return imgData; } }