package ac.ooechs.oil.segmentation;

import ac.essex.ooechs.imaging.commons.segmentation.Segmenter;
import ac.essex.ooechs.imaging.commons.PixelLoader;
import ac.essex.ooechs.imaging.commons.ColourChannels;
import ac.essex.ooechs.imaging.commons.fast.FastStatistics;
import ac.essex.gp.multiclass.BetterDRS;
import ac.essex.gp.multiclass.PCM;
import ac.ooechs.oil.util.DataTypes;

/**
 * Segments images of the pipeline.
 *
 * @author Olly Oechsle, University of Essex, Date: 06-Mar-2008
 * @version 1.0
 */
public class PipelineImageSegmenter extends Segmenter {

    double perimeter1Mean;
    double perimeter1StdDeviation;

    double perimeter2Mean;
    double perimeter2StdDeviation;


    public int segment(PixelLoader image, int x, int y) {

        FastStatistics perimeter1 = image.getPerimeter1().getStatistics(image, x, y);
        perimeter1Mean = perimeter1.getMean();
        perimeter1StdDeviation = perimeter1.getStandardDeviation();
        FastStatistics perimeter2 = image.getPerimeter1().getStatistics(image, x, y);
        perimeter2Mean = perimeter2.getMean();
        perimeter2StdDeviation = perimeter2.getStandardDeviation();

        if (segmentRoads(image, x, y) == DataTypes.ROADS) {
            if (segmentPipelines(image, x, y) == DataTypes.PIPELINE) {
                return DataTypes.PIPELINE;
            } else {
                return DataTypes.ROADS;
            }
        }


        if (segmentRoads2(image, x, y) == 2) {
            if (segmentPipelines(image, x, y) == DataTypes.PIPELINE) {
                return DataTypes.PIPELINE;
            } else {
                return DataTypes.ROADS;
            }
        }

        int classID;
        classID = segment0(image, x, y);
        if (classID == 2) {
            if (segmentPipelines(image, x, y) == DataTypes.PIPELINE) {
                return DataTypes.PIPELINE;
            } else {
                return DataTypes.ROADS;
            }
        }

        if (segmentWater2(image, x, y) == 5) {
            return DataTypes.WATER;
        }

        if (classID == 3) {
            return DataTypes.VEGETATION;
        }
        return classID;

    }

    BetterDRS pcm1 = new BetterDRS(-9.0, 253.0357208251953, new int[]{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2});
    ;

    PCM pcm = new BetterDRS(-32824.99466954256, 4.9E-324, new
            int[]{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, -1});

    public int segment0(PixelLoader image, int x, int y) {
        double perim = perimeter2Mean;
        double node1 = -0.5029327021628938 * perim;
        double node4 = 3.0853951707068945 + perim;
        return pcm.getClassFromOutput(node1 * node4);
    }

    PCM pcm8 = new BetterDRS(7.061628408878896, 255.69380925927666, new int[]{3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2});

    public int segmentRoads2(PixelLoader image, int x, int y) {
        boolean node7 = 1.4804566701492694 > image.get3x3Stats(x, y, ColourChannels.GREEN).getMean();
        double node6 = node7 ? 0.19004317022690254 : perimeter2StdDeviation;
        double node5 = node6 + perimeter1StdDeviation;
        double node3 = image.getLightness(x, y) + node5;
        double node1 = node3 != 0 ? image.get3x3Stats(x, y, ColourChannels.RED).getMean() / node3 : 0;
        return pcm8.getClassFromOutput(node1 * perimeter2Mean);
    }

    /**
     * Roughly segments the ground from the vegetation and other stuff.
     */
    public int segment1(PixelLoader image, int x, int y) {
        double node3 = Math.sin(3.9153116207066083);
        boolean node1 = ((perimeter2StdDeviation > node3) && (perimeter2StdDeviation < 1.7887720332995005));
        boolean node7 = image.getGreyValue(x, y) > image.getVLine1().getMean(image, x, y);
        double node6 = node7 ? image.getLaplacian(x, y) : 0;
        return pcm1.getClassFromOutput(node1 ? node6 : perimeter2Mean);
    }

    /**
     * Distinguishes non-ground areas into GROUND | ROAD | VEGETATION
     */
    BetterDRS pcm2 = new BetterDRS(2.1520729064941406, 254.8679331655907, new int[]{2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3});

