package ac.essex.gp.ooechs.detection;

import ac.essex.ooechs.imaging.commons.util.ImageFilenameFilter;
import ac.essex.ooechs.imaging.commons.HaarRegions;
import ac.essex.ooechs.imaging.commons.PixelLoader;
import ac.essex.ooechs.adaboost.AdaBoost;
import ac.essex.ooechs.adaboost.AdaBoostSample;
import ac.essex.ooechs.adaboost.AdaBoostSolution;
import ac.essex.ooechs.adaboost.AdaBoostLearner;
import ac.essex.gp.ooechs.detection.gp.HaarTrainingSet;
import ac.essex.gp.ooechs.detection.gp.DetectionProblem;
import ac.essex.gp.ooechs.detection.evolved.IndividualFaceDetector;
import ac.essex.gp.Evolve;
import ac.essex.gp.problems.DataStack;
import ac.essex.gp.individuals.Individual;
import ac.essex.gp.interfaces.console.ConsoleListener;
import ac.essex.gp.params.GPParams;

import java.util.Vector;
import java.io.File;
import java.io.IOException;

/**
 * Attempts to solve the face detector problem using Adaboost. The weak learners used are simply
 * one of the haar basis functions.
 *
 * @author Olly Oechsle, University of Essex, Date: 17-May-2007
 * @version 1.0
 */
public class BoostedDetectionProblem extends AdaBoost {

    Vector<AdaBoostSample> samples;

    public static void main(String[] args) throws Exception {

        birdEye();

    }

    public static void birdEye() throws IOException {
        long start = System.currentTimeMillis();

        BoostedDetectionProblem l = new BoostedDetectionProblem();

        // true training data
        l.addImageFiles(new File("/home/ooechs/Desktop/birds/toucan/eyes"), DetectionProblem.OBJECT1);
        l.addImageFiles(new File("/home/ooechs/Desktop/birds/mandarin/eyes"), DetectionProblem.OBJECT1);

        // false training data
        l.addImageFiles(new File("/home/ooechs/ecj-training/faces/essex/false1/"), DetectionProblem.NOT_OBJECT);
        l.addImageFiles(new File("/home/ooechs/Desktop/birds/mandarin/false"), DetectionProblem.NOT_OBJECT);
        l.addImageFiles(new File("/home/ooechs/Desktop/birds/mandarin/false2"), DetectionProblem.NOT_OBJECT);
        l.addImageFiles(new File("/home/ooechs/Desktop/birds/mandarin/false3"), DetectionProblem.NOT_OBJECT);

        l.boost(30);

        AdaBoostSolution s0 = l.getBestSolution();

        long time = System.currentTimeMillis() - start;

        System.out.println("Saving solution...");

        s0.save(new File("/home/ooechs/Desktop/birds/toucan/eyes.solution"));

        System.out.println("Time taken: " + time);
    }

    public static void birdFace() throws IOException {
        long start = System.currentTimeMillis();

        BoostedDetectionProblem l = new BoostedDetectionProblem();

        // true training data
        l.addImageFiles(new File("/home/ooechs/Desktop/birds/mandarin/faces/left"), DetectionProblem.OBJECT1);

        // false training data
        l.addImageFiles(new File("/home/ooechs/ecj-training/faces/essex/false1/"), DetectionProblem.NOT_OBJECT);
        l.addImageFiles(new File("/home/ooechs/Desktop/birds/mandarin/false"), DetectionProblem.NOT_OBJECT);
        l.addImageFiles(new File("/home/ooechs/Desktop/birds/mandarin/false2"), DetectionProblem.NOT_OBJECT);
        l.addImageFiles(new File("/home/ooechs/Desktop/birds/mandarin/false3"), DetectionProblem.NOT_OBJECT);

        l.boost(30);

        AdaBoostSolution s = l.getBestSolution();

        System.out.println(s);

        long time = System.currentTimeMillis() - start;

        System.out.println("Saving solution...");

        s.save(new File("/home/ooechs/Desktop/birds/mandarin/left-faces2.solution"));

        System.out.println("Time taken: " + time);
    }

