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

package yi.iu.processor.texture.reg;

import yi.ai.cluster.*;
import yi.util.config.*;
import yi.util.data.*;
import yi.util.label.*;

/**
 * Still use color to guide texture segmentation.  But no post connected
 * component analysis.
 */
public class ColorGuidedTextureSegNCC
    extends ColorGuidedTextureSeg {

  public boolean DEMO_TEXTURE_SEG = true;
  public double MERGE_THRESHOLD = 0.5;

  public ColorGuidedTextureSegNCC() {
    super();
  }


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


    // use processor ColorPatternSeg to roughly segment the image to patterned
    // color regions
    ColorPatternSeg color_seg = new LooseColorPatternSeg();
    color_seg.DILATION_DISK_SIZE = DILATION_DISK_SIZE;
    color_seg.COMBINE_THRESHOLD = COMBINE_THRESHOLD;
    DS_ColorPatternRegions color_regions = color_seg.getReusableColorPatternRegions(pixels, width, height);
    int[] color_region_labels = color_regions.getLabels();

    if (DEMO_COLOR_PATTERN_SEG) {
      int[] region_img = yi.util.ImageUtil.makeNewImageFromLabel(color_region_labels);
      String img_name = Configuration.getStringParameter("SOURCE_NAME", "unknown");
      yi.util.io.OutputResult.outputGIFImage(img_name + "_patterned_color_regions.gif", region_img, width, height);
    }

    // use texture segmentation
    int color_region_num = yi.stat.StatUtil.maximum(color_region_labels) + 1;
    Clusters texture_segs = textureSegOnRegions(
      pixels, color_region_labels, color_region_num, width, height);
    int[] texture_region_labels = texture_segs.getClusterMap();
    double[][] texture_means = texture_segs.getClusterMeans();

    // demo the regions after texture segmentation
    if (DEMO_TEXTURE_SEG_BEFORE_FILTER) {
      int[] region_img = yi.util.ImageUtil.makeNewImageFromLabel(texture_region_labels);
      String img_name = Configuration.getStringParameter("SOURCE_NAME", "unknown");
      yi.util.io.OutputResult.outputGIFImage(img_name + "_before_filter.gif", region_img, width, height);
    }

    // now remove those single regions which are super small.
    // find connected components (these are also sequentially labeled)
    // 0 should be treated as background
//    ConnectComponent cc = new ConnectComponent();
//    int[] cc_labels = cc.compactLabeling(texture_region_labels, new Dimension(width, height), true);
//    filterSmallRegions(cc_labels, (int)(MINIMUM_REGION_SIZE * width * height / 10));
//
//    for (int i=0; i<texture_region_labels.length; i++) {
//      if (cc_labels[i] == 0) texture_region_labels[i] = 0;
//    }

    // No filtering here, only filter out small size of regions (the regions can be dis-connected)
//    filterSmallRegions(texture_region_labels, (int)(MINIMUM_REGION_SIZE * width * height));

    // merge close clusters
    Label.sequential(texture_region_labels, null, true);
    double[][] means = Label.getMeans(m_features, texture_region_labels);
    int[] counts = Label.getCounts(texture_region_labels);
    double[] double_counts = Conversion.toDouble(counts);
    int[] label_map = ClosestMerger.merge(means, double_counts, MERGE_THRESHOLD, true);
    for (int i=0; i<texture_region_labels.length; i++) {
      texture_region_labels[i] = label_map[texture_region_labels[i]];
    }

    return texture_region_labels;

  }


  /**
   * Filter out small regions.  0 will be untouched.
   * @param labels
   * @param size_threshold
   * @return
   */
  void filterSmallRegions(int[] labels, int size_threshold) {

    Label.filterSmallRegions(labels, size_threshold);// filtering small component
    Label.sequential(labels,null,true);
  }