    public int segment2(PixelLoader image, int x, int y) {
        double node4 = image.getGreyValue(x, y) * image.getVLine1().getStatistics(image, x, y).getStandardDeviation();
        boolean node3 = node4 < 0.927377288806687;
        double node2 = node3 ? -1.2975405977039982 : perimeter2StdDeviation;
        return pcm2.getClassFromOutput(perimeter2Mean - node2);
    }

    PCM pcm3 = new BetterDRS(-607.2808431873447, 254.1666717529297, new int[]{3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3});

    public int segmentRoads(PixelLoader image, int x, int y) {
        boolean node1 = 4.818144294300423 > image.getVLine2().getStatistics(image, x, y).getStandardDeviation();
        double node4 = image.getVLine1().getMean(image, x, y) * -1.9262090958707077;
        return pcm3.getClassFromOutput(node1 ? node4 : image.getPerimeter1().getMean(image, x, y));
    }

    PCM pcm6 = new BetterDRS(0.0, 156.6892685014202, new int[]{1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1});

    public int segmentVegetation(PixelLoader image, int x, int y) {
        boolean node1 = 0.1452774967467417 < image.get3x3Stats(x, y, ColourChannels.RED).getMean();
        double node8 = image.getHueMean() - 0.2971239965961562;
        boolean node12 = image.getSatMean() > image.getLightness(x, y);
        double node16 = perimeter1StdDeviation - perimeter2Mean;
        double node11 = node12 ? -0.650399620839067 : node16;
        double node4 = node8 - node11;
        return pcm6.getClassFromOutput(node1 ? node4 : image.getVLine1().getEdgeCount(image, x, y));
    }

    PCM pcm5 = new BetterDRS(-0.4156990527213743, 132.98972126710365, new
            int[]{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 4, 4, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1});

    public int segmentWater(PixelLoader image, int x, int y) {
        boolean node4 = ((5.0 > image.getBlue(x, y)) && (5.0 < perimeter2Mean));
        double node8 = image.getVLine2().getMean(image, x, y) != 0 ? image.getHue(x, y) / image.getVLine2().getMean(image, x, y) : 0;
        double node3 = node4 ? node8 : 2.0237345922324472;
        boolean node2 = node3 > image.getPerimeter2().getStatistics(image, x, y).getStandardDeviation();
        double node1 = node2 ? image.getLightnessMean() : -0.5131346779299553;
        double node15 = image.getLightness(x, y) / 8.0;
        return pcm5.getClassFromOutput(node1 + node15);
    }

    PCM pcm7 = new BetterDRS(-660.1791819844442, 254.22222900390625, new int[]{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, -1, 5, 5, 1, 5, 1, 5, 5, 5, -1, -1, -1, -1, 2, 2});    ;

    public int segmentWater2(PixelLoader image, int x, int y) {
        double vLine2EdgeCount = image.getVLine2().getEdgeCount(image, x, y);
        boolean node1 = 2.1596017366926343 < vLine2EdgeCount;
        boolean node6 = image.get3x3Mean(x, y) > 0;
        double node5 = node6 ? 0.8960221718150903 : vLine2EdgeCount;
        double node4 = node5 - 0.5502315674541226;
        boolean node13 = perimeter2StdDeviation < 1.649404886039592;
        boolean node23 = perimeter1StdDeviation > 2.592097132883169;
        double node26 = 2.8608903121304;
        double node22 = node23 ? node26 : image.get3x3Stats(x, y, ColourChannels.RED).getStandardDeviation();
        double node20 = perimeter2StdDeviation + node22;
        double node19 = node20 - perimeter2Mean;
        double node17 = 2.6269359040962574 * node19;
        double node12 = node13 ? image.get3x3Stats(x, y, ColourChannels.BLUE).getMean() : node17;
        return pcm7.getClassFromOutput(node1 ? node4 : node12);
    }

    PCM pcm4 = new BetterDRS(27.111709594726562, 324.5982360839844, new int[]{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7});

    public int segmentPipelines(PixelLoader image, int x, int y) {
        return pcm4.getClassFromOutput(image.get3x3Stats(x, y, ColourChannels.BLUE).getMean() + perimeter1StdDeviation);
    }

}
