//Source file: D:\\Projects\\src\\yi\\iu\\processor\\texture\\reg\\TextureClusterGuidedSeg.java

package yi.iu.processor.texture.reg;

import yi.util.config.*;
import yi.util.io.*;
import java.awt.*;
import yi.iu.processor.resample.*;
import yi.util.label.Label;
import yi.math.*;
import yi.iu.processor.filter.*;
import yi.stat.pca.*;
import yi.stat.em.*;
import yi.iu.processor.texture.gabor.*;

/**
 * Knowing the promising clusters, segment pixels to their appropriate clusters.
 */
public class TextureClusterGuidedSeg extends ColorGuidedTextureSeg
{

  public int SMOOTH_HEIGHT = 17;
  public int SMOOTH_WIDTH = 17;

  public int PCA_REDUCED_TO = 6;
  public String GMM_FILE = "tppca.model.ser";

  public TextureClusterGuidedSeg()
  {
  }

  public int[] getLabels(int[] pixels, int width, int height) {
    try {

      DoubleMatrix features = calculateGabor(pixels, width, height);

      // smooth each pixel in (SMOOTH_WIDTH) x (SMOOTH_HEIGHT) block
      double[] dat = new double[features.height];
      for (int i = 0; i < features.width; i++) { // for each dim
        for (int j = 0; j < features.height; j++) {
          dat[j] = features.data[j][i];
        }
        double[] smoothed = Average.average(dat, width, height, SMOOTH_WIDTH,
                                            SMOOTH_HEIGHT);
        for (int j = 0; j < features.height; j++) {
          features.data[j][i] = smoothed[j];
        }
      }

      // pca conversion
      // pca analysis
      PCAOnCorrelation pca = PCAOnCorrelation.createFromFile("texture.pca");
      double[][] data_pca = pca.project(features.data);

      // only use the important dimensions
      double[][] data_reduced = new double[data_pca.length][PCA_REDUCED_TO];
      for (int i = 0; i < data_pca.length; i++) {
        for (int j = 0; j < PCA_REDUCED_TO; j++) {
          data_reduced[i][j] = data_pca[i][j];
        }
      }

      // clustering use gmm model
      GaussianMixtureModel gmm = GaussianMixtureModel.createFromFile(GMM_FILE);

      int[] label = new int[width * height];
      for (int i = 0; i < label.length; i++) {
        label[i] = gmm.classify(data_reduced[i]);
      }

      int boundary_effect_size = (int) Math.round(Gabor.maskSize *
                                                  BOUNDARY_EFFECT_SIZE);
//      setBoundary(label, width, height, boundary_effect_size, 0);

      yi.util.label.Label.sequential(label, null, true);
      m_features = data_reduced;

      return label;
    }catch (Exception e) {
      e.printStackTrace();
      return null;
    }

  }

  public static void main(String[] args) {
    // init configuration
    Configuration.init(args);

    // get the image name
    String img_name = ReadArgu.getOption('i', args);
    if (img_name == null) {
      System.err.println("Usage: -i image_name");
      System.exit(1);
    }

    // read in image
    // get the scale
    String scale_str = ReadArgu.getOption('s', args);
    int scale = 1;
    if (scale_str != null) {
      scale = Integer.parseInt(scale_str);
    }

    // read in image
    Image image = yi.util.io.ImageReader.JAIReadImage(img_name);
    Dimension d = new Dimension();
    int[] pixels = yi.util.io.ImageReader.getPixels(image, d);

    // rescale the image if necessary
    double the_scale = 1.0;
    if (scale != 1) {
      TextureClusterGuidedSeg dummy = new TextureClusterGuidedSeg();
      ResampledDescriptor resampled = Resampler.scaleDown(pixels, d,
          dummy.RESAMPLER, scale);
      if (resampled != null) {
        pixels = resampled.m_resampled;
        d = resampled.m_newDimension;
        the_scale = resampled.m_scale;
        img_name = img_name + Resampler.RESIZED_FILE_SUFFIX + scale;
      }
    }

    // process
    try {

      Configuration.setParameter("SOURCE_NAME", img_name);
      yi.util.ImageUtil.setPixels(pixels);
      yi.util.ImageUtil.setDimension(d);

      TextureClusterGuidedSeg processor = new TextureClusterGuidedSeg();
      long startTime = System.currentTimeMillis();
      DS_PolygonRegionTextureStat ds = processor.getReusablePolygonRegionTextureStat(pixels, d.width, d.height, the_scale);
      long endTime = System.currentTimeMillis();
      System.out.println("running time: " + (endTime-startTime));

      int[] demo = ds.getPolygonDemo(null, true);
      yi.util.io.OutputResult.outputGIFImage(img_name + ".text.reg.gif", demo, d.width,
                                             d.height, false);

    } catch (Exception e) {
      System.err.println("broken when processing " + img_name);
      e.printStackTrace();
    }

    System.exit(0);
  }

}
