TePDIBaatz.cpp

Go to the documentation of this file.
00001 #define MAX_FLT 3.4e38 /* maximum float value */
00002 
00003 // Internal includes
00004 #include <cstdlib>
00005 #include <iostream>
00006 #include <iomanip>
00007 #include <fstream>
00008 #include <time.h>
00009 #include <math.h>
00010 
00011 // TerraLib includes
00012 #include "TePDIBaatz.hpp"
00013 #include "TePDIRaster2Vector.hpp"
00014 #include "TePDIUtils.hpp"
00015 
00016 using namespace std;
00017 
00018 /**********************************************************************************/
00019 /* TerraLib main implementation for Baatz Segmentation                            */
00020 /**********************************************************************************/
00021 
00022 TePDIBaatz::TePDIBaatz()
00023 {
00024 }
00025 
00026 bool TePDIBaatz::CheckParameters( const TePDIParameters& parameters ) const
00027 {
00028         // checking input_image
00029     TePDITypes::TePDIRasterPtrType input_image;
00030         TEAGN_TRUE_OR_RETURN(parameters.GetParameter( "input_image", input_image ),
00031                 "Missing parameter: input_image");
00032         TEAGN_TRUE_OR_RETURN(input_image.isActive(),
00033                 "Invalid parameter: input_image inactive");
00034         TEAGN_TRUE_OR_RETURN(input_image->params().status_ != TeRasterParams::TeNotReady ,
00035                 "Invalid parameter: input_image not ready");
00036         vector<float> input_weights;
00037   TEAGN_TRUE_OR_RETURN(parameters.GetParameter( "input_weights", input_weights ),
00038     "Missing parameter: input_weights");
00039   TEAGN_TRUE_OR_RETURN(input_weights.size() <= (unsigned) input_image->params().nBands() && input_weights.size() > 0,
00040     "Input weights different from number of bands");
00041   vector<unsigned> input_channels;
00042   TEAGN_TRUE_OR_RETURN(parameters.GetParameter( "input_channels", input_channels ),
00043     "Missing parameter: input_channels");
00044   TEAGN_TRUE_OR_RETURN(input_channels.size() == input_weights.size(),
00045     "Input bands with different size from input weights");
00046    
00047         // checking output_image
00048     TePDITypes::TePDIRasterPtrType output_image;
00049         TEAGN_TRUE_OR_RETURN(parameters.GetParameter( "output_image", output_image ),
00050                 "Missing parameter: output_image");
00051 
00052         // checking thresholds
00053         float scale;
00054         TEAGN_TRUE_OR_RETURN(parameters.GetParameter( "scale", scale ),
00055                 "Missing parameter: scale");
00056         TEAGN_TRUE_OR_RETURN(scale > 0,
00057                 "Parameter scale is > 0");
00058         float compactness;
00059         TEAGN_TRUE_OR_RETURN(parameters.GetParameter( "compactness", compactness ),
00060                 "Missing parameter: compactness");
00061         TEAGN_TRUE_OR_RETURN(compactness > 0 && compactness <= 1,
00062                 "Parameter compactness is > 0 and <= 1");
00063         float color;
00064         TEAGN_TRUE_OR_RETURN(parameters.GetParameter( "color", color ),
00065                 "Missing parameter: color");
00066         TEAGN_TRUE_OR_RETURN(color > 0 && color <= 1,
00067                 "Parameter color is > 0 and <= 1");
00068     
00069    // checking output polygon sets parameter
00070   if( parameters.CheckParameter< TePDITypes::TePDIPolSetMapPtrType >( 
00071     "output_polsets" ) ) {
00072     TePDITypes::TePDIPolSetMapPtrType output_polsets;
00073     parameters.GetParameter( "output_polsets", output_polsets );
00074     TEAGN_TRUE_OR_RETURN( output_polsets.isActive(),
00075       "Invalid parameter output_polsets : Inactive polygon set pointer" );   
00076   }   
00077 
00078         return true;
00079 }
00080 
00081 void TePDIBaatz::ResetState( const TePDIParameters& )
00082 {
00083 }
00084      
00085 bool TePDIBaatz::RunImplementation()
00086 {
00087   TePDITypes::TePDIRasterPtrType input_image;
00088         params_.GetParameter( "input_image", input_image );
00089 
00090   vector<float> input_weights;
00091   params_.GetParameter( "input_weights", input_weights );
00092 
00093   vector<unsigned> input_channels;
00094   params_.GetParameter( "input_channels", input_channels );
00095   
00096         /* retrieve input_image parameters */
00097         int H = input_image->params().nlines_,
00098                 W = input_image->params().ncols_,
00099                 B = input_channels.size();
00100 
00101         /* retrieve algorithm parameters */
00102         float scale;
00103         params_.GetParameter( "scale", scale );
00104         float compactness;
00105         params_.GetParameter( "compactness", compactness );
00106         float color;
00107         params_.GetParameter( "color", color );
00108 
00109   struct segment **segments_ptr_vector = NULL;
00110   struct segment *initial_segment = NULL;
00111   struct segment *final_segment = NULL;
00112   struct segmentation_parameters seg_parameters;
00113 
00114         seg_parameters.sp = scale;
00115         seg_parameters.wcmpt = compactness;
00116         seg_parameters.wcolor = color;
00117         seg_parameters.bands = B;
00118         for (int i = 0; i < B; i++)
00119                 seg_parameters.wband[i] = input_weights[i];
00120 
00121         /* run segmentation */
00122 /*
00123         initialize_segments(&segments_ptr_vector, 
00124                 &initial_segment, &final_segment, input_image, H, W, progress_enabled_);
00125         segmentation(segments_ptr_vector, 
00126                 initial_segment, final_segment, H, W, seg_parameters, progress_enabled_);
00127 */
00128 /*
00129         float **float_input_image = (float **) malloc( B * sizeof(float) );
00130         for (int i = 0; i < B; i++)
00131                 float_input_image[i] = (float *) malloc( H * W * sizeof(float) );
00132 
00133         int p = 0;
00134         cout << "H: " << H << " W: " << W << " B: " << B << endl;
00135         for (int i = 0; i < H; i++)
00136                 for (int j = 0; j < W; j++)
00137                 {
00138                         for (int k = 0; k < B; k++)
00139                         {
00140                                 double pixel;
00141                                 input_image->getElement(j, i, pixel, k);
00142                                 float_input_image[k][p] = (float) pixel;
00143                         }
00144                         p++;
00145                 }
00146 */
00147         initialize_segments(&segments_ptr_vector, 
00148                 &initial_segment, &final_segment, input_image, input_channels, H, W, progress_enabled_);
00149 
00150   segmentation(segments_ptr_vector, 
00151                 initial_segment, final_segment, H, W, seg_parameters, progress_enabled_);
00152 
00153   /* write results */
00154   
00155         TePDITypes::TePDIRasterPtrType output_image;
00156         params_.GetParameter( "output_image", output_image );
00157         TeRasterParams output_image_params = output_image->params();
00158         output_image_params.nBands( 1 );
00159         output_image_params.setDataType( TeUNSIGNEDLONG );
00160   output_image_params.boundingBoxLinesColumns( 
00161     input_image->params().boundingBox().x1(),
00162     input_image->params().boundingBox().y1(),
00163     input_image->params().boundingBox().x2(),
00164     input_image->params().boundingBox().y2(),
00165     input_image->params().nlines_,
00166     input_image->params().ncols_ );
00167   output_image_params.projection( input_image->params().projection() );
00168         TEAGN_TRUE_OR_RETURN( output_image->init(output_image_params),
00169     "Error initiating output image" );
00170      
00171         write_segments(output_image, initial_segment, 0, progress_enabled_); 
00172   free_segment_list(&initial_segment, &segments_ptr_vector); 
00173 /*
00174         p = 0;
00175         for (int i = 0; i < H; i++)
00176                 for (int j = 0; j < W; j++)
00177                 {
00178                         double pixel = (double) float_input_image[0][p++];
00179                         output_image->setElement(j, i, pixel);
00180                 }
00181 */
00182 
00183         /* generate output polygonset */
00184   if( params_.CheckParameter< TePDITypes::TePDIPolSetMapPtrType >( 
00185     "output_polsets" ) ) {
00186     TePDITypes::TePDIPolSetMapPtrType output_polsets;
00187     params_.GetParameter( "output_polsets", output_polsets );
00188 
00189     TePDIParameters params_output;
00190     params_output.SetParameter( "rotulated_image", output_image );
00191     params_output.SetParameter( "channel", (unsigned int) 0 );
00192     params_output.SetParameter( "output_polsets", output_polsets );
00193 
00194     TePDIRaster2Vector raster2Vector;  
00195 
00196     TEAGN_TRUE_OR_THROW( raster2Vector.Reset(params_output),
00197       "Invalid Parameters for raster2Vector" );
00198 
00199     TEAGN_TRUE_OR_THROW( raster2Vector.Apply(), 
00200       "Apply error" );
00201   }   
00202 
00203   return true;
00204 }
00205 
00206 /**********************************************************************************/
00207 /* Internal main implementation for Baatz Segmentation                            */
00208 /**********************************************************************************/
00209 
00210 /* remove segment from list and conects segment list neighbours */
00211 void remove_segment(struct segment *aux_segment, 
00212           struct segment **first_segment, 
00213           struct segment **last_segment);
00214 
00215 /* merge neighbor with current_segment and removes neighbor segment */
00216 int merge_segment(struct segment_neighbor *curr_neighbor, 
00217           struct segment *curr_segment, 
00218           struct segment **first_segment, 
00219           struct segment **last_segment,
00220           struct segment **segments_ptr_vector, 
00221           long int nrows, 
00222           long int ncols); 
00223 
00224 /* identifies borderline pixels and change segment_matrix */
00225 void reset_pixels(struct segment_neighbor *curr_neighbor, 
00226           struct segment *curr_segment, 
00227           struct segment **segments_ptr_vector, 
00228           long int nrows, 
00229           long int ncols);
00230  
00231 /* creates list of segment's image neighbours */
00232 struct segment_neighbor* find_neighbors(struct segment *curr_segment, 
00233                     struct segment **segments_ptr_vector, 
00234                     long int nrows, 
00235                     long int ncols); 
00236 
00237 /* finds the 4 neighbors of a pixel */
00238 void find_neighbor_pixels(unsigned long int pixel_id, 
00239               long int nrows, 
00240               long int ncols, 
00241               long int *n0, 
00242               long int *n1, 
00243               long int *n2, 
00244               long int *n3);
00245  
00246 /* frees list of segment's neighbors from memory */
00247 void free_neighbor_list(struct segment_neighbor **first_neighbor); 
00248 
00249 /* calcs mean and stddev of merging of curr_segment and curr_neighbor */
00250 float calc_color_stats (struct segment_neighbor *curr_neighbor, 
00251             struct segment *curr_segment, 
00252             // float **input_image, 
00253             struct segmentation_parameters parameters);
00254  
00255 /* calcs spatial heterogeneity of merging of curr_segment and curr_neighbor */
00256 float calc_spatial_stats(struct segment_neighbor *curr_neighbor, 
00257              struct segment *curr_segment, 
00258              struct segment *segments_ptr_vector, 
00259              long int nrows, 
00260              long int ncols, 
00261              struct segmentation_parameters parameters);
00262  
00263 /* calcs perimeter of merging of curr_segment and curr_neighbor */
00264 void calc_perimeter(struct segment_neighbor *curr_neighbor, 
00265           struct segment *curr_segment, 
00266           struct segment **segments_ptr_vector, 
00267           long int nrows, 
00268           long int ncols); 
00269 
00270 /* calcs perimeter of merging of curr_segment and curr_neighbor, second version */
00271 void calc_perimeter_optimized(struct segment_neighbor *curr_neighbor, 
00272           struct segment *curr_segment, 
00273           struct segment **segments_ptr_vector, 
00274           long int nrows, 
00275           long int ncols); 
00276 
00277 /* calcs bounding box of merging of curr_segment and curr_neighbor */
00278 void calc_bounding_box(struct segment_neighbor *curr_neighbor, 
00279              struct segment *curr_segment); 
00280 
00281 /* mark all segments as unused */
00282 void reset_unused_segments_list(unsigned long int num_segments, 
00283                  struct segment *first_segment); 
00284 
00285 /* search unused segment using a dither matrix */
00286 struct segment* find_unused_by_dither(struct segment **segments_ptr_vector, 
00287                     int num_bits, 
00288                     long int nrows, 
00289                     long int ncols,
00290                     unsigned long int *cell_count);
00291 
00292 /* finds col and row from a pixel id */
00293 void convert_pixel_id(unsigned long int pixel_id, 
00294             long int ncols, 
00295             long int *row, 
00296             long int *col); 
00297 
00298 /**********************************************************************************/
00299 /* ranval: random number generator                                                */
00300 /**********************************************************************************/
00301 
00302 float ranval(float low, 
00303        float high)
00304 {
00305   float val;
00306 
00307   val = (((float) rand())/RAND_MAX) * (high - low) + low;
00308 
00309   return(val);
00310 }
00311 
00312 /**********************************************************************************/
00313 /* function dither_matrix_bits: calculate number of bits necessary to hold a      */
00314 /*                              coordinate subscript of dither (square) matrix    */
00315 /**********************************************************************************/
00316 unsigned long int dither_matrix_dimension(long int nrows,
00317                       long int ncols,
00318                       int *dither_bits)
00319 {
00320   int num_bits;
00321   unsigned long int max_dimension;
00322   unsigned long int dither_dimension;
00323   
00324   if (nrows>ncols)
00325     max_dimension=nrows*nrows;
00326   else
00327     max_dimension=ncols*ncols;
00328 
00329   num_bits=0;
00330   dither_dimension=1;
00331 
00332   while (dither_dimension < max_dimension)
00333   {
00334     dither_dimension = dither_dimension*2;
00335     num_bits++;
00336   }
00337 
00338   if (num_bits%2)
00339   {
00340     num_bits++;
00341     dither_dimension = dither_dimension*2;
00342   }
00343 
00344   *dither_bits = num_bits;
00345 
00346   return(dither_dimension);
00347 }
00348 
00349 /**********************************************************************************/
00350 /* function dither_matrix_conversion: converts an pixel index into a dither       */
00351 /*                                    matrix index                                */
00352 /**********************************************************************************/
00353 unsigned long int dither_matrix_conversion(int num_bits, 
00354                        long int nrows, 
00355                        long int ncols,
00356                        unsigned long int *cell_count)
00357 {
00358   long int row, col, irow, icol;
00359   unsigned long int pixel_id;
00360   unsigned long int aux_cell_count;
00361   int i, j, k;
00362   bool found;
00363 
00364   aux_cell_count = *cell_count;
00365   found = false;
00366 
00367   while (!found) 
00368   {
00369     irow = icol = 0;
00370     j = k = 1;
00371     for (i=0;i<num_bits;i++)
00372     {
00373       if (i % 2)
00374       {
00375         icol = icol+(aux_cell_count&j)/k;
00376       }
00377       else
00378       {
00379         irow = irow+(aux_cell_count&j)/k;
00380         k = k * 2;
00381       }
00382       j = j * 2;
00383     }
00384 
00385     row = col = 0;
00386     j = 1;
00387     for (i=0;i<(num_bits/2);i++)
00388     {
00389       k = k / 2;
00390       if (irow & j) row = row+k;
00391       if (icol & j) col = col+k;
00392       j = j * 2;
00393     }
00394     
00395     if ((col >= ncols)||(row >= nrows))
00396     {
00397       found = false;
00398       aux_cell_count++;
00399     }
00400     else
00401     {
00402       pixel_id = (ncols*row)+col;
00403       found = true;
00404     }
00405   }
00406 
00407   *cell_count = aux_cell_count;
00408   return(pixel_id);
00409 }
00410 
00411 /**********************************************************************************/
00412 /* function create_initial_segments: creates initial segment list                 */
00413 /**********************************************************************************/
00414 
00415 int initialize_segments(struct segment ***segments_ptr_vector, 
00416             struct segment **first_segment, 
00417             struct segment **last_segment, 
00418             // float **input_image, 
00419             TePDITypes::TePDIRasterPtrType input_image,
00420             vector<unsigned> input_channels, 
00421             long int nrows, 
00422             long int ncols,
00423             bool progress_enabled_)
00424 {
00425   struct segment *aux_segment = 0;
00426   struct segment *prev_segment;
00427   struct segment_pixel *body_pixel;
00428   unsigned long int id_pixel;
00429   int row, col;
00430   int allocate_memory, error;
00431 
00432   error = 0;
00433 
00434   /* allocate memory for segments matrix if it has not been created yet */
00435   if (*segments_ptr_vector == NULL)
00436   {
00437   allocate_memory = true;
00438   *segments_ptr_vector = (struct segment **) malloc(nrows*ncols * sizeof(struct segment *));
00439   }
00440   else
00441   allocate_memory = false;
00442 
00443   if(*segments_ptr_vector == NULL) error = 1;
00444 
00445   row = 0;
00446   col = 0;
00447   id_pixel=0;
00448   prev_segment = NULL;
00449 
00450   TePDIPIManager pim("Initializing Data", nrows * ncols, progress_enabled_);
00451   while ((id_pixel<(unsigned long)(nrows*ncols)) && (error!=1))
00452   {
00453 
00454   if (allocate_memory)
00455   {
00456       aux_segment = (struct segment*) malloc(sizeof(struct segment));
00457     if(aux_segment == NULL) error = 1;
00458     
00459     body_pixel = (struct segment_pixel*) malloc(sizeof(struct segment_pixel));
00460     if(body_pixel == NULL) error = 1;
00461 
00462     aux_segment->next_original_segment = NULL;
00463     aux_segment->original_pixel = body_pixel;
00464   }
00465   else
00466   {
00467     if (id_pixel==0)
00468       aux_segment = *first_segment;
00469     else
00470       aux_segment = aux_segment->next_original_segment;
00471     
00472     body_pixel = aux_segment->original_pixel;
00473   }
00474 
00475   if (error!=1)
00476   {
00477     (*segments_ptr_vector)[id_pixel] = aux_segment;
00478 
00479     aux_segment->id = id_pixel;
00480     aux_segment->area = 1;
00481     aux_segment->perimeter = 4;
00482     aux_segment->b_box[0] = (float)row;
00483     aux_segment->b_box[1] = (float)col;
00484     aux_segment->b_box[2] = 1;
00485     aux_segment->b_box[3] = 1;
00486 
00487     for(unsigned b = 0; b < input_channels.size(); b++)
00488     {
00489       double pixel;
00490       input_image->getElement(col, row, pixel, input_channels[b]);
00491       aux_segment->avg_color[b] = (float) pixel;
00492       aux_segment->std_color[b] = 0;
00493       aux_segment->avg_color_square[b] = (float) (pixel * pixel);
00494       aux_segment->color_sum[b] = (float) pixel;
00495     }
00496 /*
00497     for(int b = 0; b < NUM_BANDS; b++)
00498     {
00499       aux_segment->avg_color[b] = input_image[b][id_pixel];
00500       aux_segment->std_color[b] = 0;
00501       aux_segment->avg_color_square[b] = (float)(input_image[b][id_pixel])*(input_image[b][id_pixel]);
00502       aux_segment->color_sum[b] = input_image[b][id_pixel];
00503     }
00504 */
00505     aux_segment->used = false;
00506 
00507     body_pixel->pixel_id = id_pixel;
00508     body_pixel->borderline = true;
00509     body_pixel->next_pixel = NULL;
00510     aux_segment->pixel_list = body_pixel;
00511     aux_segment->last_pixel = body_pixel;
00512     
00513     aux_segment->next_segment = NULL;
00514     aux_segment->previous_segment = prev_segment;
00515 
00516     if (prev_segment)
00517     {
00518       prev_segment->next_segment = aux_segment;
00519       prev_segment->next_original_segment = aux_segment;
00520 
00521       *last_segment = aux_segment;
00522     }
00523     else
00524     {
00525       *first_segment = aux_segment;
00526     }
00527 
00528     prev_segment = aux_segment;
00529     
00530     col++;
00531     if (col==ncols)
00532     {
00533       col = 0;
00534       row++;
00535     }
00536     
00537       id_pixel++;
00538     pim.Increment();
00539   }
00540   }
00541   pim.Toggle(false);
00542   if(error)
00543   {
00544     /* out of memory space */
00545     return(1);
00546   }
00547   return(0);
00548 }
00549 
00550 /**********************************************************************************/
00551 /* function find_unused_by_dither : finds segment using dither matrix             */
00552 /**********************************************************************************/
00553 
00554 struct segment* find_unused_by_dither(struct segment **segments_ptr_vector, 
00555                     int num_bits, 
00556                     long int nrows, 
00557                     long int ncols,
00558                     unsigned long int *cell_count)
00559 
00560 {
00561   struct segment *aux_segment;
00562   unsigned long int pixel_id;
00563   bool found;
00564 
00565   found = false;
00566 
00567   while (!found)
00568   {
00569   pixel_id=dither_matrix_conversion(num_bits, nrows, ncols, cell_count);
00570   aux_segment = segments_ptr_vector[pixel_id];
00571 
00572     if (aux_segment->used)
00573     *cell_count=*cell_count+1;
00574   else
00575     found = true;
00576   }
00577   
00578   return(aux_segment);
00579 }
00580 
00581 /**********************************************************************************/
00582 /* function convert_pixel_id: finds col and row from pixel id                     */
00583 /**********************************************************************************/
00584 
00585 void convert_pixel_id(unsigned long int pixel_id, 
00586             long int ncols, 
00587             long int *row, 
00588             long int *col)
00589 {
00590   *row = (long)floor((double)pixel_id / (double)ncols);
00591   *col = pixel_id % ncols;
00592 }
00593 
00594 /**********************************************************************************/
00595 /* function free_neighbor_list: frees list of segment's neighbors from memory     */
00596 /**********************************************************************************/
00597 
00598 void free_neighbor_list(struct segment_neighbor **first_neighbor)
00599 {
00600   struct segment_neighbor *aux_neighbor;
00601   
00602   while (*first_neighbor!=NULL)
00603   {
00604     aux_neighbor = (*first_neighbor)->next_neighbor;
00605     free(*first_neighbor);
00606     *first_neighbor = aux_neighbor;
00607   }
00608 }
00609 
00610 /**********************************************************************************/
00611 /* function find_neighbors: creates list of segment's image neighbors             */
00612 /**********************************************************************************/
00613 
00614 struct segment_neighbor* find_neighbors(struct segment *curr_segment, 
00615                     struct segment **segments_ptr_vector, 
00616                     long int nrows, long int ncols)
00617 {
00618   int i, not_in_neighbors_list;
00619   long int neighbor_pixel[4][2]; /* first col contain pixel id, second contains segment id */
00620   struct segment_neighbor *first_neighbor;
00621   struct segment_neighbor *aux_neighbor;
00622   struct segment_neighbor *new_neighbor;
00623   struct segment_pixel *aux_pixel;
00624   struct segment *aux_segment;
00625    
00626   aux_pixel = curr_segment->pixel_list;
00627   first_neighbor = NULL;
00628 
00629   /* for each outline pixel */
00630   while (aux_pixel!=NULL)
00631   {
00632     if (aux_pixel->borderline==true)
00633     {
00634       find_neighbor_pixels(aux_pixel->pixel_id, nrows, ncols, 
00635       neighbor_pixel[0], neighbor_pixel[1], neighbor_pixel[2], neighbor_pixel[3]);
00636       /* finds segments to which pixel belongs to */
00637       for (i=0;i<4;i++)
00638       {
00639         if (neighbor_pixel[i][0]!=-1)
00640         {
00641           aux_segment = segments_ptr_vector[neighbor_pixel[i][0]];
00642           neighbor_pixel[i][1] = aux_segment->id;
00643 
00644           if (neighbor_pixel[i][1] == (int) curr_segment->id)
00645             neighbor_pixel[i][1]=-1;
00646         }
00647         else
00648         {
00649           neighbor_pixel[i][1]=-1;
00650         }
00651         /* if pixel segment is not yet in the list of segment neighbors, includes it */
00652         if (neighbor_pixel[i][1]>-1)
00653         {
00654           not_in_neighbors_list = true;
00655           aux_neighbor = first_neighbor;
00656           while ((aux_neighbor!=NULL)&&(not_in_neighbors_list))
00657           {
00658             if (aux_neighbor->neighbor_id == (unsigned) neighbor_pixel[i][1])
00659             {
00660               not_in_neighbors_list = false;
00661             }
00662             else
00663             {
00664               aux_neighbor = aux_neighbor->next_neighbor;
00665             }
00666           }
00667           if (not_in_neighbors_list)
00668           {
00669             new_neighbor = (struct segment_neighbor*) malloc(sizeof(struct segment_neighbor));
00670             new_neighbor->neighbor_id = neighbor_pixel[i][1];
00671             new_neighbor->neighbor = segments_ptr_vector[neighbor_pixel[i][1]];
00672 
00673             if (first_neighbor==NULL)
00674             {
00675               new_neighbor->next_neighbor = NULL;
00676             }
00677             else
00678             {
00679               new_neighbor->next_neighbor = first_neighbor;
00680             }
00681             first_neighbor = new_neighbor;
00682           }
00683         }
00684       }
00685     }
00686     aux_pixel = aux_pixel->next_pixel;
00687   }
00688   return (first_neighbor);
00689 }
00690 
00691 /**********************************************************************************/
00692 /* function find_neighbor_pixels: returns the ids of the (4) neighbors of a pixel */
00693 /**********************************************************************************/
00694 
00695 void find_neighbor_pixels(unsigned long int pixel_id, 
00696               long int nrows, 
00697               long int ncols, 
00698               long int *n0, 
00699               long int *n1, 
00700               long int *n2, 
00701               long int *n3)
00702 {
00703   long int row, col;
00704 
00705   convert_pixel_id(pixel_id, ncols, &row, &col);
00706 
00707   *n0 = *n1 = *n2 = *n3 = -1;
00708   
00709   if (row>0)         *n0=((row-1)*ncols) + col;      
00710 
00711   if (col>0)         *n1=(row*ncols) + (col-1);
00712 
00713   if (row<(nrows-1)) *n2=((row+1)*ncols) + col;
00714 
00715   if (col<(ncols-1)) *n3=(row*ncols) + (col+1);
00716 }
00717 
00718 /**********************************************************************************/
00719 /* function calc_color_stats: calculate the mean color and the standard deviation */
00720 /*           of the merging of two segments and writes it to the current neighbor */
00721 /**********************************************************************************/
00722 
00723 float calc_color_stats (struct segment_neighbor *curr_neighbor, 
00724             struct segment *curr_segment, 
00725             //float **input_image, 
00726             struct segmentation_parameters parameters)
00727 {
00728   float mean[NUM_BANDS], colorSum[NUM_BANDS];
00729   float squarePixels[NUM_BANDS];
00730   float stddev[NUM_BANDS];
00731   float stddevNew[NUM_BANDS];
00732   float sum_wband, wband_norm[NUM_BANDS];
00733   float color_f[NUM_BANDS];
00734   float color_h;
00735   int b;
00736   long int count;
00737   count = 0;
00738   float a_current, a_neighbor, a_sum;
00739   struct segment *neighbor;
00740 
00741   neighbor = curr_neighbor->neighbor;
00742 
00743   a_current = curr_segment->area;
00744   a_neighbor = neighbor->area;
00745   a_sum = a_current+a_neighbor;
00746   sum_wband = 0;
00747 
00748   for (b = 0; b < parameters.bands; b++)
00749   {
00750     mean[b] = ((curr_segment->avg_color[b]*a_current)+(neighbor->avg_color[b]*a_neighbor))/a_sum;
00751   squarePixels[b] = (curr_segment->avg_color_square[b])+(neighbor->avg_color_square[b]);
00752   colorSum[b] = curr_segment->color_sum[b] + neighbor->color_sum[b];
00753     stddev[b] = 0;
00754   stddevNew[b] = 0;
00755   sum_wband = sum_wband + parameters.wband[b];
00756   }
00757 
00758   for(b = 0; b < parameters.bands; b++)
00759   {
00760     stddevNew[b] = squarePixels[b] - 2*mean[b]*colorSum[b] + a_sum*mean[b]*mean[b];
00761   }
00762 
00763   /* stores stddev and mean in neighbor */
00764   /* calculates color factor per band and total */
00765   color_h = 0;
00766   for (b = 0; b < parameters.bands; b++)
00767   {
00768     stddev[b] = sqrt(stddevNew[b]/a_sum);
00769   wband_norm[b] = parameters.wband[b]; /* new implementation, bands already weighted */
00770 
00771     color_f[b] = (a_current*curr_segment->std_color[b]) + 
00772     (a_neighbor*neighbor->std_color[b]);
00773     color_f[b] = wband_norm[b] * ((a_sum*stddev[b])-color_f[b]);
00774     color_h = color_h + color_f[b];
00775     
00776     curr_neighbor->avg_color[b] = mean[b];
00777     curr_neighbor->std_color[b] = stddev[b];
00778   curr_neighbor->avg_color_square[b] = squarePixels[b];
00779   curr_neighbor->color_sum[b] = colorSum[b];
00780   }
00781   return(color_h);
00782 }
00783 
00784 /**********************************************************************************/
00785 /* function calc_spatial_stats: calcs spatial heterogeneity of merging of         */
00786 /*                              curr_segment and curr_neighbor                    */
00787 /**********************************************************************************/
00788 
00789 float calc_spatial_stats(struct segment_neighbor *curr_neighbor, 
00790              struct segment *curr_segment, 
00791              struct segment **segments_ptr_vector, 
00792              long int nrows, 
00793              long int ncols, 
00794              struct segmentation_parameters parameters)
00795 {
00796   struct segment *neighbor;  
00797   float spatial_h, smooth_f, compact_f;
00798   float area[3], perimeter[3], b_box_len[3]; /* 0-current segment; 
00799                           1-neighbor segment; 
00800                         2-merged (new) segment */
00801 
00802   neighbor = curr_neighbor->neighbor;
00803 
00804   /* area */
00805   area[0] = curr_segment->area;
00806   area[1] = neighbor->area;
00807   area[2] = area[0]+area[1];
00808   curr_neighbor->area = area[2];
00809   
00810   /* perimeter */
00811   perimeter[0] = curr_segment->perimeter;
00812   perimeter[1] = neighbor->perimeter;
00813   if (area[2]<4) /* valid only if pixel neighborhood==4 */
00814   {
00815     if (area[2]==2)
00816     curr_neighbor->perimeter = 6;
00817   else
00818     curr_neighbor->perimeter = 8; 
00819   }
00820   else
00821   {
00822 //    calc_perimeter(curr_neighbor, curr_segment, segments_ptr_vector, nrows, ncols);
00823 //cout << "original: " << curr_neighbor->perimeter << endl;
00824     calc_perimeter_optimized(curr_neighbor, curr_segment, segments_ptr_vector, nrows, ncols);
00825 //cout << "optimized: " << curr_neighbor->perimeter << endl;
00826 
00827 //    calc_perimeter(curr_neighbor, curr_segment, segments_ptr_vector, nrows, ncols);
00828   }
00829   perimeter[2] = curr_neighbor->perimeter;
00830   
00831   /* bounding box lenght */
00832   calc_bounding_box(curr_neighbor, curr_segment);
00833   b_box_len[0] = curr_segment->b_box[2]*2 + curr_segment->b_box[3]*2;
00834   b_box_len[1] = neighbor->b_box[2]*2 + neighbor->b_box[3]*2;
00835   b_box_len[2] = curr_neighbor->b_box[2]*2 + curr_neighbor->b_box[3]*2;
00836 
00837   /* smoothness factor */
00838   smooth_f = (area[2]*perimeter[2]/b_box_len[2] - 
00839     (area[1]*perimeter[1]/b_box_len[1] + area[0]*perimeter[0]/b_box_len[0]));
00840   
00841   /* compactness factor */
00842   compact_f = (area[2]*perimeter[2]/sqrt(area[2]) - 
00843     (area[1]*perimeter[1]/sqrt(area[1]) + area[0]*perimeter[0]/sqrt(area[0])));
00844 
00845   /* spatial heterogeneity */
00846   spatial_h = parameters.wcmpt*compact_f + (1-parameters.wcmpt)*smooth_f;
00847   return(spatial_h);
00848 }
00849 
00850 /**********************************************************************************/
00851 /* function calc_perimeter: calculates the perimeter of merging of curr_segment   */
00852 /*                          and curr_neighbor                                     */
00853 /**********************************************************************************/
00854 
00855 void calc_perimeter(struct segment_neighbor *curr_neighbor, 
00856           struct segment *curr_segment, 
00857           struct segment **segments_ptr_vector, 
00858           long int nrows, 
00859           long int ncols)
00860 {
00861   int i, j, k;
00862   float perimeter_total;
00863   unsigned long int neighbor_id, segment_id;
00864   long int neighbor_pixel[4][2]; /* first col contain pixel id, second contains segment id */
00865   struct segment_pixel *aux_pixel;
00866   struct segment *aux_segment; 
00867 
00868   perimeter_total = 0;
00869 
00870   for (j=0;j<2;j++) /* once for the current segment, once for the neighbor segment */
00871   {
00872     neighbor_id = curr_neighbor->neighbor_id;
00873     segment_id = curr_segment->id;
00874     if (j==1)
00875     {
00876       aux_pixel = curr_segment->pixel_list;
00877     }
00878     else
00879     {
00880       aux_pixel = curr_neighbor->neighbor->pixel_list;
00881     }
00882     /* for each outline pixel */
00883     while (aux_pixel!=NULL)
00884     {
00885       if (aux_pixel->borderline==true)
00886       {
00887         find_neighbor_pixels(aux_pixel->pixel_id, nrows, ncols, 
00888       &neighbor_pixel[0][0], &neighbor_pixel[1][0], &neighbor_pixel[2][0], &neighbor_pixel[3][0]);
00889         /* count how many of the surrounding pixels are from the own segment or neighbor */
00890         k = 0;
00891     for (i=0; i<4; i++)
00892           if (neighbor_pixel[i][0]==-1) /* image limit */
00893       k++;
00894           else
00895           {
00896             aux_segment = segments_ptr_vector[neighbor_pixel[i][0]];
00897             neighbor_pixel[i][1] = aux_segment->id;
00898 
00899             if ((neighbor_pixel[i][1] != (int) segment_id)&&(neighbor_pixel[i][1] != (int) neighbor_id))
00900               k++;
00901           }
00902         perimeter_total=perimeter_total+k; 
00903       }
00904       aux_pixel = aux_pixel->next_pixel;
00905     }
00906   }
00907   curr_neighbor->perimeter = perimeter_total;
00908 
00909 
00910 }
00911 
00912 /**********************************************************************************/
00913 /* function calc_bounding_box: calcs bounding box of merging of curr_segment      */
00914 /*   and curr_neighbor                                                            */
00915 /**********************************************************************************/
00916 
00917 void calc_bounding_box(struct segment_neighbor *curr_neighbor, 
00918              struct segment *curr_segment)
00919 {
00920   float min_row[3], max_row[3], min_col[3], max_col[3];
00921 
00922   min_row[0] = curr_segment->b_box[0];
00923   max_row[0] = curr_segment->b_box[0]+curr_segment->b_box[2];
00924   min_col[0] = curr_segment->b_box[1];
00925   max_col[0] = curr_segment->b_box[1]+curr_segment->b_box[3];
00926   
00927   min_row[1] = curr_neighbor->neighbor->b_box[0];
00928   max_row[1] = curr_neighbor->neighbor->b_box[0]+curr_neighbor->neighbor->b_box[2];
00929   min_col[1] = curr_neighbor->neighbor->b_box[1];
00930   max_col[1] = curr_neighbor->neighbor->b_box[1]+curr_neighbor->neighbor->b_box[3];
00931 
00932   if (min_row[0]<min_row[1]) min_row[2]=min_row[0]; else min_row[2]=min_row[1];
00933   if (min_col[0]<min_col[1]) min_col[2]=min_col[0]; else min_col[2]=min_col[1];
00934   if (max_row[0]>max_row[1]) max_row[2]=max_row[0]; else max_row[2]=max_row[1];
00935   if (max_col[0]>max_col[1]) max_col[2]=max_col[0]; else max_col[2]=max_col[1];
00936 
00937   curr_neighbor->b_box[0] = min_row[2];
00938   curr_neighbor->b_box[1] = min_col[2];
00939   curr_neighbor->b_box[2] = max_row[2]-min_row[2];
00940   curr_neighbor->b_box[3] = max_col[2]-min_col[2];
00941 }
00942 
00943 /**********************************************************************************/
00944 /* function reset_pixels: sets pixels from neighbor as belonging to current      */
00945 /*                         segment and corrects its outline                       */
00946 /**********************************************************************************/
00947 
00948 void reset_pixels(struct segment_neighbor *curr_neighbor, 
00949           struct segment *curr_segment, 
00950           struct segment **segments_ptr_vector, 
00951           long int nrows, 
00952           long int ncols)
00953 {
00954   int i;
00955   unsigned long int neighbor_id, segment_id;
00956   long int neighbor_pixel[4][2]; /* first col contain pixel id, second col contains segment id */
00957   struct segment_pixel *aux_pixel;
00958   struct segment *aux_segment;
00959 
00960   neighbor_id = curr_neighbor->neighbor_id;
00961   segment_id = curr_segment->id;
00962 
00963   /* for each pixel of the neighbor segment to be merged */
00964   aux_pixel = curr_neighbor->neighbor->pixel_list;
00965   while (aux_pixel!=NULL)
00966   {
00967     /* changes the value of the pixel in the segment matrix (assign it to the current segment) */
00968     segments_ptr_vector[aux_pixel->pixel_id] = curr_segment;
00969 
00970     /* if it is outline pixel, check if that must be changed */
00971     if ((aux_pixel->borderline==true)&&(curr_segment->area>6)) /* curr_segment->area>6, 
00972                                   only valid for pixel neighborhood==4 */
00973     {
00974       find_neighbor_pixels(aux_pixel->pixel_id, nrows, ncols, 
00975       neighbor_pixel[0], neighbor_pixel[1], neighbor_pixel[2], neighbor_pixel[3]);
00976       /* if pixel is surrounded by pixels of the same segment or of the merged neighbor, 
00977        it's no longer a border pixel */
00978       i=0;
00979       while ((i<4)&&(i>-1))
00980       {
00981         if (neighbor_pixel[i][0]==-1) /* image limit */
00982         {
00983           i=-1;
00984         }
00985         else
00986         {
00987       aux_segment = segments_ptr_vector[neighbor_pixel[i][0]];
00988           neighbor_pixel[i][1] = aux_segment->id;
00989 
00990           if ((neighbor_pixel[i][1] != (int) segment_id)&&(neighbor_pixel[i][1] != (int) neighbor_id))
00991           {
00992             i=-1;
00993           }
00994           else
00995           {
00996             i++;
00997           }
00998         }
00999       }
01000       if (i!=-1) /* no longer outline pixel */
01001       {
01002         aux_pixel->borderline=false;
01003       }
01004     }
01005     aux_pixel = aux_pixel->next_pixel;
01006   }
01007   
01008   if (curr_segment->area>6) /* curr_segment->area>6, only valid for pixel neighborhood==4 */
01009   {
01010     /* for each outline pixel of the current segment */
01011     aux_pixel = curr_segment->pixel_list;
01012     while (aux_pixel!=NULL)
01013     {
01014       if (aux_pixel->borderline==true)
01015       {
01016         find_neighbor_pixels(aux_pixel->pixel_id, nrows, ncols, 
01017       neighbor_pixel[0], neighbor_pixel[1], neighbor_pixel[2], neighbor_pixel[3]);
01018         /* if pixel is surrounded by pixels of the same segment or of the merged neighbor, 
01019        it's no longer a border pixel */
01020         i=0;
01021         while ((i<4)&&(i>-1))
01022         {
01023           if (neighbor_pixel[i][0]==-1) /* image limit */
01024           {
01025             i=-1;
01026           }
01027           else
01028           {
01029             aux_segment = segments_ptr_vector[neighbor_pixel[i][0]];
01030             neighbor_pixel[i][1] = aux_segment->id;
01031 
01032             if ((neighbor_pixel[i][1] != (int) segment_id)&&(neighbor_pixel[i][1] != (int) neighbor_id))
01033             {
01034               i=-1;
01035             }
01036             else
01037             {
01038               i++;
01039             }
01040           }
01041         }
01042         if (i!=-1) /* no longer outline pixel */
01043         {
01044           aux_pixel->borderline=false;
01045         }
01046       }
01047       aux_pixel = aux_pixel->next_pixel;
01048     }
01049   }
01050 
01051   /* include pixel list of neighbor in the list of curr_segment */
01052   curr_segment->last_pixel->next_pixel = curr_neighbor->neighbor->pixel_list;
01053   curr_segment->last_pixel = curr_neighbor->neighbor->last_pixel;
01054   curr_neighbor->neighbor->pixel_list = NULL;
01055 }
01056 
01057 /**********************************************************************************/
01058 /* function remove_segment: remove segment from list                              */
01059 /**********************************************************************************/
01060 
01061 void remove_segment(struct segment *aux_segment, 
01062           struct segment **first_segment, 
01063           struct segment **last_segment)
01064 {
01065   if (aux_segment==*first_segment)
01066   {
01067     *first_segment = aux_segment->next_segment;
01068     (*first_segment)->previous_segment = NULL;
01069   }
01070   else
01071   {
01072     if (aux_segment==*last_segment)
01073     {
01074       *last_segment = aux_segment->previous_segment;
01075       (*last_segment)->next_segment = NULL;
01076     }
01077     else
01078     {
01079       aux_segment->previous_segment->next_segment = aux_segment->next_segment;
01080       aux_segment->next_segment->previous_segment = aux_segment->previous_segment;
01081     }
01082   }
01083 }
01084 
01085 
01086 /**********************************************************************************/
01087 /* function merge_segment: merge neighbor with current_segment and removes        */
01088 /*                         neighbor segment. Returns 0 if merged segment has been */
01089 /*                         used before, 1 otherwise.                              */
01090 /**********************************************************************************/
01091 
01092 int merge_segment(struct segment_neighbor *curr_neighbor, 
01093           struct segment *curr_segment, 
01094           struct segment **first_segment, 
01095           struct segment **last_segment, 
01096           struct segment **segments_ptr_vector, 
01097           long int nrows, 
01098           long int ncols)
01099 {
01100   int i, not_used;
01101   struct segment *neighbor;
01102 
01103   neighbor = curr_neighbor->neighbor;
01104 
01105   /* check if selected neighbor had already been used, if not set it as used */
01106   if (neighbor->used)
01107   {
01108     not_used = false;
01109   }
01110   else
01111   {
01112     not_used = true;
01113     neighbor->used = true;
01114   }
01115   
01116   /* copy data from curr_neighbor to curr_seg */
01117   curr_segment->area = curr_neighbor->area;
01118   curr_segment->perimeter = curr_neighbor->perimeter;
01119   for (i=0;i<4;i++)
01120   {
01121     curr_segment->b_box[i] = curr_neighbor->b_box[i];   
01122   }
01123   for (i=0;i<NUM_BANDS;i++)
01124   {
01125     curr_segment->avg_color[i] = curr_neighbor->avg_color[i];
01126     curr_segment->std_color[i] = curr_neighbor->std_color[i];
01127   curr_segment->avg_color_square[i] = curr_neighbor->avg_color_square[i];
01128   curr_segment->color_sum[i] = curr_neighbor->color_sum[i];
01129   }
01130 
01131   /* sets pixels from neighbor as belonging to current segment and corrects outline */
01132   reset_pixels(curr_neighbor, curr_segment, segments_ptr_vector, nrows, ncols);
01133   
01134   /* remove neighbor segment from list */
01135   remove_segment(neighbor, first_segment, last_segment);
01136 
01137   return(not_used);
01138 }
01139 
01140 /**********************************************************************************/
01141 /* function free_segment_list: remove all segment list and frees memory         */
01142 /**********************************************************************************/
01143 
01144 void free_segment_list(struct segment **initial_segment, 
01145              struct segment ***segments_ptr_vector)
01146 {
01147   struct segment *aux_segment;
01148   struct segment *next_segment;
01149   struct segment_pixel *aux_pixel;
01150   struct segment_pixel *next_pixel;
01151 
01152   /* frees segment list */
01153   aux_segment=*initial_segment;
01154   while (aux_segment!=NULL)
01155   {
01156     /* frees pixels lists */
01157     aux_pixel = aux_segment->pixel_list;
01158     while (aux_pixel!=NULL)
01159     {
01160       next_pixel = aux_pixel->next_pixel;
01161       free(aux_pixel);
01162       aux_pixel = next_pixel;
01163     }
01164     next_segment=aux_segment->next_original_segment;
01165     free(aux_segment);
01166     aux_segment=next_segment;
01167   }
01168   initial_segment=NULL;
01169 
01170   /* frees segment vector */
01171   if (segments_ptr_vector!=NULL)
01172   {
01173     free(*segments_ptr_vector);
01174     *segments_ptr_vector=NULL;
01175   }
01176 }
01177 
01178 /**********************************************************************************/
01179 /* function reset_unused_segments_list: mark all segments as unused                */
01180 /**********************************************************************************/
01181 
01182 void reset_unused_segments_list(unsigned long int num_segments, 
01183                  struct segment *first_segment)
01184 {
01185   unsigned long int i;
01186   struct segment *aux_segment;
01187 
01188   aux_segment = first_segment;
01189 
01190   /* mark all segments as unused */
01191   for (i=0; i<num_segments; i++)
01192   {
01193     aux_segment->used = false;
01194     aux_segment = aux_segment->next_segment;
01195   }
01196 }
01197 
01198 /**********************************************************************************/
01199 /* function write_segments: write output image                                    */
01200 /**********************************************************************************/
01201 
01202 void write_segments(// float **input_image, 
01203           TePDITypes::TePDIRasterPtrType output_image,
01204           struct segment *first_segment, 
01205           int write_type,
01206           bool progress_enabled_)
01207 {
01208   int color[NUM_BANDS];
01209   struct segment_pixel *aux_pixel;
01210   struct segment *aux_segment;
01211   long  ncols = output_image->params().ncols_,
01212       nrows = output_image->params().nlines_,
01213     col, row;
01214 
01215   /* searches for first segment with a pixel list */
01216   aux_segment = first_segment;
01217   while (aux_segment->pixel_list==NULL)
01218   {
01219     aux_segment = aux_segment->next_original_segment;
01220   }
01221 
01222   /* for each segment */
01223   TePDIPIManager pim("Writing segments", nrows * ncols, progress_enabled_);
01224   long pixel_id = 1;
01225   while (aux_segment!=NULL)
01226   {
01227     /* define segment color */
01228     switch (write_type)
01229     {
01230       case 0: /* random colors */
01231         color[0] = pixel_id++; //(int) floor(ranval(0, 256));
01232         //color[1] = (int) floor(ranval(0, 256));
01233         //color[2] = (int) floor(ranval(0, 256));
01234         break;
01235       case 3: /* encoded segment id */
01236         color[0] = (int) floor((double)aux_segment->id / 256.0);
01237         //color[1] = ((int) aux_segment->id) % 256;
01238         //color[2] = 0;
01239         break;
01240       default: /* average colors */
01241         color[0] = (int) floor(aux_segment->avg_color[0]);
01242         //color[1] = (int) floor(aux_segment->avg_color[1]);
01243         //color[2] = (int) floor(aux_segment->avg_color[2]);
01244         break;      
01245     }
01246 
01247     /* for each pixel of the segment */
01248     aux_pixel = aux_segment->pixel_list;
01249     while (aux_pixel!=NULL)
01250     {
01251    convert_pixel_id(aux_pixel->pixel_id, ncols, &row, &col);
01252    output_image->setElement(col, row, color[0]);
01253    // input_image[0][aux_pixel->pixel_id] = (unsigned char) color[0];
01254      //input_image[1][aux_pixel->pixel_id] = (unsigned char) color[1];
01255      //input_image[2][aux_pixel->pixel_id] = (unsigned char) color[2];
01256      if (aux_pixel->borderline)
01257       {
01258         if (write_type==2)
01259         {
01260       convert_pixel_id(aux_pixel->pixel_id, ncols, &row, &col);
01261       output_image->setElement(col, row, OUTLINE_COLOR_0);
01262           // input_image[0][aux_pixel->pixel_id] = (unsigned char) OUTLINE_COLOR_0;
01263           //input_image[1][aux_pixel->pixel_id] = (unsigned char) OUTLINE_COLOR_1;
01264           //input_image[2][aux_pixel->pixel_id] = (unsigned char) OUTLINE_COLOR_2;
01265         }
01266         if (write_type==3)
01267         {
01268           //input_image[2][aux_pixel->pixel_id] = (unsigned char) 255;
01269         }
01270       }
01271       aux_pixel = aux_pixel->next_pixel;
01272     }
01273     aux_segment=aux_segment->next_segment;
01274   pim.Increment();
01275   }
01276   pim.Toggle(false);
01277 }
01278 
01279 /**********************************************************************************/
01280 /* function segmentation: performs the region growing segmentation                */
01281 /**********************************************************************************/
01282 
01283 float segmentation(//float **input_image, 
01284            struct segment **segments_ptr_vector, 
01285            struct segment *initial_segment, 
01286            struct segment *final_segment, 
01287            long int nrows, 
01288            long int ncols, 
01289            struct segmentation_parameters parameters,
01290            bool progress_enabled_)
01291 {
01292   int curr_step;
01293   bool no_merges_prev_step = false;
01294   float spectral_h, spatial_h;
01295   float spectral_f, spatial_f;
01296   float min_fusion_f, fusion_f, ssp;
01297   long int num_segments, num_segments_unused;
01298   unsigned long int num_pixels;
01299   int dither_bits;
01300   unsigned long int num_dither_cells, dither_cell_count;
01301   struct segment *first_original_segment; /* first segment in segment list */
01302   struct segment *first_segment; /* first not deleted segment in segment list */
01303   struct segment *last_segment; /* last not deleted segment in segment list */
01304   struct segment *curr_segment; /* current segment */
01305   struct segment_neighbor *curr_neighbor; /* current neighbor */
01306   struct segment_neighbor *first_neighbor; /* root of neighbor segment list */
01307   struct segment_neighbor *best_neighbor = 0; /* lowest fusion factor to current segment */
01308 
01309   /* initializes variables */
01310   num_segments = num_pixels = nrows * ncols;
01311   first_segment = initial_segment;
01312   first_original_segment = initial_segment;
01313   last_segment = final_segment;
01314  
01315   /* square of scale parameter */
01316   ssp = parameters.sp*parameters.sp;
01317 
01318   /* calculate dimensions of dither matrix */
01319   num_dither_cells = dither_matrix_dimension(nrows, ncols, &dither_bits);
01320 
01321   curr_step = 0;
01322 
01323   /* segmentation step */
01324   TePDIPIManager pim("Segmenting image", MAX_STEPS, progress_enabled_);
01325   while ((curr_step<MAX_STEPS) && (no_merges_prev_step!=true))
01326   {
01327     /* flag that indicates if there were merges in the step */
01328     no_merges_prev_step = true;
01329 
01330     /* mark all segments as not used */
01331     num_segments_unused = num_segments;
01332 
01333     /* initialize cell count for dither search */
01334   dither_cell_count = 0;
01335 
01336   /* while there are segments not used (num_segments_unused>0)*/
01337     while (num_segments_unused>0)
01338     {
01339       /* select one segment and mark that segment as used */
01340       curr_segment = find_unused_by_dither(segments_ptr_vector, 
01341       dither_bits, nrows, ncols, &dither_cell_count);
01342     dither_cell_count++;
01343     
01344     curr_segment->used = true;
01345       num_segments_unused--;
01346 
01347       first_neighbor = curr_neighbor = NULL;
01348 
01349       /* find segment neighbors */
01350       first_neighbor = find_neighbors(curr_segment, segments_ptr_vector, nrows, ncols);
01351       curr_neighbor = first_neighbor;
01352 
01353       /* calculate heterogeinity factors for each neighbor */
01354       min_fusion_f =  (float) MAX_FLT;
01355       while (curr_neighbor != NULL)
01356       {
01357         /* calculates spectral heterogeneity */
01358         spectral_h = calc_color_stats(curr_neighbor, curr_segment, /* input_image, */ parameters);
01359     spectral_f = parameters.wcolor * spectral_h;
01360 
01361         if (spectral_f<ssp)
01362     {
01363       /* calculates spatial heterogeneity */
01364       spatial_h = calc_spatial_stats(curr_neighbor, curr_segment, 
01365         segments_ptr_vector, nrows, ncols, parameters);
01366       spatial_f = (1-parameters.wcolor) * spatial_h;
01367 
01368       /* calculates fusion factor and identify best neighbor */
01369       fusion_f = spectral_f + spatial_f;
01370       if (fusion_f<min_fusion_f)
01371       {
01372         min_fusion_f = fusion_f;
01373         best_neighbor = curr_neighbor;  
01374       }
01375     }
01376         curr_neighbor = curr_neighbor->next_neighbor; 
01377       }
01378 
01379       /* checks if merge of current segment with best neighbor is possible */
01380       if (min_fusion_f<ssp)
01381       {
01382         /* merges current segment with best neighbor and removes best neighbor */
01383         num_segments_unused = num_segments_unused - 
01384       merge_segment(best_neighbor, curr_segment, &first_segment, &last_segment, 
01385           segments_ptr_vector, nrows, ncols);
01386         num_segments--;
01387         no_merges_prev_step = false;
01388       }
01389       free_neighbor_list(&first_neighbor);
01390     }
01391     reset_unused_segments_list(num_segments, first_segment);
01392     
01393   curr_step++;
01394   pim.Increment();
01395     
01396   }
01397   return(1.0);
01398 }
01399 
01400 /**********************************************************************************/
01401 /* function calc_perimeter_optimized: calculates the perimeter of merging         */
01402 /*                         of curr_segment and curr_neighbor                      */
01403 /**********************************************************************************/
01404 
01405 void calc_perimeter_optimized(struct segment_neighbor *curr_neighbor, 
01406           struct segment *curr_segment, 
01407           struct segment **segments_ptr_vector, 
01408           long int nrows, 
01409           long int ncols)
01410 {
01411   int i;
01412   long int perimeter_total;
01413   long int neighbor_pixel[4][2]; /* first col contain pixel id, second contains segment id */
01414   struct segment_pixel *aux_pixel;
01415   struct segment_pixel *id_nb;
01416   struct segment *aux_segment; 
01417 
01418         //optimization: perimeter total is the sum of perimeters less the points of colision between them
01419         
01420         //sum perimeters
01421         perimeter_total = curr_segment->perimeter + curr_neighbor->neighbor->perimeter;
01422 
01423         //choose segment with less perimeter
01424         if ( curr_segment->perimeter <= curr_neighbor->neighbor->perimeter )
01425         {
01426     aux_pixel = curr_segment->pixel_list;
01427     id_nb = curr_neighbor->neighbor->pixel_list;
01428         }
01429         else
01430         {
01431     aux_pixel = curr_neighbor->neighbor->pixel_list;
01432     id_nb = curr_segment->pixel_list;
01433         }
01434 
01435   // for each pixel from the less perimeter segment
01436   while ( aux_pixel != NULL )
01437   {
01438                 // just for borderline
01439                 if ( aux_pixel->borderline == true )
01440                 {
01441                         find_neighbor_pixels( aux_pixel->pixel_id, nrows, ncols, 
01442                                                     &neighbor_pixel[ 0 ][ 0 ], &neighbor_pixel[ 1 ][ 0 ], 
01443                             &neighbor_pixel[ 2 ][ 0 ], &neighbor_pixel[ 3 ][ 0 ] );
01444 
01445                         //verify the neighbor pixels
01446                         for ( i = 0; i < 4; i++ )
01447                         {
01448                           if ( neighbor_pixel[i][0] != -1 ) // if it is not image limit 
01449                           {
01450           aux_segment = segments_ptr_vector[ neighbor_pixel[ i ][ 0 ] ];
01451           neighbor_pixel[i][1] = aux_segment->id;
01452 
01453           if ( neighbor_pixel[ i ][ 1 ] == (long int)id_nb->pixel_id ) //if the pixel neighbor is from grater perimeter segment
01454             perimeter_total = perimeter_total - 2;
01455                           }
01456                         }
01457                 }
01458     aux_pixel = aux_pixel->next_pixel;
01459   }
01460 
01461   curr_neighbor->perimeter = perimeter_total;
01462 }

Generated on Sun Jul 29 04:01:23 2012 for TerraLib - Development Source by  doxygen 1.5.3