00001 #define MAX_FLT 3.4e38
00002
00003
00004 #include <cstdlib>
00005 #include <iostream>
00006 #include <iomanip>
00007 #include <fstream>
00008 #include <time.h>
00009 #include <math.h>
00010
00011
00012 #include "TePDIBaatz.hpp"
00013 #include "TePDIRaster2Vector.hpp"
00014 #include "TePDIUtils.hpp"
00015
00016 using namespace std;
00017
00018
00019
00020
00021
00022 TePDIBaatz::TePDIBaatz()
00023 {
00024 }
00025
00026 bool TePDIBaatz::CheckParameters( const TePDIParameters& parameters ) const
00027 {
00028
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
00048 TePDITypes::TePDIRasterPtrType output_image;
00049 TEAGN_TRUE_OR_RETURN(parameters.GetParameter( "output_image", output_image ),
00050 "Missing parameter: output_image");
00051
00052
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
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
00097 int H = input_image->params().nlines_,
00098 W = input_image->params().ncols_,
00099 B = input_channels.size();
00100
00101
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
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
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
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
00175
00176
00177
00178
00179
00180
00181
00182
00183
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
00208
00209
00210
00211 void remove_segment(struct segment *aux_segment,
00212 struct segment **first_segment,
00213 struct segment **last_segment);
00214
00215
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
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
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
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
00247 void free_neighbor_list(struct segment_neighbor **first_neighbor);
00248
00249
00250 float calc_color_stats (struct segment_neighbor *curr_neighbor,
00251 struct segment *curr_segment,
00252
00253 struct segmentation_parameters parameters);
00254
00255
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
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
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
00278 void calc_bounding_box(struct segment_neighbor *curr_neighbor,
00279 struct segment *curr_segment);
00280
00281
00282 void reset_unused_segments_list(unsigned long int num_segments,
00283 struct segment *first_segment);
00284
00285
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
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
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
00314
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
00351
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
00413
00414
00415 int initialize_segments(struct segment ***segments_ptr_vector,
00416 struct segment **first_segment,
00417 struct segment **last_segment,
00418
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
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
00498
00499
00500
00501
00502
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
00545 return(1);
00546 }
00547 return(0);
00548 }
00549
00550
00551
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
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
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
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];
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
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
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
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
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
00720
00721
00722
00723 float calc_color_stats (struct segment_neighbor *curr_neighbor,
00724 struct segment *curr_segment,
00725
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
00764
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];
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
00786
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];
00799
00800
00801
00802 neighbor = curr_neighbor->neighbor;
00803
00804
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
00811 perimeter[0] = curr_segment->perimeter;
00812 perimeter[1] = neighbor->perimeter;
00813 if (area[2]<4)
00814 {
00815 if (area[2]==2)
00816 curr_neighbor->perimeter = 6;
00817 else
00818 curr_neighbor->perimeter = 8;
00819 }
00820 else
00821 {
00822
00823
00824 calc_perimeter_optimized(curr_neighbor, curr_segment, segments_ptr_vector, nrows, ncols);
00825
00826
00827
00828 }
00829 perimeter[2] = curr_neighbor->perimeter;
00830
00831
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
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
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
00846 spatial_h = parameters.wcmpt*compact_f + (1-parameters.wcmpt)*smooth_f;
00847 return(spatial_h);
00848 }
00849
00850
00851
00852
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];
00865 struct segment_pixel *aux_pixel;
00866 struct segment *aux_segment;
00867
00868 perimeter_total = 0;
00869
00870 for (j=0;j<2;j++)
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
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
00890 k = 0;
00891 for (i=0; i<4; i++)
00892 if (neighbor_pixel[i][0]==-1)
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
00914
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
00945
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];
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
00964 aux_pixel = curr_neighbor->neighbor->pixel_list;
00965 while (aux_pixel!=NULL)
00966 {
00967
00968 segments_ptr_vector[aux_pixel->pixel_id] = curr_segment;
00969
00970
00971 if ((aux_pixel->borderline==true)&&(curr_segment->area>6))
00972
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
00977
00978 i=0;
00979 while ((i<4)&&(i>-1))
00980 {
00981 if (neighbor_pixel[i][0]==-1)
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)
01001 {
01002 aux_pixel->borderline=false;
01003 }
01004 }
01005 aux_pixel = aux_pixel->next_pixel;
01006 }
01007
01008 if (curr_segment->area>6)
01009 {
01010
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
01019
01020 i=0;
01021 while ((i<4)&&(i>-1))
01022 {
01023 if (neighbor_pixel[i][0]==-1)
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)
01043 {
01044 aux_pixel->borderline=false;
01045 }
01046 }
01047 aux_pixel = aux_pixel->next_pixel;
01048 }
01049 }
01050
01051
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
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
01088
01089
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
01106 if (neighbor->used)
01107 {
01108 not_used = false;
01109 }
01110 else
01111 {
01112 not_used = true;
01113 neighbor->used = true;
01114 }
01115
01116
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
01132 reset_pixels(curr_neighbor, curr_segment, segments_ptr_vector, nrows, ncols);
01133
01134
01135 remove_segment(neighbor, first_segment, last_segment);
01136
01137 return(not_used);
01138 }
01139
01140
01141
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
01153 aux_segment=*initial_segment;
01154 while (aux_segment!=NULL)
01155 {
01156
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
01171 if (segments_ptr_vector!=NULL)
01172 {
01173 free(*segments_ptr_vector);
01174 *segments_ptr_vector=NULL;
01175 }
01176 }
01177
01178
01179
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
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
01200
01201
01202 void write_segments(
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
01216 aux_segment = first_segment;
01217 while (aux_segment->pixel_list==NULL)
01218 {
01219 aux_segment = aux_segment->next_original_segment;
01220 }
01221
01222
01223 TePDIPIManager pim("Writing segments", nrows * ncols, progress_enabled_);
01224 long pixel_id = 1;
01225 while (aux_segment!=NULL)
01226 {
01227
01228 switch (write_type)
01229 {
01230 case 0:
01231 color[0] = pixel_id++;
01232
01233
01234 break;
01235 case 3:
01236 color[0] = (int) floor((double)aux_segment->id / 256.0);
01237
01238
01239 break;
01240 default:
01241 color[0] = (int) floor(aux_segment->avg_color[0]);
01242
01243
01244 break;
01245 }
01246
01247
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
01254
01255
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
01263
01264
01265 }
01266 if (write_type==3)
01267 {
01268
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
01281
01282
01283 float segmentation(
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;
01302 struct segment *first_segment;
01303 struct segment *last_segment;
01304 struct segment *curr_segment;
01305 struct segment_neighbor *curr_neighbor;
01306 struct segment_neighbor *first_neighbor;
01307 struct segment_neighbor *best_neighbor = 0;
01308
01309
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
01316 ssp = parameters.sp*parameters.sp;
01317
01318
01319 num_dither_cells = dither_matrix_dimension(nrows, ncols, &dither_bits);
01320
01321 curr_step = 0;
01322
01323
01324 TePDIPIManager pim("Segmenting image", MAX_STEPS, progress_enabled_);
01325 while ((curr_step<MAX_STEPS) && (no_merges_prev_step!=true))
01326 {
01327
01328 no_merges_prev_step = true;
01329
01330
01331 num_segments_unused = num_segments;
01332
01333
01334 dither_cell_count = 0;
01335
01336
01337 while (num_segments_unused>0)
01338 {
01339
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
01350 first_neighbor = find_neighbors(curr_segment, segments_ptr_vector, nrows, ncols);
01351 curr_neighbor = first_neighbor;
01352
01353
01354 min_fusion_f = (float) MAX_FLT;
01355 while (curr_neighbor != NULL)
01356 {
01357
01358 spectral_h = calc_color_stats(curr_neighbor, curr_segment, parameters);
01359 spectral_f = parameters.wcolor * spectral_h;
01360
01361 if (spectral_f<ssp)
01362 {
01363
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
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
01380 if (min_fusion_f<ssp)
01381 {
01382
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
01402
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];
01414 struct segment_pixel *aux_pixel;
01415 struct segment_pixel *id_nb;
01416 struct segment *aux_segment;
01417
01418
01419
01420
01421 perimeter_total = curr_segment->perimeter + curr_neighbor->neighbor->perimeter;
01422
01423
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
01436 while ( aux_pixel != NULL )
01437 {
01438
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
01446 for ( i = 0; i < 4; i++ )
01447 {
01448 if ( neighbor_pixel[i][0] != -1 )
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 )
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 }