    public static void pipes() throws IOException {
        long start = System.currentTimeMillis();

        BoostedDetectionProblem l = new BoostedDetectionProblem();

        DetectionProblem.WINDOW_WIDTH =50;
        DetectionProblem.WINDOW_HEIGHT = 3;
        DetectionProblem.WINDOWBLOCKSX = 25;
        DetectionProblem.WINDOWBLOCKSY = 3;

        // true training data
        l.addImageFiles(new File("/home/ooechs/Desktop/pipes_coloured/Foreground"), DetectionProblem.OBJECT1);

        // false training data
        l.addImageFiles(new File("/home/ooechs/Desktop/pipes_coloured/Background"), DetectionProblem.NOT_OBJECT);

        l.boost(30);

        AdaBoostSolution s = l.getBestSolution();

        System.out.println(s);

        long time = System.currentTimeMillis() - start;

        System.out.println("Saving solution...");

        s.save(new File("/home/ooechs/Desktop/pipes_coloured/pipes.solution"));

        System.out.println("Time taken: " + time);
        
    }


    public BoostedDetectionProblem() {

        samples = new Vector<AdaBoostSample>();

    }

    public AdaBoostSample[] getSamples() {

       AdaBoostSample[] s = new AdaBoostSample[samples.size()];

       return samples.toArray(s);

    }

    public int addImageFiles(File directory, int classID) {

        if (!directory.exists()) throw new RuntimeException("Directory does not exist: " + directory.getAbsolutePath());
        int counter = 0;
        try {
            File[] trueFiles = directory.listFiles();

            for (int i = 0; i < trueFiles.length; i++) {
                File f = trueFiles[i];
                if (ImageFilenameFilter.isImage(f)) {
                    
                    HaarTrainingSet haarTrainingSet = new HaarTrainingSet(new HaarRegions(new PixelLoader(f)), classID);

                    if (haarTrainingSet.classID == DetectionProblem.OBJECT1) {
                        haarTrainingSet.image.makeWindowFillImage(DetectionProblem.WINDOWBLOCKSX, DetectionProblem.WINDOWBLOCKSY);
                    } else {
                        int x = (int) (Math.random() * (haarTrainingSet.image.getWidth() - DetectionProblem.WINDOW_WIDTH));
                        int y = (int) (Math.random() * (haarTrainingSet.image.getHeight() - DetectionProblem.WINDOW_HEIGHT));
                        haarTrainingSet.image.setWindowPosition(x, y, DetectionProblem.WINDOW_WIDTH, DetectionProblem.WINDOW_HEIGHT, DetectionProblem.WINDOWBLOCKSX, DetectionProblem.WINDOWBLOCKSY);
                    }

                    samples.add(haarTrainingSet);

                    counter++;
                }
            }
            System.out.println("\nLoaded: " + counter + " images.");

        } catch (Exception e) {
            e.printStackTrace();
        }
        return counter;
    }

    protected AdaBoostLearner weakLearn(AdaBoostSample[] adaBoostM1Samples, double[] weights) {

        // run the GP process here
        DetectionProblem problem = new DetectionProblem();
        problem.addImageFiles(adaBoostM1Samples);
        problem.weights = weights;
        GPParams params = new GPParams();
        params.setGenerations(20);
        params.setPopulationSize(800);
        ConsoleListener listener = new ConsoleListener(ConsoleListener.SILENT);
        Evolve e = new Evolve(problem, listener, params);
        e.run();

        // copying loses the pcm, so rebuild it
        Individual ind = e.getBestIndividual();
        problem.buildProgramClassificationMap(new DataStack(), ind);
        ind.setPCM(problem.pcm);

        return new IndividualFaceDetector(ind);
        
    }

}
