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

package yi.iu.processor.texture.reg;

import yi.iu.region.*;
import java.awt.*;
import yi.graph.polygon.*;
import java.util.LinkedList;
import yi.util.io.input.*;
import yi.util.config.*;
import java.util.*;
import yi.stat.pca.*;
import yi.iu.imgdb.learn.*;

/**
 * DS_PolygonRegionTextureStat is a set of PolygonRegionTextureStat
 */
public class DS_PolygonRegionTextureStat extends DS_PolygonRegionFeatureStat
{

  /**
   * @param feature_set
   */
  public DS_PolygonRegionTextureStat(DS_PolygonRegionFeatureStat feature_set)
  {
    super(feature_set);
  }

  /**
   * @param data
   * @param labels
   * @param width
   * @param height
   * @param ignore_zero
   */
  public DS_PolygonRegionTextureStat(double[][] data, int[] labels, int width, int height, boolean ignore_zero)
  {
    m_imgWidth  = width;
    m_imgHeight = height;
    PolygonRegionFeatureStat[] regions =
        PolygonRegionFeatureStat.createPolygonRegionFeatureStats(data, labels, width, height, ignore_zero);
    m_regions = new PolygonRegionTextureStat[regions.length];
    for (int i=0; i<regions.length; i++) {
      m_regions[i] = new PolygonRegionTextureStat(regions[i]);
    }
  }

  /**
   * @param w
   * @param h
   * @param regions
   */
  public DS_PolygonRegionTextureStat(int w, int h, PolygonRegionTextureStat[] regions)
  {
    super(w,h,regions);
  }

  public DS_PolygonRegionTextureStat()
  {
    super();
  }

//  /**
//   * @param img
//   * @return LinkedList
//   */
//  public LinkedList represent(String img)
//  {
//    /** @todo scale should be setable */
//    int scale = 256;
//    String scaled_img_name = img;
//    if (scale != 0) scaled_img_name = img + yi.iu.processor.resample.Resampler.RESIZED_FILE_SUFFIX + scale;
//    Configuration.setParameter("SOURCE_NAME", scaled_img_name);
//
//    // read the results from the output xml
//    ColorGuidedTextureSeg dp = new ColorGuidedTextureSeg();
//    DS_PolygonRegionTextureStat ds = (DS_PolygonRegionTextureStat)dp.reusePolygonRegionTextureStat(DIU.INPUT_XML);
//    double[][] fvs = ds.getFeatureVectors(0);
//
//    // the first feature data is corresponding to the background, so ignore it
//    LinkedList list = new LinkedList();
//    for (int i=1; i<fvs.length; i++) {
//      list.add(fvs[i]);
//    }
//    return list;
//  }

  /**
   * represent the filter responses as vectors.  e.g. for 12 Gabor, return
   * vectors of size 12
   */
  public final static int REP_VECTORS = 0;

  /**
   * process the vectors first with PCA, and then return the processed result
   */
  public final static int REP_PCA_REDUCED = 1;

  /**
   * Represent the texture feature as feature vectors.  "mode" defines how to
   * represent the feature values.  REP_VECTORS and REP_PCA_REDUCED are
   * available
   * @param processor_name
   * @param scale
   * @param img
   * @param mode
   * @return
   * @throws Exception
   */
  public FeatureRepresentationList represent(String processor_name, int mode) throws Exception
  {
    double[][] fvs = getFeatureVectors(0);

    if (mode == REP_VECTORS) {
      return new FeatureRepresentationList(fvs, fvs[0].length);
    }

    // pca analysis
    if (pca == null) {
      pca = PCAOnCorrelation.createFromFile("texture.pca");
    }
    double[][] fvs_pca = pca.project(fvs);

    // the first feature data is corresponding to the background, so ignore it
    // only use the important dimensions
    double[][] fvs_reduced = new double[fvs_pca.length - 1][PCA_REDUCED_TO];
    for (int i=1; i<fvs_pca.length; i++) {
      for (int j=0; j<PCA_REDUCED_TO; j++) {
        fvs_reduced[i-1][j] = fvs_pca[i][j];
      }
    }

    return new FeatureRepresentationList(fvs_reduced, fvs_reduced[0].length);
  }

  public int PCA_REDUCED_TO = 6;
  static PCAOnCorrelation pca = null;