//  public static class GenTextureLabeledRgnFts {
//    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);
//      }
//
//      String from_path = ReadArgu.getOption('f', args, "");
//      String to_path = ReadArgu.getOption('t', args, "");
//
//      // get the scale
//      String scale_str = ReadArgu.getOption('s', args);
//      int scale = 1;
//      if (scale_str != null) {
//        scale = Integer.parseInt(scale_str);
//      }
//
//      // get the result scale
//      String rst_scale_str = ReadArgu.getOption('r', args, "1");
//      int rst_scale = Integer.parseInt(rst_scale_str);
//
//      // read in image
//      Image image = yi.util.io.ImageReader.JAIReadImage(from_path + img_name);
//      Dimension d = new Dimension();
//      int[] pixels = yi.util.io.ImageReader.getPixels(image, d);
//      Dimension old_d = (Dimension)d.clone();
//
//      // rescale the image if necessary
//      double the_scale = 1.0;
//      if (scale != 1) {
//        ColorGuidedTextureSeg dummy = new ColorGuidedTextureSeg();
//        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;
//        }
//      }
//
//      // result scale
//      Dimension rst_dim = d;
//      if (rst_scale != 1) {
//        rst_dim = Resampler.getDestSize(d.width, d.height, rst_scale, rst_scale);
//        img_name = img_name + ".r" + rst_scale;
//      }
//
//      // process
//      try {
//
//        // process
//        Configuration.setParameter("SOURCE_NAME", img_name);
//        Configuration.setParameter("DEST_PATH", to_path);
//        // make destination directory
//        yi.util.io.File.makeDirectory(to_path + img_name, true);
//
//        yi.util.ImageUtil.setPixels(pixels);
//        yi.util.ImageUtil.setDimension(d);
//
//        /** @todo use ColorGuidedTextureSegWPCA for now */
//        ColorGuidedTextureSegNCC processor = new ColorGuidedTextureSegNCC();
//        long startTime = System.currentTimeMillis();
//        TextureLabeledRgnFts ds = processor.getReusableTextureLabeledRgnFts(pixels, d.width, d.height,
//            old_d.width, old_d.height, rst_dim.width, rst_dim.height);
//        long endTime = System.currentTimeMillis();
//        System.out.println("running time: " + (endTime-startTime));
//
//        int[] demo = ds.demo();
//        yi.util.io.OutputResult.outputGIFImage(to_path + img_name + ".text.rgn.gif",
//                                               demo, rst_dim.width,
//                                               rst_dim.height, false);
//
//
//      } catch (Exception e) {
//        System.err.println("broken when processing " + img_name);
//        e.printStackTrace();
//      }
//
//    }
//  }
//
//  public static class GenTextureLabRgnFtsPxlVal {
//
//    public final static String USAGE = "Usage: -i image_name -f from_path -t to_path -s scale -r result_scale";
//
//    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);
//      }
//
//      String from_path = ReadArgu.getOption('f', args, "");
//      String to_path = ReadArgu.getOption('t', args, "");
//
//      // 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);
//      }
//
//      // get the result scale
//      String rst_scale_str = ReadArgu.getOption('r', args, "1");
//      int rst_scale = Integer.parseInt(rst_scale_str);
//
//      try {
//
//        // read in image
//        Dimension d = new Dimension();
//        int[] pixels = yi.util.io.ImageIOUtil.read(from_path + img_name, d);
//
//        Dimension old_d = (Dimension) d.clone();
//
//        // rescale the image if necessary
//        double the_scale = 1.0;
//        if (scale != 1) {
//          ColorGuidedTextureSeg dummy = new ColorGuidedTextureSeg();
//          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;
//          }
//        }
//
//        // result scale
//        Dimension rst_dim = d;
//        if (rst_scale != 1) {
//          rst_dim = Resampler.getDestSize(d.width, d.height, rst_scale,
//                                          rst_scale);
//          img_name = img_name + ".r" + rst_scale;
//        }
//
//        // process
//        Configuration.setParameter("SOURCE_NAME", img_name);
//        Configuration.setParameter("DEST_PATH", to_path);
//        // make destination directory
//        yi.util.io.File.makeDirectory(to_path + img_name, true);
//
//        yi.util.ImageUtil.setPixels(pixels);
//        yi.util.ImageUtil.setDimension(d);
//
//        /** @todo use ColorGuidedTextureSegWPCA for now */
//        ColorGuidedTextureSegNCC processor = new ColorGuidedTextureSegNCC();
//        long startTime = System.currentTimeMillis();
//        TextureLabRgnFtsPxlVal ds = processor.getReusableTextureLabRgnFtsPxlVal(
//            pixels, d.width, d.height, old_d.width, old_d.height, rst_dim.width, rst_dim.height);
//        long endTime = System.currentTimeMillis();
//        System.out.println("running time: " + (endTime-startTime));
//
//        int[] demo = ds.demo();
//        yi.util.io.OutputResult.outputGIFImage(to_path + img_name + ".text.rgn.gif",
//                                               demo, rst_dim.width,
//                                             rst_dim.height, false);
//
//
//      } catch (Exception e) {
//        System.err.println("broken when processing " + img_name);
//        e.printStackTrace();
//      }
//
//      System.exit(0);
//    }
//  }
//
//  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) {
//      ColorGuidedTextureSeg dummy = new ColorGuidedTextureSeg();
//      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);
//
//      /** @todo use ColorGuidedTextureSegWPCA for now */
//      ColorGuidedTextureSegNCC processor = new ColorGuidedTextureSegNCC();
//      long startTime = System.currentTimeMillis();
//      //DS_GaborTextureRegions ds = processor.getReusableTextureRegions(pixels, d.width, d.height, 1.0);
//      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.poly.gif", demo, d.width,
//                                             d.height, false);
//
//      if (processor.DEMO_ONE_BY_ONE) {
//        ds.demoRegions(img_name, pixels, -1, 0xffff0000);
//      }
//
//
//    } catch (Exception e) {
//      System.err.println("broken when processing " + img_name);
//      e.printStackTrace();
//    }
//
//  }


}