outlineDescriptor.CellArray.java Source code

Java tutorial

Introduction

Here is the source code for outlineDescriptor.CellArray.java

Source

/*******************************************************************************
 * @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;
    }

}