  public DS_PolygonRegionTextureStat createFromFile(String processor_name,
      int scale,
      String img) throws Exception {
    String scaled_img_name = img;
    if (scale != 0)
      scaled_img_name = img +
          yi.iu.processor.resample.Resampler.RESIZED_FILE_SUFFIX + scale;
    Configuration.setParameter("SOURCE_NAME", scaled_img_name);

    // read the results from the output xml
    ColorGuidedTextureSeg dp = (ColorGuidedTextureSeg) Class.forName(
        processor_name).newInstance(); ;
    DS_PolygonRegionTextureStat ds = (DS_PolygonRegionTextureStat) dp.
        reusePolygonRegionTextureStat(DIU.INPUT_XML);
    return ds;
  }

  public FeatureRepresentable createFeatureFromFile(String processor_name, int scale,
      String img) throws Exception {
    return createFromFile(processor_name, scale, img);

  }
  public FeatureRepresentable createFeatureFromFile(String processor_name, int scale, int rst_scale, String img) throws Exception {
    /**@todo Implement this yi.iu.imgdb.learn.FeatureRepresentable method*/
    throw new java.lang.UnsupportedOperationException("Method createFeatureFromFile() not yet implemented.");
  }

  public PolygonFeatureRepresentationList representPolygonFeatures(
     String processor_name, int mode)  throws Exception
  {
    double[][] fvs = getFeatureVectors(0);

    if (mode == REP_PCA_REDUCED) { // use PCA to reduce the dimension
      // pca analysis
      if (pca == null) {
        pca = PCAOnCorrelation.createFromFile("texture.pca");
      }
      double[][] fvs_pca = pca.project(fvs);

      // the first feature data is corresponding to the background, so ignore it
      // only use the important dimensions
      double[][] fvs_reduced = new double[fvs_pca.length - 1][PCA_REDUCED_TO];
      for (int i = 1; i < fvs_pca.length; i++) {
        for (int j = 0; j < PCA_REDUCED_TO; j++) {
          fvs_reduced[i - 1][j] = fvs_pca[i][j];
        }
      }
      fvs = fvs_reduced;
    }

    double scale = getScale();
    int width = (int)Math.round(getImageWidth()/scale);  // recover the image width and height
    int height = (int)Math.round(getImageHeight()/scale);
    // get the region information
    PolygonFeatureRepresentationList list = new PolygonFeatureRepresentationList(fvs[0].length, width, height);
    // the first feature data is corresponding to the background, so ignore it
    for (int i=1; i<m_regions.length; i++) {
      PolygonRegionFeatureStat f = m_regions[i];
      // rescale the polygon
      GenericPolygon region = f.getPolygonRegion();
      region.scale(1/scale);
      list.add(new PolygonFeatureRepresentation(fvs[i-1], region));
    }

    return list;
  }


  public static void main(String[] args) {
    try {
      DS_PolygonRegionTextureStat texture = new DS_PolygonRegionTextureStat();
//    FeatureRepresentationList data = texture.represent("F:/groundtruth/arborgreens/arborgreens01.jpg");
//    double[][] vectors = data.as2DDoubleArray();
//    yi.util.io.OutputResult.print(System.out, vectors, 5, vectors.length);
      DS_PolygonRegionTextureStat ds = (new DS_PolygonRegionTextureStat()).createFromFile(
          "yi.iu.processor.texture.reg.ColorGuidedTextureSeg", 256,
          "F:/groundtruth/arborgreens/arborgreens01.jpg");
      PolygonFeatureRepresentationList data2 = texture.representPolygonFeatures(
          "yi.iu.processor.texture.reg.ColorGuidedTextureSeg",
          DS_PolygonRegionTextureStat.REP_VECTORS);
      double[][] vectors = data2.as2DDoubleArray();
      yi.util.io.OutputResult.print(System.out, vectors, 5, vectors.length);

      int width = data2.imgWidth, height = data2.imgHeight;
      int[] pixels =
          data2.drawScoreDemo(null,
                              new FeatureScoringCapable() { // a inner class give sequence score
        int count = 1;
        public double getFeatureScore(double[] feature, Object obj) {
          return count++;
        }
      }

      , 0, 1);
      int[] pixels_img = yi.util.ImageUtil.makeNewImageFromLabel(pixels, true);
      yi.util.io.OutputResult.outputGIFImage("score.gif", pixels_img, width,
                                             height);
    } catch(Exception e) {
      e.printStackTrace();

    }

  }
}
