Changeset 52053


Ignore:
Timestamp:
Jun 12, 2012 4:03:03 PM (4 years ago)
Author:
momsen
Message:
 
Location:
grass-addons/grass7/imagery/i.segment
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • grass-addons/grass7/imagery/i.segment/create_isegs.c

    r52019 r52053  
    1717    int successflag = 1;
    1818
    19     /* method specific parameter set up and memory allocation */
     19    /* TODO consider if there are _method specific_ parameter set up and memory allocation, should that happen here? */
    2020
    2121    if (functions->method == 1) {       /*region growing */
     
    2525
    2626    /*TODO: implement outer loop to process polygon interior, then all remaining pixels */
    27     /* This loop could go in here, or outside in main (only make segmentation file for what is currently being processed.) */
     27    /* This loop could go in here, or in main to contain open/create/write to reduced memory reqs.  But how merge the writes? */
    2828
    2929    G_debug(1, "Threshold: %g", functions->threshold);
     
    3232
    3333    if (functions->method == 0)
    34         successflag = io_debug(files, functions);       /* TODO: why does it want &files in main, but files here ??? */
     34        successflag = io_debug(files, functions);       /* TODO: why does it want `&files` in main, but `files` here ??? */
    3535    else if (functions->method == 1) {
    3636        G_debug(1, "starting region_growing()");
    3737        successflag = region_growing(files, functions);
    3838    }
    39     if (successflag != 0)
    40         G_fatal_error("Error creating segments");
    4139
    4240    /* end outer loop for processing polygons */
     
    4442    /* clean up */
    4543
    46     /* should there be a free() for every malloc?  Or only the large ones? */
    47 
    48     return 0;
     44    return successflag;
    4945}
    5046
     
    5753    G_verbose_message("writing fake data to segmentation file");
    5854    for (row = 0; row < files->nrows; row++) {
    59         G_percent(row, files->nrows, 1);        /*this didn't get displayed in the output??? Does it get erased when done? */
     55        G_percent(row, files->nrows, 1);        /* TODO this didn't get displayed in the output??? Does it get erased when done? */
    6056        for (col = 0; col < files->ncols; col++) {
    6157            /*files->out_val[0] = files->out_val[0]; *//*segment number *//* just copying the map for testing. */
     
    6662    }
    6763
    68     /* TODO: free memory */
     64    /* spot to test things... */
     65
     66
    6967
    7068    return 0;
     
    8482     * Rk = Ri's most similar neighbor
    8583     * Rkn = Rk's neighbors
    86      * Rin = Ri's neigbors (as pixels or segments ?!?
     84     * Rin = Ri's neigbors (as pixels or segments ?) currently as pixels, so repeat calculations are made when multiple neighbors in same segment
    8785     */
    8886
     
    9694
    9795    t = 0;
     96    files->candidate_count = 0;
    9897
    9998    do {
    100         /* for loop on t to slowly lower threshold. also check that endflag=0 */
    101 
    102         threshold = functions->threshold;       /* when implement t loop, this will be a function of t. */
     99        /* do while loop on t to slowly lower threshold. also check that endflag==0 */
     100
     101        G_debug(1,
     102                "#############   Starting outer do loop! t = %d ###############",
     103                t);
     104
     105        threshold = functions->threshold;       /* TODO, consider making this a function of t. */
    103106
    104107        endflag = 1;
    105108
    106 
    107109        /* Set candidate flag to true/1 for all pixels TODO: for polygon group, need to just set to true for those being processed */
    108110
    109         /*      for (row = 0; row < files->nrows; row++) {
    110            for (col = 0; col < files->ncols; col++) {   -----need to deal with edges.... */
    111         for (row = 1; row < files->nrows - 1; row++) {
    112             for (col = 1; col < files->ncols - 1; col++) {
     111        for (row = 0; row < files->nrows; row++) {
     112            for (col = 0; col < files->ncols; col++) {
    113113                segment_get(&files->out_seg, (void *)files->out_val, row, col); /*need to get, since we only want to change the flag, and not overwrite the segment value. */
    114114                /* TODO: if we are starting from seeds...and only allow merges between unassigned pixels
     
    118118                segment_put(&files->out_seg, (void *)files->out_val, row,
    119119                            col);
     120
     121                files->candidate_count++;       /*TODO this assumes full grid with no null or mask!! But need something to prevent "pathflag" infinite loop */
     122
    120123            }
    121124        }
    122         G_debug(1, "Starting to process candidate pixels");
     125        G_debug(1, "Starting to process %d candidate pixels",
     126                files->candidate_count);
     127
    123128        /*process candidate pixels */
    124129
     
    126131        for (row = 0; row < files->nrows; row++) {
    127132            for (col = 0; col < files->ncols; col++) {
    128                 segment_get(&files->out_seg, (void *)files->out_val, row,
    129                             col);
    130                 if (files->out_val[1] == 1) {   /* out_val[1] is the candidate pixel flag */
     133
     134                G_verbose_message("Completion for pass number %d: ", t);
     135                G_percent(row, files->nrows, 1);        /*this didn't get displayed in the output??? Does it get erased when done? */
     136
     137                G_debug(1,
     138                        "Next starting pixel from next row/col, not from Rk");
     139                segment_get(&files->out_seg, (void *)files->out_val, row, col); /*TODO small time savings - if candidate_count reaches zero, bail out of these loops too? */
     140                if (files->out_val[1] == 1) {   /* out_val[1] is the candidate pixel flag, want to process the 1's */
     141
     142                    /*  ... need to switch to lists/stacks/maps... */
    131143
    132144                    /*need to empty/reset Ri, Rn, and Rk */
     
    138150                    }
    139151                    Rin_count = Rkn_count = Rk_count = 0;
     152
     153                    /* First pixel in Ri is current pixel.  We may add more later if it is part of a segment */
    140154                    Ri_count = 1;       /*we'll have the focus pixel to start with. */
    141155
    142                     /* First pixel in Ri is current pixel.  We may add more later if it is part of a segment */
    143156                    Ri[0][0] = row;
    144157                    Ri[0][1] = col;
    145                     /* Ri_seg = files->out_val[0]; don't need this here -have it in merge_segments() *//* out_val[0] is segment ID, we still have data from call to check the flag. *//* TODO: if seperate segment ID from flag, need to get this value. */
    146158
    147159                    pathflag = 1;
    148160
    149                     while (pathflag == 1) {     /*if don't find mutual neighbors on first try, will use Rk as next Ri. */
    150                         G_debug(1, "just before find_segment_neighbors(Ri)");
    151                         if (find_segment_neighbors
    152                             (Ri, Rin, Ri_count, Rin_count, files,
    153                              functions) != 0) {
    154                             G_debug(1, "Couldn't find neighbors");      /*this could happen if there is a pixel surrounded by pixels that have already been processed */
    155                             pathflag = 0;
    156                             Ri_count = 0;
    157                             set_candidate_flag(Ri, 0, files);   /* TODO: error trap? */
     161                    //      while (pathflag == 1 && files->candidate_count > 0) {   /*if don't find mutual neighbors on first try, will use Rk as next Ri. */
     162
     163                    G_debug(1, "Next starting pixel: row, %d, col, %d",
     164                            Ri[0][0], Ri[0][1]);
     165
     166                    /* Setting Ri to be not a candidate allows using "itself" when at edge of raster.
     167                     * Otherwise need to use a list/count/something to know the number of pixel neighbors */
     168                    set_candidate_flag(Ri, 0, 0, files);        /* TODO: error trap? */
     169                    G_debug(1, "line 165, \t\t\t\tcc = %d",
     170                            files->candidate_count);
     171
     172
     173                    /* find segment neighbors */
     174                    if (find_segment_neighbors
     175                        (Ri, Rin, &Ri_count, &Rin_count, files,
     176                         functions) != 0) {
     177                        G_fatal_error("find_segment_neighbors() failed");
     178                    }
     179
     180                    if (Rin_count == 0) {
     181                        G_debug(1, "2a, Segment had no valid neighbors");       /*this could happen if there is a segment surrounded by pixels that have already been processed */
     182                        pathflag = 0;
     183                        Ri_count = 0;
     184                        set_candidate_flag(Ri, Ri_count, 0, files);     /* TODO: error trap? */
     185                        files->candidate_count++;       /* already counted out Ri[0]; */
     186                        G_debug(1, "line 176, \t\t\t\tcc = %d",
     187                                files->candidate_count);
     188                    }
     189                    else {      /*found neighbors, go ahead until find mutually agreeing neighbors */
     190
     191                        G_debug(1, "2b, Found Ri's pixels");
     192                        /*print out neighbors */
     193                        for (n = 0; n < Ri_count; n++)
     194                            G_debug(1, "Ri %d: row: %d, col: %d", n, Ri[n][0],
     195                                    Ri[n][1]);
     196
     197                        G_debug(1, "2b, Found Ri's neighbors");
     198                        /*print out neighbors */
     199                        for (n = 0; n < Rin_count; n++)
     200                            G_debug(1, "Rin %d: row: %d, col: %d", n,
     201                                    Rin[n][0], Rin[n][1]);
     202
     203                        /* find Ri's most similar neighbor */
     204                        Rk_id = -1;
     205                        Ri_similarity = LDBL_MAX;       /* set current similarity to max value */
     206                        segment_get(&files->bands_seg, (void *)files->bands_val, Ri[0][0], Ri[0][1]);   /* current segment values */
     207
     208                        for (n = 0; n < Rin_count; n++) {       /* for each of Ri's neighbors */
     209                            tempsim = (*functions->calculate_similarity) (Ri[0], Rin[n], files, functions);     /*TODO: does this pass just the single point, row/col ???? */
     210                            G_debug(1,
     211                                    "simularity = %g for neighbor %d: row: %d, col %d.",
     212                                    tempsim, n, Rin[n][0], Rin[n][1]);
     213                            if (tempsim < Ri_similarity) {
     214                                Ri_similarity = tempsim;
     215                                Rk_id = n;
     216                            }
    158217                        }
    159                         else {  /*found neighbors, go ahead until find mutually agreeing neighbors */
    160                             G_debug(1, "Found neighbors");
    161                             /* find Ri's most similar neighbor */
    162                             Rk_id = -1;
    163                             Ri_similarity = LDBL_MAX;   /* set current similarity to max value */
    164                             segment_get(&files->bands_seg, (void *)files->bands_val, Ri[0][0], Ri[0][1]);       /* current segment values */
    165 
    166                             for (n = 0; n < Rin_count; n++) {   /* for each of Ri's neighbors */
    167                                 tempsim = (*functions->calculate_similarity) (Ri[0], Rin[n], files, functions); /*TODO: does this pass just the single point, row/col ???? */
    168                                 if (tempsim < Ri_similarity) {
    169                                     Ri_similarity = tempsim;
    170                                     Rk_id = n;
     218
     219                        G_debug(1,
     220                                "Lowest Ri_similarity = %g, for neighbor pixel Rk_id (n) = %d",
     221                                Ri_similarity, Rk_id);
     222
     223                        if (Rk_id >= 0 && Ri_similarity < threshold) {  /* small TODO: should this be < or <= for threshold? */
     224                            /* we'll have the neighbor pixel to start with. */
     225                            G_debug(1, "3a: Working with Rk");
     226                            Rk_count = 1;
     227                            Rk[0][0] = Rin[Rk_id][0];
     228                            Rk[0][1] = Rin[Rk_id][1];
     229
     230                            /* Rkn = Ri; *//* we know Ri should be a neighbor of Rk *//*Todo: is there a way to skip similarity calculations on these?  keep a count, and pop them before doing the similarity check? */
     231                            find_segment_neighbors(Rk, Rkn, &Rk_count, &Rkn_count, files, functions);   /* data structure for Rk's neighbors, and pixels in Rk if we don't already have it */
     232
     233                            G_debug(1, "Found Rk's pixels");
     234                            /*print out neighbors */
     235                            for (n = 0; n < Rk_count; n++)
     236                                G_debug(1, "Rk %d: row: %d, col: %d", n,
     237                                        Rk[n][0], Rk[n][1]);
     238
     239                            G_debug(1, "Found Rk's neighbors");
     240                            /*print out neighbors */
     241                            for (n = 0; n < Rkn_count; n++)
     242                                G_debug(1, "Rkn %d: row: %d, col: %d", n,
     243                                        Rkn[n][0], Rkn[n][1]);
     244
     245                            /*find Rk's most similar neighbor */
     246                            Rk_similarity = Ri_similarity;      /*Ri gets first priority - ties won't change anything, so we'll accept Ri and Rk as mutually best neighbors */
     247                            segment_get(&files->bands_seg, (void *)files->bands_val, Rk[0][0], Rk[0][1]);       /* current segment values */
     248
     249                            for (n = 0; n < Rkn_count; n++) {   /* for each of Rk's neighbors */
     250                                tempsim = functions->calculate_similarity(Rk[0], Rkn[n], files, functions);     /*TODO: need an error trap here, if something goes wrong with calculating similarity? */
     251                                if (tempsim < Rk_similarity) {
     252                                    Rk_similarity = tempsim;
     253                                    break;      /* exit for Rk's neighbors loop here, we know that Ri and Rk aren't mutually best neighbors */
    171254                                }
    172255                            }
    173256
    174                             if (Rk_id >= 0 && Ri_similarity < threshold) {      /* small TODO: should this be < or <= for threshold? */
    175                                 /*we'll have the neighbor pixel to start with. */
    176                                 Rk_count = 1;
    177                                 Rk[0][0] = Rin[Rk_id][0];
    178                                 Rk[0][1] = Rin[Rk_id][1];
    179 
    180                                 /* Rkn = Ri; *//* we know Ri should be a neighbor of Rk *//*Todo: is there a way to skip similarity calculations on these?  keep a count, and pop them before doing the similarity check? */
    181                                 find_segment_neighbors(Rk, Rkn, Rk_count, Rkn_count, files, functions); /* data structure for Rk's neighbors, and pixels in Rk if we don't already have it */
    182 
    183                                 /*find Rk's most similar neighbor */
    184                                 Rk_similarity = Ri_similarity;  /*Ri gets first priority - ties won't change anything, so we'll accept Ri and Rk as mutually best neighbors */
    185                                 segment_get(&files->bands_seg, (void *)files->bands_val, Rk[0][0], Rk[0][1]);   /* current segment values */
    186 
    187                                 for (n = 0; n < Rkn_count; n++) {       /* for each of Rk's neighbors */
    188                                     tempsim =
    189                                         functions->calculate_similarity(Rk[0],
    190                                                                         Rkn
    191                                                                         [n],
    192                                                                         files,
    193                                                                         functions);
    194                                     if (tempsim < Rk_similarity) {
    195                                         Rk_similarity = tempsim;
    196                                         break;  /* exit for Rk's neighbors loop here, we know that Ri and Rk aren't mutually best neighbors */
    197                                     }
    198                                 }
    199 
    200                                 if (Rk_similarity == Ri_similarity) {   /* so they agree, both are mutually most similar neighbors */
    201                                     /* TODO: put these steps in merge_segments(Ri, Rk) function?  */
    202                                     merge_values(Ri, Rk, Ri_count, Rk_count, files);    /* TODO error trap */
    203                                     endflag = 0;        /* we've made at least one merge, so need another t iteration */
    204                                     pathflag = 0;       /* go to next row,column pixel - end of Rk -> Ri chain since we found mutual best neighbors */
    205                                 }
    206                                 else {  /* they weren't mutually best neighbors */
    207                                     set_candidate_flag(Ri, 0, files);   /* remove Ri from candidate pixels (set flag) */
    208 
    209                                     /* Use Rk as next Ri:   this is the eCognition technique.  Seems this is a bit faster, we already have segment membership pixels */
    210                                     Ri_count = Rk_count;
    211                                     /* Ri = &Rk; *//* TODO fast/correct way to use arrays and pointers? Ri now will just point to Rk? */
    212                                     /* at beginning, when initialize Rk ` Rk[n][m] = 0 ` ?? with that just remove the Rk pointer, and leave Ri pointing to the original Rk data? */
    213                                     for (n = 0; n < 100; n++) { /*TODO shortcut code...get rid of this... */
    214                                         for (m = 0; m < 2; m++) {
    215                                             Ri[n][m] = Rk[n][m];
    216                                         }
    217                                     }
    218 
    219                                 }
    220                             }   /*end if Rk exists and < threshold */
    221                         }       /* end else - Ri did have neighbors */
    222                     }           /*end pathflag do loop */
     257                            if (Rk_similarity == Ri_similarity) {       /* so they agree, both are mutually most similar neighbors, none of Rk's other neighbors were more similar */
     258                                /* TODO: put these steps in merge_segments(Ri, Rk) function?  */
     259                                merge_values(Ri, Rk, Ri_count, Rk_count, files);        /* TODO error trap */
     260                                endflag = 0;    /* we've made at least one merge, so need another t iteration */
     261                                pathflag = 0;   /* go to next row,column pixel - end of Rk -> Ri chain since we found mutual best neighbors */
     262                            }
     263                            else {      /* they weren't mutually best neighbors */
     264                                G_debug(1,
     265                                        "Ri was not Rk's best neighbor, Ri_sim: %g, Rk_sim, %g",
     266                                        Ri_similarity, Rk_similarity);
     267
     268                                /* did this at beginning of trail loop */
     269                                set_candidate_flag(Ri, Ri_count, 0, files);     /* remove all Ri members from candidate pixels (set flag) */
     270                                files->candidate_count++;       /* add one back, we had already set Ri[0] flag at the beginning. */
     271                                G_debug(1, "line 247, \t\t\t\tcc = %d",
     272                                        files->candidate_count);
     273                                //~ /* Use Rk as next Ri:   this is the eCognition technique.  Seems this is a bit faster, we already have segment membership pixels */
     274                                //~ Ri_count = Rk_count;
     275                                //~ /* Ri = &Rk; *//* TODO fast/correct way to use arrays and pointers? Ri now will just point to Rk? */
     276                                //~ /* at beginning, when initialize Rk ` Rk[n][m] = 0 ` ?? with that just remove the Rk pointer, and leave Ri pointing to the original Rk data? */
     277                                //~ for (n = 0; n < 100; n++) {     /*TODO shortcut code...get rid of this... */
     278                                //~ for (m = 0; m < 2; m++) {
     279                                //~ Ri[n][m] = Rk[n][m];
     280                                //~ }
     281                                //~ }
     282
     283                            }
     284                        }       /*end if Rk exists and < threshold */
     285                        else
     286                            G_debug(1,
     287                                    "3b Rk didn't didn't exist or similarity was > threshold");
     288                    }           /* end else - Ri did have neighbors */
     289                    //          }           /*end pathflag do loop */
    223290                }               /*end if pixel is candidate pixel */
    224291            }                   /*next column */
     
    227294        /* finished one pass for processing candidate pixels */
    228295
     296        G_debug(1, "Finished one pass, t was = %d", t);
    229297        t++;
    230298    } while (t < 90 && endflag == 0);
     
    236304}
    237305
    238 int find_segment_neighbors(int Ri[][2], int Rin[][2], int seg_count,
    239                            int segn_count, struct files *files,
     306int find_segment_neighbors(int Ri[][2], int Rin[][2], int *seg_count,
     307                           int *segn_count, struct files *files,
    240308                           struct functions *functions)
    241309{
    242     G_debug(1, "in find_segment_neighbors()");
     310    //   G_debug(1, "\tin find_segment_neighbors()");
    243311    int n, m, Ri_seg_ID = -1;
    244312
     
    249317
    250318
    251     /* Ri could be single pixel or list of pixels. */
    252     /* Rin could have a list already, or could be empty ?  Or just the head?  */
    253 
    254     /*local data structures... but maybe they should be allocated out in the main function, is it really slow to create/free on each pass? */
    255 
    256     /* Ri : input parameter, list of pixels in the current segment */
     319    /* parameter: Ri, current segment membership, could be single pixel or list of pixels. */
     320    /* parameter: Rin, neighbor pixels, could have a list already, or could be empty ?  Or just the head of a list?  */
     321
     322    /* TODO local data structures... but maybe they should be allocated out in the main function, is it really slow to create/free on each pass? */
     323
    257324    int to_check[100][2];       /* queue or stack - need to check the neighbors of these pixels */
    258325
     326    /* put no_check in files structure for now... */
    259327    /* int[100][2] no_check;    *//* sorted array or btree: list of pixels (by row / column ?) that have been put into the to_check queue, been processed, or are not candidate pixels */
    260328    /* or use flag for no_check? ... need a better name for this variable??? */
    261329
    262     int pixel_neighbors[8][2];  /* data type?  put in files to allocate memory once? */
    263 
    264     int current_pixel = 0;      /*what data type?  This will be the popped pixel in each loop. */
    265 
    266     /* functions->pixel_neighbors  ...array, 4 or 8 long.  (Can be 4 or 8 neighbors to each pixel)
    267      * functions->num_pn  int, 4 or 8. */
     330    int val_no_check = -1;      /*value of the no_check flag for the particular pixel. */
     331
     332    int pixel_neighbors[8][2];  /* TODO: data type?  put in files to allocate memory once? */
     333
     334    int current_pixel = 0;      /* TODO: for now, row index for pixel_neighbors[][].  With linked list will be the popped pixel in each loop. */
     335
     336    /* Notes, these are in fucntions structure:
     337     * functions->num_pn  int, 4 or 8, for number of pixel neighbors */
    268338
    269339    /*initialize data.... TODO: maybe remember min max row/col that was looked at each time, initialize in open_files, and reset smaller region at end of this functions */
    270     G_debug(1, "setting files->no_check to 0...");
    271     for (n = 0; n < files->nrows; n++)
    272         for (m = 0; n < files->ncols; n++)
    273             files->no_check[n][m] = 0;  /* 0 means should be checked/expanded, 1 means it has already been checked/expanded. */
    274 
    275     G_debug(1, "setting to_check to 0");
     340    for (n = 0; n < files->nrows; n++) {
     341        for (m = 0; m < files->ncols; m++) {
     342            val_no_check = 0;
     343            segment_put(&files->no_check, &val_no_check, n, m);
     344        }
     345    }
    276346
    277347    for (n = 0; n < 100; n++) {
    278348        for (m = 0; m < 2; m++) {
    279             to_check[n][m] = files->no_check[n][m] = 0;
     349            to_check[n][m] = 0;
    280350        }
    281351    }
     
    283353    /* Put Ri in to be checked and no check lists (don't expand them if we find them again) */
    284354    /* NOTE: in pseudo code also have a "current segment" list, but think we can just pass Ri and use it directly */
    285     G_debug(1, "Setting up Ri... ");
    286     for (n = 0; n < seg_count; n++) {
     355    for (n = 0; n < *seg_count; n++) {
    287356        to_check[n][0] = Ri[n][0];
    288357        to_check[n][1] = Ri[n][1];
    289358
    290         files->no_check[Ri[n][0]][Ri[n][1]] = 1;
    291     }
    292 
    293     /* empty "neighbor" list  Note: in pseudo code, but think we just pass in Rin - it was already initialized, and later could have Ri data available to start from */
     359        val_no_check = 1;
     360        segment_put(&files->no_check, &val_no_check, Ri[n][0], Ri[n][1]);
     361
     362    }
     363
     364    /* empty "neighbor" list  Note: this step is in pseudo code, but think we just pass in Rin - it was already initialized, and later could have Ri data available to start from */
    294365
    295366    /* get Ri's segment ID */
    296367    segment_get(&files->out_seg, (void *)files->out_val, Ri[0][0], Ri[0][1]);
    297     Ri_seg_ID = files->out_val[1];
    298     G_debug(1, "initializing is done, start processing");
    299     while (current_pixel >= 0) {        /* change to not empty once there is a stack... */
    300         G_debug(1, "current_pixel: %d", current_pixel);
     368    Ri_seg_ID = files->out_val[0];
     369
     370    while (current_pixel >= 0) {        /* change to not empty once there is a linked list... */
     371        G_debug(1, "\tfind neighbors(): current_pixel: %d", current_pixel);
    301372        /* current_pixel = pop next to_check element; */
    302         /*syntax for function pointer?  functions->(*find_pixel_neighbors) (to_check[current_pixel], pixel_neighbors, files); */
    303         functions->find_pixel_neighbors(to_check[current_pixel],
     373
     374        G_debug(1,
     375                "\tbefore fpn: to_check[current_pixel][0] %d , to_check[current_pixel][1] %d",
     376                to_check[current_pixel][0], to_check[current_pixel][1]);
     377
     378        functions->find_pixel_neighbors(to_check[current_pixel][0],
     379                                        to_check[current_pixel][1],
    304380                                        pixel_neighbors, files);
    305381        current_pixel--;        /* Done using this pixels coords, now check neighbors and add to the lists */
    306         G_debug(1, "found pixel neighbors");
    307         for (n = 0; n < functions->num_pn; n++) {       /*with pixel neighbors */
    308             if (files->no_check[pixel_neighbors[n][0]][pixel_neighbors[n][1]] == 0) {   /* want to check this neighbor */
    309                 files->no_check[pixel_neighbors[n][0]][pixel_neighbors[n][1]] = 1;      /* OK, check it, but don't check it again! */
     382
     383        G_debug(1,
     384                "\tafter fpn: to_check[current_pixel][0] %d , to_check[current_pixel][1] %d",
     385                to_check[current_pixel][0], to_check[current_pixel][1]);
     386
     387        /*debug what neighbors were found: */
     388        /*      for (n = 0; n < functions->num_pn; n++){
     389           G_debug(1, "\tpixel_neighbors[n][0]: %d, pixel_neighbors[n][1]: %d",  pixel_neighbors[n][0], pixel_neighbors[n][1]);
     390           } */
     391
     392        for (n = 0; n < functions->num_pn; n++) {       /* with pixel neighbors */
     393
     394            segment_get(&files->no_check, &val_no_check,
     395                        pixel_neighbors[n][0], pixel_neighbors[n][1]);
     396            G_debug(1,
     397                    "\twith pixel neighbor %d, row: %d col: %d, val_no_check = %d",
     398                    n, pixel_neighbors[n][0], pixel_neighbors[n][1],
     399                    val_no_check);
     400            if (val_no_check == 0) {    /* want to check this neighbor */
     401                val_no_check = 1;
     402                segment_put(&files->no_check, &val_no_check,
     403                            pixel_neighbors[n][0], pixel_neighbors[n][1]);
    310404
    311405                segment_get(&files->out_seg, (void *)files->out_val, pixel_neighbors[n][0], pixel_neighbors[n][1]);     /*TODO : do I need a second "out_val" data structure? */
     
    313407                if (files->out_val[1] == 1) {   /* valid candidate pixel */
    314408
    315                     G_debug(1, "files->out_val[0] = %d Ri_seg_ID = %d",
     409                    G_debug(1, "\tfiles->out_val[0] = %d Ri_seg_ID = %d",
    316410                            files->out_val[0], Ri_seg_ID);
    317411                    if (files->out_val[0] == Ri_seg_ID) {
    318                         G_debug(1, "puting pixel_neighbor in Ri");
     412                        G_debug(1, "\tputing pixel_neighbor in Ri");
    319413                        /* put pixel_neighbor[n] in Ri */
    320                         Ri[seg_count][0] = pixel_neighbors[n][0];
    321                         Ri[seg_count][1] = pixel_neighbors[n][1];
    322                         seg_count++;    /* zero index... so increment after save data. */
     414                        Ri[*seg_count][0] = pixel_neighbors[n][0];
     415                        Ri[*seg_count][1] = pixel_neighbors[n][1];
     416                        *seg_count = *seg_count + 1;    /* zero index... Ri[0] had first pixel and set count =1.  increment after save data. */
     417                        G_debug(1, "\t*seg_count now = %d", *seg_count);
    323418
    324419                        /* put pixel_neighbor[n] in to_check -- want to check this pixels neighbors */
     
    330425                    else {
    331426                        /* put pixel_neighbor[n] in Rin */
    332                         Rin[segn_count][0] = pixel_neighbors[n][0];
    333                         Rin[segn_count][1] = pixel_neighbors[n][1];
    334                         segn_count++;
     427                        Rin[*segn_count][0] = pixel_neighbors[n][0];
     428                        Rin[*segn_count][1] = pixel_neighbors[n][1];
     429                        *segn_count = *segn_count + 1;
    335430                    }
    336431                }               /*end if valid candidate pixel */
     
    342437}
    343438
    344 int find_four_pixel_neighbors(int pixel[2], int pixel_neighbors[][2],
     439int find_four_pixel_neighbors(int p_row, int p_col, int pixel_neighbors[][2],
    345440                              struct files *files)
    346441{
    347     /*
    348        G_debug(1,"in find 4 pixel neighbors () ");
    349        G_debug(1,"pixel row: %d pixel col: %d", pixel[0], pixel[1]);
    350        G_debug(1, "Total rows: %d, total cols: %d", files->nrows, files->ncols); /*check that we have files... */
     442    /*   
     443       G_debug(1,"\t\tin find 4 pixel neighbors () ");
     444       G_debug(1,"\t\tpixel row: %d pixel col: %d", p_row, p_col);
     445       G_debug(1, "\t\tTotal rows: %d, total cols: %d", files->nrows, files->ncols); *//*check that we have files... */
    351446
    352447    /* north */
    353     pixel_neighbors[0][1] = pixel[1];
    354     if (pixel[0] > 0)
    355         pixel_neighbors[0][0] = pixel[0] + 1;
     448    pixel_neighbors[0][1] = p_col;
     449    if (p_row > 0)
     450        pixel_neighbors[0][0] = p_row - 1;
    356451    else
    357         pixel_neighbors[0][0] = pixel[0];       /*This is itself, which will be in "already checked" list.  TODO: use null or -1 as flag to skip?  What is fastest to process? */
     452        pixel_neighbors[0][0] = p_row;  /*This is itself, which will be in "already checked" list.  TODO: use null or -1 as flag to skip?  What is fastest to process? */
    358453
    359454    /* east */
    360     pixel_neighbors[1][0] = pixel[0];
    361     if (pixel[1] < files->ncols)
    362         pixel_neighbors[1][1] = pixel[1] + 1;
     455    pixel_neighbors[1][0] = p_row;
     456    if (p_col < files->ncols - 1)
     457        pixel_neighbors[1][1] = p_col + 1;
    363458    else
    364         pixel_neighbors[1][1] = pixel[1];
     459        pixel_neighbors[1][1] = p_col;
    365460
    366461    /* south */
    367     pixel_neighbors[2][1] = pixel[1];
    368     if (pixel[0] < files->nrows)
    369         pixel_neighbors[2][0] = pixel[0] - 1;
     462    pixel_neighbors[2][1] = p_col;
     463    if (p_row < files->nrows - 1)
     464        pixel_neighbors[2][0] = p_row + 1;
    370465    else
    371         pixel_neighbors[2][0] = pixel[0];
     466        pixel_neighbors[2][0] = p_row;
    372467
    373468    /* west */
    374     pixel_neighbors[3][0] = pixel[0];
    375     if (pixel[1] < 0)
    376         pixel_neighbors[3][1] = pixel[1] - 1;
     469    pixel_neighbors[3][0] = p_row;
     470    if (p_col > 0)
     471        pixel_neighbors[3][1] = p_col - 1;
    377472    else
    378         pixel_neighbors[3][1] = pixel[1];
     473        pixel_neighbors[3][1] = p_col;
    379474
    380475    /*TODO: seems there should be a more elegent way to do this... */
     
    382477}
    383478
    384 int find_eight_pixel_neighbors(int pixel[2], int pixel_neighbors[8][2],
    385                                struct files *files)
     479int find_eight_pixel_neighbors(int p_row, int p_col,
     480                               int pixel_neighbors[8][2], struct files *files)
    386481{
    387482    /* get the 4 orthogonal neighbors */
    388     find_four_pixel_neighbors(pixel, pixel_neighbors, files);
     483    find_four_pixel_neighbors(p_row, p_col, pixel_neighbors, files);
    389484
    390485    /* get the 4 diagonal neighbors */
     
    395490
    396491/* similarity / distance between two points based on their input raster values */
    397 /* TODO: I pulled getting the a values into the main function, they are stored in files.  Remove a from these parameters */
     492/* assumes first point values already saved in files->bands_seg - only run segment_get once for that value... */
     493/* TODO: segment_get already happened for a[] values in the main function.  Could remove a[] from these parameters */
    398494double calculate_euclidean_similarity(int a[2], int b[2], struct files *files,
    399495                                      struct functions *functions)
     
    402498    int n;
    403499
    404     /* get comparison values for point b (got values for a before loop on all neighbors... */
     500    /* get values for point b[] */
    405501    segment_get(&files->bands_seg, (void *)files->second_val, b[0], b[1]);
    406502
     
    418514int merge_values(int Ri[100][2], int Rk[100][2], int Ri_count, int Rk_count,
    419515                 struct files *files)
    420 {                               /* I assume this is a weighted mean? */
     516{                               /* TODO: correct assumption that this should be a weighted mean. */
    421517    int n;
    422518
     
    437533    segment_get(&files->out_seg, (void *)files->out_val, Ri[0][0], Ri[0][1]);
    438534    files->out_val[1] = 0;      /*candidate pixel flag, only one merge allowed per t iteration */
    439 
     535    /* if separate out candidate flag, can do all changes with helper function...otherwise remember: */
     536
     537
     538    G_debug(1, "\t\tMerging, segment number: %d, including pixels:",
     539            files->out_val[0]);
    440540
    441541    /* for each member of Ri and Rk, write new average bands values and segment values */
     
    445545        segment_put(&files->out_seg, (void *)files->out_val, Ri[n][0],
    446546                    Ri[n][1]);
     547        files->candidate_count--;
     548        G_debug(1, "line 508, \t\t\t\tcc = %d", files->candidate_count);
     549        G_debug(1, "\t\tRi row: %d, col: %d", Ri[n][0], Ri[n][1]);
    447550    }
    448551    for (n = 0; n < Rk_count; n++) {
     
    451554        segment_put(&files->out_seg, (void *)files->out_val, Rk[n][0],
    452555                    Rk[n][1]);
    453     }
    454 
     556        files->candidate_count--;
     557        G_debug(1, "line 516, \t\t\t\tcc = %d", files->candidate_count);
     558        G_debug(1, "\t\tRk row: %d, col: %d", Rk[n][0], Rk[n][1]);
     559
     560    }
     561
     562    files->candidate_count++;   /* had already counted down the starting pixel Ri[0] at the beginning... */
     563    G_debug(1, "line 522, \t\t\t\tcc = %d", files->candidate_count);
    455564    return 0;
    456565}
    457566
    458567/* TODO.. helper function, maybe make more general? */
    459 int set_candidate_flag(int Ri[100][2], int value, struct files *files)
     568int set_candidate_flag(int Ri[100][2], int count, int value,
     569                       struct files *files)
    460570{
    461571    /* Ri is list of pixels, value is new value of flag */
     
    463573
    464574    /* TODO: Ri data structure... eventually just need to process all pixels in Ri. */
    465     for (n = 0; n < 100; n++) {
     575    for (n = 0; n <= count; n++) {
    466576        segment_get(&files->out_seg, (void *)files->out_val, Ri[n][0], Ri[n][1]);       /* this may change... */
    467577        files->out_val[1] = value;      /*candidate pixel flag */
     
    469579                    Ri[n][1]);
    470580
    471     }
    472     return 0;
    473 }
     581        /* also increment how many pixels remain to be processed */
     582
     583        if (value == 0)
     584            files->candidate_count--;
     585        else if (value == 1)
     586            files->candidate_count++;
     587        G_debug(1, "line 544, \t\t\t\tcc = %d", files->candidate_count);
     588
     589    }
     590    return 0;
     591}
  • grass-addons/grass7/imagery/i.segment/iseg.h

    r52019 r52053  
    2525    /* files */
    2626    int nbands;
     27    int candidate_count;        /*how many candidate pixels remain */
    2728    SEGMENT bands_seg, out_seg; /* bands is for input, normal application is landsat bands, but other input can be included in the group. */
    2829    double *bands_val;          /* array, to hold all input values at one pixel */
     
    3132    char *out_name;             /* name of output raster map */
    3233
    33     /*int **no_check; *//* TODO maybe as SEGMENT.  Also can this be smaller then an int?  Just need to save 0 and 1. */
    34     int no_check[100][2];
     34    SEGMENT no_check;           /* pixels that have already been checked during this neighbor finding routine */
    3535
    3636    /* RASTER_MAP_TYPE data_type;       Removed: input is always DCELL, output is CELL.
     
    5757};
    5858
    59 
    60 /* I think if I use function pointers, I can set up one time in the input
    61  * what similarity function, etc, will be used later in the processing
    62  * and make it easier to add additional variations later.
    63  */
    64 
    6559struct functions
    6660{
    6761    int method;                 /* Segmentation method */
    68     int (*find_pixel_neighbors) (int[2], int[8][2], struct files *);    /*pixel, pixel_neighbors */
    69     double (*calculate_similarity) (int[2], int[2], struct files *,
     62
     63    /* Some function pointers to set one time in parse_args() */
     64    int (*find_pixel_neighbors) (int, int, int[8][2], struct files *);  /*parameters: row, col, pixel_neighbors */
     65    double (*calculate_similarity) (int[2], int[2], struct files *,     /*parameters: two points (row,col) to compare */
    7066                                    struct functions *);
    7167
    72     int num_pn;                 /* number of pixel neighbors  int, 4 or 8. */
    73 
     68    int num_pn;                 /* number of pixel neighbors  int, 4 or 8. TODO: can remove if pixel neighbors is list instead of array.  But maybe this one is small enough that is faster as array? */
    7469    float threshold;            /* similarity threshold */
    7570
     71};
     72
     73struct pixel
     74{
     75    int row;
     76    int col;
     77    struct pixel *next;
    7678};
    7779
     
    8789int io_debug(struct files *, struct functions *);
    8890int region_growing(struct files *, struct functions *);
    89 int find_segment_neighbors(int[][2], int[][2], int, int, struct files *, struct functions *);   /* TODO: need data structure for Ri, Rin */
    90 int set_candidate_flag(int[100][2], int, struct files *);
     91int find_segment_neighbors(int[][2], int[][2], int *, int *, struct files *, struct functions *);       /* TODO: need data structure for Ri, Rin */
     92int set_candidate_flag(int[100][2], int, int, struct files *);
    9193int merge_values(int[100][2], int[100][2], int, int, struct files *);   /* I assume this is a weighted mean? */
    92 int find_four_pixel_neighbors(int[2], int[][2], struct files *);
    93 int find_eight_pixel_neighbors(int[2], int[8][2], struct files *);
     94int find_four_pixel_neighbors(int, int, int[][2], struct files *);
     95int find_eight_pixel_neighbors(int, int, int[8][2], struct files *);
    9496double calculate_euclidean_similarity(int[2], int[2], struct files *,
    9597                                      struct functions *);
     
    9799
    98100/* write_output.c */
    99 /* also currently closes files */
    100101int write_output(struct files *);
     102int close_files(struct files *);
  • grass-addons/grass7/imagery/i.segment/main.c

    r52006 r52053  
    3939
    4040    if (parse_args(argc, argv, &files, &functions) != 0)
    41         G_fatal_error("Error in parse_args()");
     41        G_debug(1, "Error in parse_args()");    /* TODO: should these be debug or G_fatal_error() or nested if statement? want to clean up mem and temp files */
    4242
    4343    G_debug(1, "Main: starting open_files()");
    4444    if (open_files(&files) != 0)
    45         G_fatal_error("Error in open_files()");
     45        G_debug(1, "Error in open_files()");
    4646
    4747    G_debug(1, "Main: starting create_isegs()");
    4848    if (create_isegs(&files, &functions) != 0)
    49         G_fatal_error("Error in create_isegs()");
     49        G_debug(1, "Error in create_isegs()");
    5050
    5151    G_debug(1, "Main: starting write_output()");
    5252    if (write_output(&files) != 0)
    53         G_fatal_error("Error in write_output()");
     53        G_debug(1, "Error in write_output()");
     54
     55    G_debug(1, "Main: starting close_files()");
     56    close_files(&files);
     57
     58    /* TODO - G_fatal_error() called in sub routines - do I need to run close_files() before quitting?
     59     * http://rackerhacker.com/2010/03/18/sigterm-vs-sigkill/
     60     * "Standard C applications have a header file that contains the steps that the process should follow if it receives a particular signal. "
     61     *  */
    5462
    5563    G_done_msg("Number of segments created: ");
  • grass-addons/grass7/imagery/i.segment/parse_args.c

    r52019 r52053  
    8585    files->image_group = group->answer;
    8686
    87     /* TODO: I'm assuming it is already validated as a number.  Is this OK, or is there a better way to cast the input? */
    88     /* reference r.cost line 313
    89        if (sscanf(opt5->answer, "%d", &maxcost) != 1 || maxcost < 0)
    90        G_fatal_error(_("Inappropriate maximum cost: %d"), maxcost); */
    91 
    9287    if (G_legal_filename(output->answer) == 1)
    9388        files->out_name = output->answer;       /* name of output raster map */
     
    9691
    9792    /* segmentation methods:  0 = debug, 1 = region growing */
     93    /* TODO, instead of string compare, does the Option structure have these already numbered? */
    9894
    9995    if (strncmp(method->answer, "io_debug", 5) == 0)
     
    106102    G_debug(1, "segmentation method: %d", functions->method);
    107103
    108 
     104    /* TODO: I'm assuming threshold is already validated as a number.  Is this OK, or is there a better way to cast the input? */
     105    /* reference r.cost line 313
     106       if (sscanf(opt5->answer, "%d", &maxcost) != 1 || maxcost < 0)
     107       G_fatal_error(_("Inappropriate maximum cost: %d"), maxcost); */
    109108    sscanf(threshold->answer, "%f", &functions->threshold);
    110109
     
    120119    }
    121120
    122     /* note from tutorial: You may have got to use the complete name of the member function
    123      * including class-name and scope-operator (::).) */
    124 
    125121    /* TODO add user input for this */
    126122    functions->calculate_similarity = &calculate_euclidean_similarity;
  • grass-addons/grass7/imagery/i.segment/write_output.c

    r52019 r52053  
    11/* transfer the segmented regions from the segmented data file to a raster file */
    2 /* put closing segment files here for now, OK to combine or better to put in a seperate function? */
     2/* close_files() function is at bottom */
    33
    44#include <stdlib.h>
     
    3737    }
    3838
     39    /* close and save file */
     40    Rast_close(out_fd);
    3941
     42    return 0;
     43}
     44
     45int close_files(struct files *files)
     46{
    4047    /* close segmentation files and output raster */
    4148    G_debug(1, "closing files");
    4249    segment_close(&files->bands_seg);
    4350    segment_close(&files->out_seg);
    44     Rast_close(out_fd);
     51    segment_close(&files->no_check);
    4552
    46     for (n = 0; n < files->nrows; n++)
    47         G_free(files->no_check[n]);
    48     G_free(files->no_check);
     53    /* close segmentation files and output raster */
     54
     55    G_free(files->bands_val);
     56    G_free(files->second_val);
     57    G_free(files->out_val);
    4958
    5059    /* anything else left to clean up? */
Note: See TracChangeset for help on using the changeset viewer.