Example #1
0
void clusclus::Clustering()
{
	int num_currcluster = num_samples;
	int pivot1,pivot2;

	ComputeSampleDistances();
	for (int i = 0; i < num_samples; i++)
	{
		features[i][num_features]=i;
		features[i][num_features+1]=i;
		num_cluster_samples[i]=1;
		for(int j = 0; j< i+1; j++)
		{
			cluster_distances[i*(1+i)/2+j]=sample_distances[i*(1+i)/2+j];
		}
	}
	for(int i=0; i<num_samples-1; i++)
	{
		if( num_currcluster % 100 == 0)
		{
			std::cout<<"left: "<<num_currcluster<< std::endl;
		}
		mergers[i][0] = i;
		mergers[i][4]=MergeClusters(num_currcluster, &pivot1, &pivot2);
		mergers[i][1]=pivot1;
		mergers[i][2]=pivot2;
		mergers[i][3]=UpdateClusterDistances(num_currcluster,pivot1,pivot2);

		num_currcluster--;
	}
}
Example #2
0
void QueryClusterer::UpdateCluster() {
  // This function needs to be scheduled periodically for updating the clusters
  // Update the feature vectors of all templates, update new and existing
  // templates and merge the clusters
  UpdateFeatures();
  UpdateExistingTemplates();
  MergeClusters();
}
/*------------------------------------------------------------------------*/
void MergeInsignificantProtos(LIST ProtoList, const char* label,
                              CLUSTERER	*Clusterer, CLUSTERCONFIG *Config) {
  PROTOTYPE	*Prototype;
  bool debug = strcmp(test_ch, label) == 0;

  LIST pProtoList = ProtoList;
  iterate(pProtoList) {
    Prototype = (PROTOTYPE *) first_node (pProtoList);
    if (Prototype->Significant || Prototype->Merged)
      continue;
    FLOAT32 best_dist = 0.125;
    PROTOTYPE* best_match = NULL;
    // Find the nearest alive prototype.
    LIST list_it = ProtoList;
    iterate(list_it) {
      PROTOTYPE* test_p = (PROTOTYPE *) first_node (list_it);
      if (test_p != Prototype && !test_p->Merged) {
        FLOAT32 dist = ComputeDistance(Clusterer->SampleSize,
                                       Clusterer->ParamDesc,
                                       Prototype->Mean, test_p->Mean);
        if (dist < best_dist) {
          best_match = test_p;
          best_dist = dist;
        }
      }
    }
    if (best_match != NULL && !best_match->Significant) {
      if (debug)
        tprintf("Merging red clusters (%d+%d) at %g,%g and %g,%g\n",
                best_match->NumSamples, Prototype->NumSamples,
                best_match->Mean[0], best_match->Mean[1],
                Prototype->Mean[0], Prototype->Mean[1]);
      best_match->NumSamples = MergeClusters(Clusterer->SampleSize,
                                             Clusterer->ParamDesc,
                                             best_match->NumSamples,
                                             Prototype->NumSamples,
                                             best_match->Mean,
                                             best_match->Mean, Prototype->Mean);
      Prototype->NumSamples = 0;
      Prototype->Merged = 1;
    } else if (best_match != NULL) {
      if (debug)
        tprintf("Red proto at %g,%g matched a green one at %g,%g\n",
                Prototype->Mean[0], Prototype->Mean[1],
                best_match->Mean[0], best_match->Mean[1]);
      Prototype->Merged = 1;
    }
  }
  // Mark significant those that now have enough samples.
  int min_samples = (inT32) (Config->MinSamples * Clusterer->NumChar);
  pProtoList = ProtoList;
  iterate(pProtoList) {
    Prototype = (PROTOTYPE *) first_node (pProtoList);
    // Process insignificant protos that do not match a green one
    if (!Prototype->Significant && Prototype->NumSamples >= min_samples &&
        !Prototype->Merged) {
      if (debug)
        tprintf("Red proto at %g,%g becoming green\n",
                Prototype->Mean[0], Prototype->Mean[1]);
      Prototype->Significant = true;
    }
  }
}	/* MergeInsignificantProtos */
Example #4
0
/*
  See "change detection" wikis and http://people.irisa.fr/Michele.Basseville/

  The letter-detection needs to be done online, but offline may be doable as well.

  Implements an event oriented state machine in which it is easier to exit states than enter them.
  This helps detect the confounded edge between neighbor-key transitions, a difficult case.
  The only event parameter is stDev; other attributes tend to lead stDev, so a better trigger function
  could probably be devised.
*/
void SingularityBuilder::Process3(vector<Point>& inData, vector<PointMu>& outData)
{
  bool trig = false;
  //char c;
  vector<PointMu> midData;
  int i, sampleRate, segmentWidth, trigger, eventStart, eventEnd, stDevTrigger;
  double dDist, dist, dydx, lastDist, coVar, stDev, nKeyHits, avgDist, avgTheta, lastTheta, dTheta; 
  char currentAlpha = '!', prevAlpha = '!';

  //segment width is the sample radius for assessing a trigger
  sampleRate = 1;  //sample every two ticks. Thus, there will be n/2 analyses
  segmentWidth = 3; //every k ticks, grab next k point for analysis
  lastTheta = dTheta = avgTheta = 0.0;

  int triggerThreshold = 4;
  int highFocus = 45;
  double stDev_HardTrigger = 225;
  double stDev_SoftTrigger = 14;

  cout << "processing " << inData.size() << " data points in sb.process(), dxThreshold=" << dxThreshold << endl;

  //TODO: sleep if no data
  trigger = 0;
  for(i = 0; i < (inData.size() - segmentWidth - 1); i += sampleRate){
    //ignore points outside of the active region, including the <start/stop> region
    if(InBounds(inData[i]) && InBounds(inData[i+segmentWidth-1])){
      //measures absolute change in distance, a dumb attribute
      //lastDist = dist;
      //dist = layoutManager->DoubleDistance(inData[i],inData[i+segmentWidth-1]);
      //dDist = dist - lastDist;
      //dydx = layoutManager->DyDx(inData[i],inData[i+segmentWidth-1]); //slope
      //dydx = layoutManager->AvgDyDx(inData,i,segmentWidth);
      //avgDist = layoutManager->AvgDistance(inData,i,segmentWidth);
      //measures clustering of a group of points, but only the points themselves
      //coVar = layoutManager->CoVariance(inData,i,segmentWidth);
      stDev = layoutManager->CoStdDeviation(inData,i,segmentWidth); //(sigmaX*sigmaY)^2
	    //lastTheta = avgTheta;
	    //avgTheta = layoutManager->AvgTheta(inData,i,segmentWidth);  //get the avg direction for a sequence of points
	    //dTheta = (avgTheta - lastTheta) / 2.0;
      //printf("stDev,avgDist,dDist,dydx,avgTheta,dTheta: %9.3f  %9.3f  %9.3f  %9.3f  %9.3f  %9.3f\n",stDev,avgDist,dDist,dydx,avgTheta,dTheta);
      currentAlpha = layoutManager->FindNearestKey(inData[i]);

      if(stDev < stDev_HardTrigger){
        printf("curAlpha, prevAlpha, pt-stDev: %c  %c  %9.3f  %d  %d  pretrig\n",currentAlpha,prevAlpha,stDev,inData[i].X,inData[i].Y);
      }
      else{
        printf("curAlpha, prevAlpha, pt-stDev: %c  %c  %9.3f  %d  %d\n",currentAlpha,prevAlpha,stDev,inData[i].X,inData[i].Y);
      }
      /*
        Implements an event oriented state machine in which it is easier to exit states than enter them.
        This helps detect the confounded edge between neighbor-key transitions, a difficult case.
      */
      if(stDev < stDev_HardTrigger){

        //gives the trigger faster progress when confidence is higher; there ought to be a more continuous way to do this
        if(stDev < highFocus){
          trigger += 2;
        }
        else{
          trigger++;
        }
        
        //trigger and collect event
        if(trigger > triggerThreshold){
          cout << "trig" << endl;
          //this optimistically assumes current position has (intentional) focus on some key
          prevAlpha = currentAlpha = layoutManager->FindNearestKey(inData[i]);
          eventStart = i;
          i++;
          stDev = layoutManager->CoStdDeviation(inData,i,segmentWidth);
          //hold state, unless there is a stDev change and an alpha change. Only if both alpha changes and stDev throws, will we exit.
          // A new event will immediately be thrown to catch the neighbor key event.
          while(i < inData.size() && (stDev < stDev_SoftTrigger || prevAlpha == currentAlpha) && (stDev < stDev_HardTrigger)){
          //while(i < inData.size() && (stDev < stDev_SoftTrigger && prevAlpha == currentAlpha) && (stDev < stDev_HardTrigger)){
          //while(i < inData.size() && (stDev < stDev_SoftTrigger || prevAlpha == currentAlpha) && (stDev < stDev_HardTrigger)){
            stDev = layoutManager->CoStdDeviation(inData,i,segmentWidth);
            currentAlpha = layoutManager->FindNearestKey(inData[i]);
            printf("curAlpha, prevAlpha, pt-stDev: %c  %c  %9.3f  trig\n",currentAlpha,prevAlpha,stDev);
            i++;
          }
          //exit state either by hard/fast exit, or soft-exit to an adjacent key
          eventEnd = i;
          i--;

          //capture event data and push it, then continue monitoring for new ones. Event is pushed only if unique from previous one..
          PointMu outPoint;
          outPoint.ticks = eventEnd - eventStart + trigger; //ticks can be used as a confidence measure of the event
          CalculateMean(eventStart,eventEnd,inData,outPoint);
          outPoint.alpha = layoutManager->FindNearestKey(outPoint.pt);
          cout << "hit mean for " << outPoint.alpha << " ticks: " << outPoint.ticks << endl;
          trigger = 0;
          //NOTE A new cluster is appended only if it is a unique letter; this prevents repeated chars.
          if(midData.empty()){  //this is just an exception check, so we don't deref a -1 index in the next if-stmt, when the vec is empty
            midData.push_back(outPoint);
          }
          //verify incoming alpha cluster is unique from previous alpha; accumulate ticks if not
          else if(outPoint.alpha == midData[midData.size()-1].alpha){
            midData[midData.size()-1].ticks += outPoint.ticks;
          }
          else{
            midData.push_back(outPoint);
          }
        }
      }
      else{
        trigger = 0;
      }
    }
  }

  cout << "clusters before merging..." << endl;
  PrintOutData(midData);
  MergeClusters(midData,outData);
  //dbg
  //PrintOutData(outData);
}
Example #5
0
/*

  More advanced event detection, using any attributes that are meaningful (dTheta, coVar(X,Y), etc.).
  -dTheta(eventBegin,eventEnd)
  -coVar(X,Y) (for some last k-inputs: this is like assessing when a set of point converges to a likely mean
  -nKeyHits: num discrete key hits in a single key region; this may be no different than coVar()
  -dist(pt[i],pt[i+]) Distance between points some k-ticks apart

  This starts with analysis, to figure out what parameters look meaningful, by the data
*/
void SingularityBuilder::Process2(vector<Point>& inData, vector<PointMu>& outData)
{
  bool trig = false;
  //char c;
  vector<PointMu> midData;
  int i, sampleRate, segmentWidth, trigger, eventStart, eventEnd, stDevTrigger;
  double dx, dist, lastDist, coVar, stDev, nKeyHits, avgDist, avgTheta, lastTheta, dTheta; 

  //segment width is the sample radius for assessing a trigger
  sampleRate = 1;  //sample every two ticks. Thus, there will be n/2 analyses
  segmentWidth = 3; //every two ticks, grab next four point for analysis
  lastTheta = dTheta = avgTheta = 0.0;

  double stDevThreshold = 30;

  cout << "processing " << inData.size() << " data points in sb.process(), dxThreshold=" << dxThreshold << endl;

  //TODO: sleep if no data
  trigger = 0;
  for(i = 0; i < (inData.size() - segmentWidth - 1); i += sampleRate){
    //ignore points outside of the active region, including the <start/stop> region
    if(InBounds(inData[i]) && InBounds(inData[i+segmentWidth-1])){
      //measures absolute change in distance, a dumb attribute
      lastDist = dist;
      dist = layoutManager->DoubleDistance(inData[i],inData[i+segmentWidth-1]);
      dx = dist - lastDist;
      avgDist = layoutManager->AvgDistance(inData,i,segmentWidth);
      //measures clustering of a group of points, but only the points themselves
      //coVar = layoutManager->CoVariance(inData,i,segmentWidth);
      stDev = layoutManager->CoStdDeviation(inData,i,segmentWidth); //(sigmaX*sigmaY)^2

      //only update theta when on the move (bounds should be the same as event capture)
      if(stDev > 100){ //stop capturing a little ahead of event capture. capture only at med/hi velocity
		    lastTheta = avgTheta;
		    avgTheta = layoutManager->AvgTheta(inData,i,segmentWidth);  //get the avg direction for a sequence of points
		    dTheta = (avgTheta - lastTheta) / 2.0;
      }
      else{
        //avgTheta = 0.0;
        dTheta = 0.0;
      }
      //dTheta = layoutManager->CosineSimilarity(inData,i,segmentWidth); // record change in angle or two sequences of points
      //correlates points with nearest key. Something like this is important to map kays to points, instead of points to keys... get creative.
      //cout << "(x,y) (" << inData[i].X << "," << inData[i].Y << ")" << endl;
      //cout << "stDev, dx, 1/dx, coVar, 1/coVar:  " << (int)stDev << "  " << (int)dx << "  " << (dx == 0 ? 0 : (1/dx)) << "  " << (int)coVar << "  " << (coVar == 0 ? 0 : (1/coVar)) << endl;
      //cout << "pt. stDev, avgDist, dx, avgTheta:  " << (int)stDev << "  " << avgDist << " " << (int)dx << " " << avgTheta << endl;
      printf("pt. stDev, avgDist, dist, dx, avgTheta, dTheta: %9.3f  %9.3f  %9.3f  %9.3f  %9.3f  %9.3f\n",stDev,avgDist,dist,dx,avgTheta,dTheta);
      //cout << "stDev:  " << (int)stDev << endl;

      if(stDev < stDevThreshold){
        stDevTrigger++;
        if(stDevTrigger > 2){
          eventStart = i;
          //event triggered, so gather event data
          i++;
          //stDev = layoutManager->CoStdDeviation(inData,i,segmentWidth);
          while(i < inData.size() && stDev < stDevThreshold){
            stDev = layoutManager->CoStdDeviation(inData,i,segmentWidth);
            printf("pt. stDev, avgDist, dist, dx, avgTheta, dTheta: %9.3f\n",stDev);
            i++;
          }
          eventEnd = i;
          i--;

          PointMu outPoint;
          outPoint.ticks = eventEnd - eventStart;
          CalculateMean(eventStart,eventEnd,inData,outPoint);
          outPoint.alpha = layoutManager->FindNearestKey(outPoint.pt);
          cout << "hit mean for " << outPoint.alpha << endl;

          //NOTE A new cluster is appended only if it is a unique letter; this prevents repeated chars.
          if(midData.empty()){  //this is just an exception check, so we don't deref a -1 index in the next if-stmt, when the vec is empty
            midData.push_back(outPoint);
          }
          //verify incoming alpha cluster is unique from previous alpha
          else if(outPoint.alpha != midData[midData.size()-1].alpha){
            midData.push_back(outPoint);
          }
          stDevTrigger = 0;
        }
      }


/*
      if(!trig && dx < dxThreshold){
        cout << "Trigger!" << endl;
        trig = true;
      }
      else{
        trig = false;
      }
*/

      /*
      //debug output, to view how data vals change
      cout << "dx: " << dx;
      if(dx > 0){
        cout << "  1/dx: " << (1.0f / (float)dx);

      }
      cout << endl;
      */
      /*
      //TODO: advancing the index i below is done without InBounds() checks
      if(dx < dxThreshold){  //determine velocity: distance of points three ticks apart
        trigger++;           //receive n-triggers before fully triggering, to buffer noise; like using a timer, but event-based
        if(trigger >= triggerThreshold){  //trigger event and start collecting event data

          //capture the event
          eventStart = i;
          while(i < (inData.size() - 4) && dx < innerDxThreshold){  //event state. remain in this state until dX (inter-reading) exceeds some threshold
            dx = layoutManager->IntDistance(inData[i],inData[i+3]);
            i++;
          }
          eventEnd = i;   // exited Event state, so store right bound of the event cluster
          //TODO: below is a small optimization to skip some data points following an event, eg, perhaps by dx difference of 3 data points.
          //i += 2;

          //get the mean point w/in the event cluster and store it
          PointMu outPoint;
          outPoint.ticks = eventEnd - eventStart;
          CalculateMean(eventStart,eventEnd,inData,outPoint);
          cout << "hit mean" << endl;
          outPoint.alpha = layoutManager->FindNearestKey(outPoint.pt);

          //NOTE A new cluster is appended only if it is a unique letter; this prevents repeated chars.
          if(midData.empty()){  //this is just an exception check, so we don't deref a -1 index in the next if-stmt, when the vec is empty
            midData.push_back(outPoint);
          }
          //verify incoming alpha cluster is unique from previous alpha
          else if(outPoint.alpha != midData[midData.size()-1].alpha){
            midData.push_back(outPoint);
          }

          //reset trigger for next event detection
          trigger = 0;
        } //exit the event-capture state, and continue streaming (reading inData and detecting the next event)
      }
      */
    }
  }

  cout << "clusters before merging..." << endl;
  PrintOutData(midData);
  MergeClusters(midData,outData);
  //dbg
  //PrintOutData(outData);
}
Example #6
0
/*
  It will take a lot of test data to figure out what event parameters are even useful, such that we can
  optimize the precision of this function and build a really good state machine for the event triggers.

  For instance, for some test input path zigzag (as a list of xy coordinates in some file), leverage everything:
  build another file of theta, dtheta, velocity, angular acceleration, etc, per that path. Analyze the xy coordinates
  for every possible attribute you might think of, and print these to some other file. Then analyze which of those
  attributes is merely noise, and which corresponds to data that might be useful to event detection.

  You might think of every point in time (each mouse reading, each tick) as a vector, and the current system
  state as a set of k-vectors. Each vector contains a bunch of attributes. A cluster is identified when the
  system (the matrix) suddenly changes in some meaningful way. The matrix analogy is intentional, since it comes from
  control theory, so existing solution undoubtedly exist for this simple problem of geometric key-point detection.

  And use python for these experiments, to avoid the labor overhead of c++.

  Otherwise the highlevel behavior/state machine of this function is simple:
     -detect event
     -capture event
     -process event (clustering)
     -pass event (key-cluster)
     -repeat

  TODO: recode this using int32, not short. Cast to short where needed.
*/
void SingularityBuilder::Process(vector<Point>& inData, vector<PointMu>& outData)
{
  //char c;
  vector<PointMu> midData;
  int i, trigger, dx, eventStart, eventEnd;

  cout << "processing " << inData.size() << " data points in sb.process()" << endl;

  //TODO: sleep if no data
  trigger = 0;
  for(i = 0; i < inData.size() - 4; i++){
    //ignore points outside of the active region, including the <start/stop> region
    if(InBounds(inData[i]) && InBounds(inData[i+3])){
      dx = layoutManager->IntDistance(inData[i],inData[i+3]);

      /*
      //debug output, to view how data vals change
      cout << "dx: " << dx;
      if(dx > 0){
        cout << "  1/dx: " << (1.0f / (float)dx);
      }
      cout << endl;
      */

      //TODO: advancing the index i below is done without InBounds() checks
      if(dx < dxThreshold){  //determine velocity: distance of points three ticks apart
        trigger++;           //receive n-triggers before fully triggering, to buffer noise; like using a timer, but event-based
        if(trigger >= triggerThreshold){  //trigger event and start collecting event data

          //capture the event
          eventStart = i;
          while(i < (inData.size() - 4) && dx < innerDxThreshold){  //event state. remain in this state until dX (inter-reading) exceeds some threshold
            dx = layoutManager->IntDistance(inData[i],inData[i+3]);
            i++;
          }
          eventEnd = i;   // exited Event state, so store right bound of the event cluster
          //TODO: below is a small optimization to skip some data points following an event, eg, perhaps by dx difference of 3 data points.
          //i += 2;

          //get the mean point w/in the event cluster and store it
          PointMu outPoint;
          //outPoint.ticks = eventEnd - eventStart;
          CalculateMean(eventStart,eventEnd,inData,outPoint);
          cout << "hit mean" << endl;
          outPoint.alpha = layoutManager->FindNearestKey(outPoint.pt);

          //NOTE A new cluster is appended only if it is a unique letter; this prevents repeated chars.
          if(midData.empty()){  //this is just an exception check, so we don't deref a -1 index in the next if-stmt, when the vec is empty
            midData.push_back(outPoint);
          }
          //verify incoming alpha cluster is unique from previous alpha
          else if(outPoint.alpha != midData[midData.size()-1].alpha){
            midData.push_back(outPoint);
          }

          //reset trigger for next event detection
          trigger = 0;
        } //exit the event-capture state, and continue streaming (reading inData and detecting the next event)
      }
    }
  }

  cout << "clusters before merging..." << endl;
  PrintOutData(midData);
  MergeClusters(midData,outData);
  //dbg
  //PrintOutData(outData);
}
// bool TePDIIsosegClas::Implementation(const TePDIParameters& params)
bool TePDIIsosegClas::RunImplementation()
{
  // Setting the parameters
  TePDITypes::TePDIRasterVectorType input_rasters;
  params_.GetParameter("input_rasters", input_rasters);

  vector<int> bands;
  params_.GetParameter("bands", bands);

  W = input_rasters[0]->params().ncols_;
  H = input_rasters[0]->params().nlines_;

  TePDITypes::TePDIPolygonSetPtrType input_polygonset;
  params_.GetParameter("input_polygonset", input_polygonset);

  TePDITypes::TePDIRasterPtrType output_raster;
  params_.GetParameter("output_raster", output_raster);

  double  acceptance_limiar;
  params_.GetParameter("acceptance_limiar", acceptance_limiar);

  /* Setting the output raster */
  TeRasterParams output_raster_params = output_raster->params();

  output_raster_params.setDataType( TeDOUBLE, -1 );
  output_raster_params.nBands( 1 );
  if( input_rasters[0]->projection() != 0 ) {
    TeSharedPtr< TeProjection > proj( TeProjectionFactory::make(
      input_rasters[0]->projection()->params() ) );
    output_raster_params.projection( proj.nakedPointer() );
  }
  output_raster_params.boxResolution( input_rasters[0]->params().box().x1(),
    input_rasters[0]->params().box().y1(), input_rasters[0]->params().box().x2(),
    input_rasters[0]->params().box().y2(), input_rasters[0]->params().resx_,
    input_rasters[0]->params().resy_ );
  // output_raster_params.setPhotometric( TeRasterParams::TeRGB, -1 );

  TEAGN_TRUE_OR_RETURN( output_raster->init( output_raster_params ),
    "Output raster reset error" );

  for (unsigned pols = 0; pols < input_polygonset->size(); pols++)
  {
    TePolygon polygon(input_polygonset->operator[](pols));

    // this iterator "walks" in the image, on the region defined by a specific polygon
    TeRaster::iteratorPoly it = input_rasters[0]->begin(polygon, TeBoxPixelIn, 0);
    TeRaster::iteratorPoly it_end = input_rasters[0]->end(polygon, TeBoxPixelIn, 0);

    long area = (long)TeGeometryArea(polygon);
    // pixel vector for each band
    vector<vector<double> > pixels_per_band(bands.size());
    vector<double> sums(bands.size());
    vector<double> tmp(1);
    for (unsigned band = 0; band < bands.size(); band++)
      pixels_per_band.push_back(tmp);

    long npix = 0;
    double tmp_pixel;
    while(it != it_end)
    {
      int col = it.currentColumn(),
          lin = it.currentLine();

      if ((col >= 0 && col < W) && (lin >=0 && lin < H))
      {
        for (unsigned band = 0; band < bands.size(); band++)
        {
          input_rasters[band]->getElement(col, lin, tmp_pixel, band);
          pixels_per_band[band].push_back(tmp_pixel);
          sums[band] += tmp_pixel;
        }
        npix++;
      }

      ++it;
    }

    vector<double> tmp_mean;
    tmp_mean.reserve(bands.size());
    for (unsigned band = 0; band < bands.size(); band++)
    {
      tmp_mean.push_back(sums[band]/npix);
    }

    // sets the covarariance matrix
    TeMatrix tmp_covar;
    int nbands = bands.size();
    TEAGN_TRUE_OR_RETURN(tmp_covar.Init(nbands, nbands, 0.0), "Unable to Init tmp_covar");
    double sum;
    for(int i = 0; i < nbands; i++)
      for(int j = 0; j < nbands; j++)
      {
        sum = 0.0;
        for (int p = 0; p < npix; p++)
          sum += (pixels_per_band[i][p] - tmp_mean[i]) * (pixels_per_band[j][p] - tmp_mean[j]);
        if (npix == 1)
          tmp_covar(i,j) = 0.0;
        else
          tmp_covar(i,j) = (double)(sum / (npix - 1));
      }

    TePDIRegion tmp_region(pols);
    TEAGN_TRUE_OR_RETURN(tmp_region.Init(bands.size(), npix, tmp_mean, tmp_covar), "Unable to Init tmp_region");
    regions.insert(pair<double, TePDIRegion>(area, tmp_region));
  }
  total_regions = regions.size();

  TEAGN_TRUE_OR_RETURN(SetThreshold(acceptance_limiar, bands.size()), "Unable to SetThreshold");
  TEAGN_TRUE_OR_RETURN(GenerateClusters(), "Unable to GenerateClusters");
  TEAGN_TRUE_OR_RETURN(MergeClusters(), "Unable to MergeClusters");

// remap cluster values to 1 -> N
  std::set<unsigned int> ulabels;
  std::set<unsigned int>::iterator lit;
  std::map<unsigned int, unsigned int> colormap;

  for (int pols = 0; pols < total_regions; pols++)
  {
    TePolygon polygon(input_polygonset->operator[](pols));

    // searches for the region with Id = pols
    multimap<double, TePDIRegion, greater<double> >::iterator regions_it;

    for (regions_it = regions.begin(); regions_it != regions.end(); ++regions_it)
      if (regions_it->second.GetId() == pols)
        break;

    ulabels.insert(regions_it->second.GetClass());
  }

  unsigned int color = 1;
  for (lit = ulabels.begin(); lit != ulabels.end(); ++lit)
    colormap[*lit] = color++;

// paint output_raster with the correspondent classes
  for (int pols = 0; pols < total_regions; pols++)
  {
    TePolygon polygon(input_polygonset->operator[](pols));

    // this iterator "walks" in the image, on the region defined by a specific polygon
    TeRaster::iteratorPoly it = input_rasters[0]->begin(polygon, TeBoxPixelIn, 0);
    TeRaster::iteratorPoly it_end = input_rasters[0]->end(polygon, TeBoxPixelIn, 0);

    // searches for the region with Id = pols
    multimap<double, TePDIRegion, greater<double> >::iterator  regions_it,
                        regions_tmp = regions.begin();
    for (regions_it = regions.begin(); regions_it != regions.end(); ++regions_it)
      if (regions_it->second.GetId() == pols)
      {
        regions_tmp = regions_it;
        break;
      }

    unsigned bit_class = colormap[regions_it->second.GetClass()];

/*
    // here, a set of colors for up to 81 classes, C(3, 4) = tree bands, four levels
    vector<int> levels;
    levels.push_back(0);
    levels.push_back(50);
    levels.push_back(100);
    levels.push_back(150);
    levels.push_back(200);
    levels.push_back(255);
	int change = levels.size();
    vector<int> colors_R, colors_G, colors_B;
    for (int c = 0, i = 0, j = 0, k = 0; c < 81; c++)
    {
      colors_R.push_back(levels[i]);
      colors_G.push_back(levels[j]);
      colors_B.push_back(levels[k]);

      i++;
      if (i >= change)
      {
        i = 0;
        j++;
      }
      if (j >= change)
      {
        j = 0;
        k++;
      }
      if (k >= change)
        k = 0;
    }

	if (bit_class >= colors_R.size())
		bit_class = 0;

    double  R = colors_R[bit_class],
        G = colors_G[bit_class],
        B = colors_B[bit_class];
*/
    // paint output_raster with specific color class
    while(it != it_end)
    {
      int  i = it.currentColumn(),
           j = it.currentLine();

      output_raster->setElement(i, j, bit_class);
      ++it;
    }
  }

  return true;
}
Example #8
0
FLODCluster FLODCluster::operator+=(const FLODCluster& Other)
{
	MergeClusters(Other);
	return *this;
}