[GRASS-SVN] r52514 - grass-addons/grass7/imagery/i.segment
svn_grass at osgeo.org
svn_grass at osgeo.org
Fri Aug 3 17:13:54 PDT 2012
Author: momsen
Date: 2012-08-03 17:13:53 -0700 (Fri, 03 Aug 2012)
New Revision: 52514
Modified:
grass-addons/grass7/imagery/i.segment/create_isegs.c
grass-addons/grass7/imagery/i.segment/iseg.h
grass-addons/grass7/imagery/i.segment/open_files.c
grass-addons/grass7/imagery/i.segment/parse_args.c
grass-addons/grass7/imagery/i.segment/write_output.c
Log:
updated seeds logic. Added Manhattan distance. Removed candidate_count.
Modified: grass-addons/grass7/imagery/i.segment/create_isegs.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/create_isegs.c 2012-08-03 23:55:50 UTC (rev 52513)
+++ grass-addons/grass7/imagery/i.segment/create_isegs.c 2012-08-04 00:13:53 UTC (rev 52514)
@@ -4,6 +4,7 @@
#include <stdlib.h>
#include <float.h> /* for DBL_MAX */
+#include <math.h> /* for fabs() */
#include <grass/gis.h>
#include <grass/glocale.h>
#include <grass/raster.h>
@@ -19,7 +20,7 @@
#endif
#define LINKM
-#define ROWMAJOR //gave nesting error with INDENT program since this changes the for loops
+#define ROWMAJOR //gave nesting error with INDENT program since this changes the for loops
int create_isegs(struct files *files, struct functions *functions)
{
@@ -27,8 +28,13 @@
int successflag = 1;
struct Range range;
- functions->threshold = functions->threshold * functions->threshold * files->nbands; /* use modified threshold to account for scaled input and to avoid square root in similarity comparison. */
+ /* todo double check this for different distance measurements and numbers of bands. */
+ if (functions->calculate_similarity == calculate_euclidean_similarity)
+ functions->threshold = functions->threshold * functions->threshold * files->nbands; /* use modified threshold to account multiple input bands and to avoid square root in similarity comparison. */
+ else
+ functions->threshold = functions->threshold * files->nbands; /* use modified threshold to account for multiple input bands. */
+
/* set parameters for outer processing loop for polygon constraints */
if (files->bounds_map == NULL) { /*normal processing */
lower_bound = upper_bound = 0; /* so run the segmentation algorithm just one time */
@@ -413,7 +419,7 @@
for (col = 0; col < files->ncols; col++) {
/*files->out_val[0] = files->out_val[0]; *//*segment number *//* just copying the map for testing. */
//~ files->iseg[row][col] = col + row;
- //todo need variable..
+ //todo need variable if this speed test will be used again..
//segment_put(&files->iseg_seg, (void *)s, row, col);
}
G_percent(row, files->nrows, 1);
@@ -496,7 +502,6 @@
start = clock();
for (i = 0; i < max; i++) {
//~ temp = files->iseg[12][12];
- //todo
}
end = clock();
cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
@@ -770,7 +775,7 @@
int get_segID_RAM(struct files *files, int row, int col)
{
- return 0; //todo... segment_put(&files->iseg_seg, (void *)s, row, col); files->iseg[row][col];
+ return 0; //files->iseg[row][col];
}
#endif
@@ -806,13 +811,11 @@
* Rkn = Rk's neighbors
* Rin = Ri's neigbors
* */
-
if (files->bounds_map == NULL)
G_message(_("Running region growing algorithm, the percent completed is based on %d max iterations, but the process will end earlier if no further merges can be made."),
functions->end_t);
t = 1;
- //~ files->candidate_count = 0;
/*set linked list head pointers to null. */
Ri_head = NULL;
@@ -831,19 +834,15 @@
#endif
fprintf(stdout, "pass %d\n", t);
G_debug(3, "####### Starting outer do loop! t = %d #######", t);
- /* todo, delete this? G_verbose_message("Pass %d: ", t); */
G_percent(t, functions->end_t, 1);
threshold = functions->threshold; /* TODO, consider making this a function of t. */
endflag = TRUE;
+ /* Set candidate flag to true/1 for all pixels */
set_all_candidate_flags(files);
- /* Set candidate flag to true/1 for all pixels */
- //~ G_debug(4, "Starting to process %d candidate pixels",
- //~ files->candidate_count);
-
/*process candidate pixels for this iteration */
/*check each pixel, start the processing only if it is a candidate pixel */
@@ -851,346 +850,342 @@
for (row = 0; row < files->nrows; row++) {
for (col = 0; col < files->ncols; col++) {
#else
-{
- /* z-order traversal: */
- /* need to get a "square" power of 2 around our processing area */
-
- /*largest dimension: */
- if (files->nrows > files->ncols)
+ {
+ /* z-order traversal: */
+ /* need to get a "square" power of 2 around our processing area */
+
+ /*largest dimension: */
+ if (files->nrows > files->ncols)
end_z = files->nrows;
- else
+ else
end_z = files->ncols;
-
- /* largest power of 2: */
- end_z--; /* in case we are already a power of two. */
- end_z = (end_z >> 1) | end_z;
- end_z = (end_z >> 2) | end_z;
- end_z = (end_z >> 4) | end_z;
- end_z = (end_z >> 8) | end_z;
- end_z = (end_z >> 16) | end_z;
- end_z = (end_z >> 32) | end_z; /* only for 64-bit architecture TODO, would this mess things up on 32? */
- /*todo does this need to repeat more since it is long unsigned??? */
- end_z++;
-
- /*squared: */
- end_z *= end_z;
-
- for (z = 0; z < end_z; z++) {
+
+ /* largest power of 2: */
+ end_z--; /* in case we are already a power of two. */
+ end_z = (end_z >> 1) | end_z;
+ end_z = (end_z >> 2) | end_z;
+ end_z = (end_z >> 4) | end_z;
+ end_z = (end_z >> 8) | end_z;
+ end_z = (end_z >> 16) | end_z;
+ end_z = (end_z >> 32) | end_z; /* only for 64-bit architecture TODO, would this mess things up on 32? */
+ /*todo does this need to repeat more since it is long unsigned??? */
+ end_z++;
+
+ /*squared: */
+ end_z *= end_z;
+
+ for (z = 0; z < end_z; z++) {
row = col = 0;
/*bit wise construct row and col from i */
for (j = 8 * sizeof(long int) - 1; j > 1; j--) {
- row = row | (1 & (z >> j));
- row = row << 1;
- j--;
- col = col | (1 & (z >> j));
- col = col << 1;
+ row = row | (1 & (z >> j));
+ row = row << 1;
+ j--;
+ col = col | (1 & (z >> j));
+ col = col << 1;
}
row = row | (1 & (z >> j));
j--;
col = col | (1 & (z >> j));
if (row >= files->nrows || col >= files->ncols)
- continue; /* todo polish, if z-order is helpful, could skip to the next z that is in the processing area. */
-}
+ continue; /* todo polish, if z-order is helpful, could skip to the next z that is in the processing area. */
+ }
#endif
- G_debug(4, "Starting pixel from next row/col, not from Rk");
+ G_debug(4, "Starting pixel from next row/col, not from Rk");
- if (FLAG_GET(files->candidate_flag, row, col) && FLAG_GET(files->seeds_flag, row, col)) { //todo OK? added the && for seed_flag...
- /*free memory for linked lists */
- my_dispose_list(files->token, &Ri_head);
- my_dispose_list(files->token, &Rk_head);
- my_dispose_list(files->token, &Rin_head);
- my_dispose_list(files->token, &Rkn_head);
- my_dispose_list(files->token, &Rclose_head);
- Rk_count = 0;
+ if (FLAG_GET(files->candidate_flag, row, col) &&
+ FLAG_GET(files->seeds_flag, row, col)) {
+ /*free memory for linked lists */
+ my_dispose_list(files->token, &Ri_head);
+ my_dispose_list(files->token, &Rk_head);
+ my_dispose_list(files->token, &Rin_head);
+ my_dispose_list(files->token, &Rkn_head);
+ my_dispose_list(files->token, &Rclose_head);
+ Rk_count = 0;
- /* First pixel in Ri is current row/col pixel. We may add more later if it is part of a segment */
- Ri_count = 1;
- newpixel = (struct pixels *)link_new(files->token);
- newpixel->next = NULL;
- newpixel->row = row;
- newpixel->col = col;
- Ri_head = newpixel;
+ /* First pixel in Ri is current row/col pixel. We may add more later if it is part of a segment */
+ Ri_count = 1;
+ newpixel = (struct pixels *)link_new(files->token);
+ newpixel->next = NULL;
+ newpixel->row = row;
+ newpixel->col = col;
+ Ri_head = newpixel;
- pathflag = TRUE;
+ pathflag = TRUE;
- while (pathflag == TRUE) { /*if don't find mutual neighbors on first try, will use Rk as next Ri. */
- //TODO: I originally thought I would need to keep track of remaining candidate pixels. But now for the pathflag
- //there is first a check if Rk is a candidate. So I think this && statment and all candidate_count statements can be removed.
- //&& files->candidate_count > 0
- G_debug(4, "Next starting pixel: row, %d, col, %d",
- Ri_head->row, Ri_head->col);
+ while (pathflag == TRUE) { /*if don't find mutual neighbors on first try, will use Rk as next Ri. */
+ G_debug(4, "Next starting pixel: row, %d, col, %d",
+ Ri_head->row, Ri_head->col);
- pathflag = FALSE;
+ pathflag = FALSE;
- /* find segment neighbors, if we don't already have them */
- if (Rin_head == NULL) {
+ /* find segment neighbors, if we don't already have them */
+ if (Rin_head == NULL) {
#ifdef PROFILE
- fn_start = clock();
+ fn_start = clock();
#endif
- if (find_segment_neighbors
- (&Ri_head, &Rin_head, &Ri_count, files,
- functions) != TRUE) {
- G_fatal_error
- ("find_segment_neighbors() failed");
- }
+ if (find_segment_neighbors
+ (&Ri_head, &Rin_head, &Ri_count, files,
+ functions) != TRUE) {
+ G_fatal_error("find_segment_neighbors() failed");
+ }
#ifdef PROFILE
- fn_end = clock();
- fn_lap =
- ((double)(fn_end - fn_start)) /
- CLOCKS_PER_SEC;
- fn_accum += fn_lap;
- fprintf(stdout, "fsn(Ri): %g\t", fn_lap);
+ fn_end = clock();
+ fn_lap =
+ ((double)(fn_end - fn_start)) / CLOCKS_PER_SEC;
+ fn_accum += fn_lap;
+ fprintf(stdout, "fsn(Ri): %g\t", fn_lap);
#endif
- }
+ }
- if (Rin_head != NULL) { /*found neighbors, find best neighbor then see if is mutually best neighbor */
+ if (Rin_head != NULL) { /*found neighbors, find best neighbor then see if is mutually best neighbor */
#ifdef DEBUG
- /*print out segment membership */
- G_debug(4, "2b, Found Ri's pixels");
- for (current = Ri_head; current != NULL;
- current = current->next)
- G_debug(4, "Ri: row: %d, col: %d",
- current->row, current->col);
- /*print out neighbors */
- G_debug(4, "2b, Found Ri's neighbors");
- for (current = Rin_head; current != NULL;
- current = current->next)
- G_debug(4, "Rin: row: %d, col: %d",
- current->row, current->col);
+ /*print out segment membership */
+ G_debug(4, "2b, Found Ri's pixels");
+ for (current = Ri_head; current != NULL;
+ current = current->next)
+ G_debug(4, "Ri: row: %d, col: %d",
+ current->row, current->col);
+ /*print out neighbors */
+ G_debug(4, "2b, Found Ri's neighbors");
+ for (current = Rin_head; current != NULL;
+ current = current->next)
+ G_debug(4, "Rin: row: %d, col: %d",
+ current->row, current->col);
#endif
- /* ******** find Ri's most similar neighbor ******** */
- Ri_bestn = NULL;
- Ri_similarity = threshold + 1; /* set current similarity to max value */
- segment_get(&files->bands_seg, (void *)files->bands_val, Ri_head->row, Ri_head->col); /* current segment values */
+ /* ******** find Ri's most similar neighbor ******** */
+ Ri_bestn = NULL;
+ Ri_similarity = threshold + 1; /* set current similarity to max value */
+ segment_get(&files->bands_seg, (void *)files->bands_val, Ri_head->row, Ri_head->col); /* current segment values */
- /* for each of Ri's neighbors */
- for (current = Rin_head; current != NULL;
- current = current->next) {
- tempsim = (*functions->calculate_similarity)
- (Ri_head, current, files, functions);
+ /* for each of Ri's neighbors */
+ for (current = Rin_head; current != NULL;
+ current = current->next) {
+ tempsim = (*functions->calculate_similarity)
+ (Ri_head, current, files, functions);
+ G_debug(4,
+ "simularity = %g for neighbor : row: %d, col %d.",
+ tempsim, current->row, current->col);
+
+ /* if very close, will merge, but continue checking other neighbors */
+ //~ if (tempsim < functions->very_close * threshold){
+ //~ /* add to Rclose list */
+ //~ newpixel = (struct pixels *)link_new(files->token);
+ //~ newpixel->next = Rclose_head;
+ //~ newpixel->row = current->row;
+ //~ newpixel->col = current->col;
+ //~ Rclose_head = newpixel;
+ //~ }
+ /* If "sort of" close, merge only if it is the mutually most similar */
+ //~ else
+ if (tempsim < Ri_similarity) {
+ Ri_similarity = tempsim;
+ Ri_bestn = current;
G_debug(4,
- "simularity = %g for neighbor : row: %d, col %d.",
- tempsim, current->row, current->col);
+ "Current lowest Ri_similarity = %g, for neighbor pixel row: %d col: %d",
+ Ri_similarity, Ri_bestn->row,
+ Ri_bestn->col);
+ }
+ } /* finished similiarity check for all neighbors */
- /* if very close, will merge, but continue checking other neighbors */
- //~ if (tempsim < functions->very_close * threshold){
- //~ /* add to Rclose list */
- //~ newpixel = (struct pixels *)link_new(files->token);
- //~ newpixel->next = Rclose_head;
- //~ newpixel->row = current->row;
- //~ newpixel->col = current->col;
- //~ Rclose_head = newpixel;
- //~ }
- /* If "sort of" close, merge only if it is the mutually most similar */
- //~ else
- if (tempsim < Ri_similarity) {
- Ri_similarity = tempsim;
- Ri_bestn = current;
- G_debug(4,
- "Current lowest Ri_similarity = %g, for neighbor pixel row: %d col: %d",
- Ri_similarity, Ri_bestn->row,
- Ri_bestn->col);
- }
- } /* finished similiarity check for all neighbors */
+ /* *** merge all the "very close" pixels/segments *** */
+ /* doing this after checking all Rin, so we don't change the bands_val between similarity comparisons
+ * TODO... but that leaves the possibility that we have the wrong best Neighbor after doing these merges...
+ * but it seems we can't put this merge after the Rk/Rkn portion of the loop, because we are changing the available neighbors
+ * ...maybe this extra "very close" idea has to be done completely differently or dropped??? */
+ for (current = Rclose_head; current != NULL;
+ current = current->next) {
+ my_dispose_list(files->token, &Rc_head);
+ my_dispose_list(files->token, &Rcn_head);
- /* *** merge all the "very close" pixels/segments *** */
- /* doing this after checking all Rin, so we don't change the bands_val between similarity comparisons
- * TODO... but that leaves the possibility that we have the wrong best Neighbor after doing these merges...
- * but it seems we can't put this merge after the Rk/Rkn portion of the loop, because we are changing the available neighbors
- * ...maybe this extra "very close" idea has to be done completely differently or dropped??? */
- for (current = Rclose_head; current != NULL;
- current = current->next) {
- my_dispose_list(files->token, &Rc_head);
- my_dispose_list(files->token, &Rcn_head);
+ /* get membership of neighbor segment */
+ Rc_count = 1;
+ newpixel =
+ (struct pixels *)link_new(files->token);
+ newpixel->next = NULL;
+ newpixel->row = current->row;
+ newpixel->col = current->col;
+ Rc_head = Rc_tail = newpixel;
+ find_segment_neighbors(&Rc_head, &Rcn_head, &Rc_count, files, functions); /* just to get members, not looking at neighbors now */
+ merge_values(Ri_head, Rc_head, Ri_count,
+ Rc_count, files);
- /* get membership of neighbor segment */
- Rc_count = 1;
- newpixel =
- (struct pixels *)link_new(files->token);
- newpixel->next = NULL;
- newpixel->row = current->row;
- newpixel->col = current->col;
- Rc_head = Rc_tail = newpixel;
- find_segment_neighbors(&Rc_head, &Rcn_head, &Rc_count, files, functions); /* just to get members, not looking at neighbors now */
- merge_values(Ri_head, Rc_head, Ri_count,
- Rc_count, files);
+ /* Add Rc pixels to Ri */
+ Rc_tail->next = Ri_head;
+ Ri_head = Rc_head;
- /* Add Rc pixels to Ri */
- Rc_tail->next = Ri_head;
- Ri_head = Rc_head;
+ //todo, recurse? Check all Rcn neighbors if they are very close?
+ // not needed if the combining works... my_dispose_list(files->token, &Rc_head);
+ Rc_head = NULL;
+ my_dispose_list(files->token, &Rcn_head);
+ }
+ my_dispose_list(files->token, &Rclose_head);
- //todo, recurse? Check all Rcn neighbors if they are very close?
- // not needed if the combining works... my_dispose_list(files->token, &Rc_head);
- Rc_head = NULL;
- my_dispose_list(files->token, &Rcn_head);
- }
- my_dispose_list(files->token, &Rclose_head);
+ /* check if we have a bestn that is valid to use to look at Rk */
+ if (Ri_bestn != NULL) {
+ G_debug(4,
+ "Lowest Ri_similarity = %g, for neighbor pixel row: %d col: %d",
+ Ri_similarity, Ri_bestn->row,
+ Ri_bestn->col);
- /* check if we have a bestn that is valid to use to look at Rk */
- if (Ri_bestn != NULL) {
- G_debug(4,
- "Lowest Ri_similarity = %g, for neighbor pixel row: %d col: %d",
- Ri_similarity, Ri_bestn->row,
- Ri_bestn->col);
-
- //todo this "limited" flag will probably be removed? Then this entire if section could be removed if we always allow multiple merges per pass?
- if ((functions->limited == TRUE) && !
- (FLAG_GET
- (files->candidate_flag,
- Ri_bestn->row, Ri_bestn->col))) {
- /* this check is important:
- * best neighbor is not a valid candidate, was already merged earlier in this time step */
- Ri_bestn = NULL;
- }
+ //todo this "limited" flag will probably be removed? Then this entire if section could be removed if we always allow multiple merges per pass?
+ if ((functions->limited == TRUE) && !
+ (FLAG_GET
+ (files->candidate_flag,
+ Ri_bestn->row, Ri_bestn->col))) {
+ /* this check is important:
+ * best neighbor is not a valid candidate, was already merged earlier in this time step */
+ Ri_bestn = NULL;
}
- if (Ri_bestn != NULL && Ri_similarity < threshold) { /* small TODO: should this be < or <= for threshold? */
- /* Rk starts from Ri's best neighbor */
- if (Rk_head) {
- G_warning("Rk_head is not NULL!");
- my_dispose_list(files->token, &Rk_head);
- }
- if (Rkn_head) {
- G_warning("Rkn_head is not NULL!");
- my_dispose_list(files->token, &Rkn_head);
- }
- Rk_count = 1;
- newpixel =
- (struct pixels *)link_new(files->token);
- newpixel->next = NULL;
- newpixel->row = Ri_bestn->row;
- newpixel->col = Ri_bestn->col;
- Rk_head = newpixel;
+ }
+ if (Ri_bestn != NULL && Ri_similarity < threshold) { /* small TODO: should this be < or <= for threshold? */
+ /* Rk starts from Ri's best neighbor */
+ if (Rk_head) {
+ G_warning("Rk_head is not NULL!");
+ my_dispose_list(files->token, &Rk_head);
+ }
+ if (Rkn_head) {
+ G_warning("Rkn_head is not NULL!");
+ my_dispose_list(files->token, &Rkn_head);
+ }
+ Rk_count = 1;
+ newpixel =
+ (struct pixels *)link_new(files->token);
+ newpixel->next = NULL;
+ newpixel->row = Ri_bestn->row;
+ newpixel->col = Ri_bestn->col;
+ Rk_head = newpixel;
- find_segment_neighbors(&Rk_head, &Rkn_head,
- &Rk_count, files,
- functions);
+ find_segment_neighbors(&Rk_head, &Rkn_head,
+ &Rk_count, files,
+ functions);
#ifdef DEBUG
- /*print out neighbors */
- G_debug(4, "Found Rk's pixels");
- for (current = Rk_head; current != NULL;
- current = current->next)
- G_debug(4, "Rk: row: %d, col: %d",
- current->row, current->col);
- /*print out neighbors */
- G_debug(4, "Found Rk's neighbors");
- for (current = Rkn_head; current != NULL;
- current = current->next)
- G_debug(4, "Rkn: row: %d, col: %d",
- current->row, current->col);
+ /*print out neighbors */
+ G_debug(4, "Found Rk's pixels");
+ for (current = Rk_head; current != NULL;
+ current = current->next)
+ G_debug(4, "Rk: row: %d, col: %d",
+ current->row, current->col);
+ /*print out neighbors */
+ G_debug(4, "Found Rk's neighbors");
+ for (current = Rkn_head; current != NULL;
+ current = current->next)
+ G_debug(4, "Rkn: row: %d, col: %d",
+ current->row, current->col);
#endif
- /* ******** find Rk's most similar neighbor ******** */
- Rk_similarity = Ri_similarity; /*Ri gets first priority - ties won't change anything, so we'll accept Ri and Rk as mutually best neighbors */
- segment_get(&files->bands_seg, (void *)files->bands_val, Rk_head->row, Rk_head->col); /* current segment values */
+ /* ******** find Rk's most similar neighbor ******** */
+ Rk_similarity = Ri_similarity; /*Ri gets first priority - ties won't change anything, so we'll accept Ri and Rk as mutually best neighbors */
+ segment_get(&files->bands_seg, (void *)files->bands_val, Rk_head->row, Rk_head->col); /* current segment values */
- /* check similarity for each of Rk's neighbors */
- for (current = Rkn_head; current != NULL;
- current = current->next) {
- tempsim =
- functions->calculate_similarity
- (Rk_head, current, files, functions);
+ /* check similarity for each of Rk's neighbors */
+ for (current = Rkn_head; current != NULL;
+ current = current->next) {
+ tempsim =
+ functions->calculate_similarity
+ (Rk_head, current, files, functions);
- if (tempsim < Rk_similarity) {
- Rk_similarity = tempsim;
- break; /* exit for Rk's neighbors loop here, we know that Ri and Rk aren't mutually best neighbors */
- }
- } /* have checked all of Rk's neighbors */
+ if (tempsim < Rk_similarity) {
+ Rk_similarity = tempsim;
+ break; /* exit for Rk's neighbors loop here, we know that Ri and Rk aren't mutually best neighbors */
+ }
+ } /* have checked all of Rk's neighbors */
- if (Rk_similarity == Ri_similarity) { /* mutually most similar neighbors */
+ if (Rk_similarity == Ri_similarity) { /* mutually most similar neighbors */
#ifdef PROFILE
- merge_start = clock();
+ merge_start = clock();
#endif
- merge_values(Ri_head, Rk_head, Ri_count,
- Rk_count, files);
+ merge_values(Ri_head, Rk_head, Ri_count,
+ Rk_count, files);
#ifdef PROFILE
- merge_end = clock();
- merge_lap =
- ((double)(merge_end - merge_start)) /
- CLOCKS_PER_SEC;
- merge_accum += merge_lap;
- fprintf(stdout, "merge time: %g\n",
- merge_lap);
+ merge_end = clock();
+ merge_lap =
+ ((double)(merge_end - merge_start)) /
+ CLOCKS_PER_SEC;
+ merge_accum += merge_lap;
+ fprintf(stdout, "merge time: %g\n",
+ merge_lap);
#endif
- endflag = FALSE; /* we've made at least one merge, so want another t iteration */
- }
- else { /* they weren't mutually best neighbors */
- G_debug(4,
- "Ri was not Rk's best neighbor, Ri_sim: %g, Rk_sim, %g",
- Ri_similarity, Rk_similarity);
+ endflag = FALSE; /* we've made at least one merge, so want another t iteration */
+ }
+ else { /* they weren't mutually best neighbors */
+ G_debug(4,
+ "Ri was not Rk's best neighbor, Ri_sim: %g, Rk_sim, %g",
+ Ri_similarity, Rk_similarity);
- /* checked Ri once, didn't find a mutually best neighbor, so remove all members of Ri from candidate pixels for this iteration */
- set_candidate_flag(Ri_head, FALSE, files);
- //~ G_debug(4, "line 247, \t\t\t\tcc = %d",
- //~ files->candidate_count);
+ /* checked Ri once, didn't find a mutually best neighbor, so remove all members of Ri from candidate pixels for this iteration */
+ set_candidate_flag(Ri_head, FALSE, files);
- if (FLAG_GET(files->candidate_flag, Rk_head->row, Rk_head->col) && FLAG_GET(files->seeds_flag, Rk_head->row, Rk_head->col))
- pathflag = TRUE;
- }
- } /* end if (Ri_bestn != NULL && Ri_similarity < threshold) */
- else {
- /* no valid best neighbor for this Ri
- * exclude this Ri from further comparisons
- * because we checked already Ri for a mutually best neighbor with all valid candidates
- * thus Ri can not be the mutually best neighbor later on during this pass
- * unfortunately this does happen sometimes */
- set_candidate_flag(Ri_head, FALSE, files);
- G_debug(4,
- "3b Ri's best neighbor was not valid candidate, or their similarity was > threshold");
+ if (FLAG_GET
+ (files->candidate_flag, Rk_head->row,
+ Rk_head->col) &&
+ FLAG_GET(files->seeds_flag, Rk_head->row,
+ Rk_head->col))
+ pathflag = TRUE;
}
-
- } /* end if(Rin_head != NULL) */
- else { /* Ri didn't have a neighbor */
- G_debug(4, "Segment had no neighbors");
+ } /* end if (Ri_bestn != NULL && Ri_similarity < threshold) */
+ else {
+ /* no valid best neighbor for this Ri
+ * exclude this Ri from further comparisons
+ * because we checked already Ri for a mutually best neighbor with all valid candidates
+ * thus Ri can not be the mutually best neighbor later on during this pass
+ * unfortunately this does happen sometimes */
set_candidate_flag(Ri_head, FALSE, files);
- //~ G_debug(4, "line 176, \t\t\t\tcc = %d",
- //~ files->candidate_count);
+ G_debug(4,
+ "3b Ri's best neighbor was not valid candidate, or their similarity was > threshold");
}
- if (pathflag) { /*initialize Ri, Rin, Rk, Rin using Rk as Ri. */
- /* So for the next iteration, lets start with Rk as the focus segment */
- /* Seems this should be a bit faster, since we already have segment membership pixels */
- /* TODO: this shortened each iteration time by about 10% but increased the number of iterations by 20% ?!?!?!? */
- if (functions->path == TRUE) {
- Ri_count = Rk_count;
- Rk_count = 0;
- my_dispose_list(files->token, &Ri_head);
- Ri_head = Rk_head;
- Rk_head = NULL;
- if (Rkn_head != NULL) {
- my_dispose_list(files->token, &Rin_head);
- Rin_head = Rkn_head;
- Rkn_head = NULL;
- }
- else
- my_dispose_list(files->token, &Rin_head);
+ } /* end if(Rin_head != NULL) */
+ else { /* Ri didn't have a neighbor */
+ G_debug(4, "Segment had no neighbors");
+ set_candidate_flag(Ri_head, FALSE, files);
+ }
+
+ if (pathflag) { /*initialize Ri, Rin, Rk, Rin using Rk as Ri. */
+ /* So for the next iteration, lets start with Rk as the focus segment */
+ /* Seems this should be a bit faster, since we already have segment membership pixels */
+ /* TODO: this shortened each iteration time by about 10% but increased the number of iterations by 20% ?!?!?!? */
+ if (functions->path == TRUE) {
+ Ri_count = Rk_count;
+ Rk_count = 0;
+ my_dispose_list(files->token, &Ri_head);
+ Ri_head = Rk_head;
+ Rk_head = NULL;
+ if (Rkn_head != NULL) {
+ my_dispose_list(files->token, &Rin_head);
+ Rin_head = Rkn_head;
+ Rkn_head = NULL;
}
else
- pathflag = FALSE;
-
+ my_dispose_list(files->token, &Rin_head);
}
+ else
+ pathflag = FALSE;
- } /*end pathflag do loop */
- } /*end if pixel is candidate and seed pixel */
- } /*next column (or next z) */
- #ifdef ROWMAJOR
- } /*next row */
- #endif
+ }
+
+ } /*end pathflag do loop */
+ } /*end if pixel is candidate and seed pixel */
+ } /*next column (or next z) */
+#ifdef ROWMAJOR
+ } /*next row */
+#endif
#ifdef PROFILE
- pass_end = clock();
- fprintf(stdout, "pass %d took: %g\n", t,
- ((double)(pass_end - pass_start)) / CLOCKS_PER_SEC);
+ pass_end = clock();
+ fprintf(stdout, "pass %d took: %g\n", t,
+ ((double)(pass_end - pass_start)) / CLOCKS_PER_SEC);
#endif
- /* finished one iteration over entire raster */
- G_debug(4, "Finished one pass, t was = %d", t);
- t++;
+ /* finished one iteration over entire raster */
+ G_debug(4, "Finished one pass, t was = %d", t);
+ t++;
}
- while (t <= functions->end_t && endflag == FALSE); /*end t loop, either reached max iterations or didn't merge any segments */
+ while (t <= functions->end_t && endflag == FALSE) ; /*end t loop, either reached max iterations or didn't merge any segments */
if (t == 2 && files->bounds_map == NULL)
G_warning(_("No segments were created. Verify threshold and region settings."));
@@ -1321,9 +1316,7 @@
t++; /* to count one more "iteration" */
} /* end if for force merge */
else
- /* todo delete? G_verbose_message(_("Input for minimum pixels in a segment was 1, will not force a merge for small segments.")); */
-
- if (t > 2)
+ if (t > 2)
G_verbose_message("temporary(?) message, number of passes: %d",
t - 1);
#ifdef PROFILE
@@ -1334,269 +1327,335 @@
((double)(end - start) / CLOCKS_PER_SEC));
#endif
return TRUE;
-}
+ }
-int find_segment_neighbors(struct pixels **R_head,
- struct pixels **neighbors_head, int *seg_count,
- struct files *files, struct functions *functions)
-{
- int n, current_seg_ID, R_iseg = -1;
- struct pixels *newpixel, *current, *to_check, tree_pix; /* need to check the pixel neighbors of to_check */
- int pixel_neighbors[8][2];
- struct RB_TREE *no_check_tree; /* pixels that should no longer be checked on this current find_neighbors() run */
- struct RB_TREE *known_iseg;
+ int find_segment_neighbors(struct pixels **R_head,
+ struct pixels **neighbors_head, int *seg_count,
+ struct files *files,
+ struct functions *functions)
+ {
+ int n, current_seg_ID, R_iseg = -1;
+ struct pixels *newpixel, *current, *to_check, tree_pix; /* need to check the pixel neighbors of to_check */
+ int pixel_neighbors[8][2];
+ struct RB_TREE *no_check_tree; /* pixels that should no longer be checked on this current find_neighbors() run */
+ struct RB_TREE *known_iseg;
#ifdef DEBUG
- struct RB_TRAV trav;
+ struct RB_TRAV trav;
#endif
- /* TODO, any time savings to move any variables to files (mem allocation in open_files) */
+ /* TODO, any time savings to move any variables to files (mem allocation in open_files) */
- /* neighbor list will be a listing of pixels that are neighbors? Include segment numbers? Only include unique segments?
- * MM: counting unique neighbor segments could have the advantage of dealing with special
- * segments that have only one neighbor, i.e. segments within segments
- *
+ /* neighbor list will be a listing of pixels that are neighbors? Include segment numbers? Only include unique segments?
+ * MM: counting unique neighbor segments could have the advantage of dealing with special
+ * segments that have only one neighbor, i.e. segments within segments
+ *
- * Maybe the most complete return would be a structure array, structure to include the segment ID and a list of points in it?
- * But the list of points would NOT be inclusive - just the points bordering the current segment...
- */
+ * Maybe the most complete return would be a structure array, structure to include the segment ID and a list of points in it?
+ * But the list of points would NOT be inclusive - just the points bordering the current segment...
+ */
- /* parameter: R, current segment membership, could be single pixel (incomplete list) or list of pixels.
- * parameter: neighbors/Rin/Rik, neighbor pixels, could have a list already, or could be empty ?
- * functions->num_pn int, 4 or 8, for number of pixel neighbors
- * */
+ /* parameter: R, current segment membership, could be single pixel (incomplete list) or list of pixels.
+ * parameter: neighbors/Rin/Rik, neighbor pixels, could have a list already, or could be empty ?
+ * functions->num_pn int, 4 or 8, for number of pixel neighbors
+ * */
- /* *** initialize data *** */
+ /* *** initialize data *** */
- segment_get(&files->iseg_seg, &R_iseg, (*R_head)->row, (*R_head)->col);
+ segment_get(&files->iseg_seg, &R_iseg, (*R_head)->row,
+ (*R_head)->col);
- if (R_iseg == 0)
- R_iseg = -1; /* with seeds, all non-seed pixels are assigned to segment 0. But we don't want to consider the others as part of the same segment. */
+ if (R_iseg == 0) { /* if seeds were provided, this is just a single non-seed pixel, only return neighbors that are segments or seeds */
- no_check_tree = rbtree_create(compare_pixels, sizeof(struct pixels));
- known_iseg = rbtree_create(compare_ids, sizeof(int));
- to_check = NULL;
+ functions->find_pixel_neighbors((*R_head)->row, (*R_head)->col,
+ pixel_neighbors, files);
+ for (n = 0; n < functions->num_pn; n++) {
- /* Copy R in to_check and no_check data structures (don't expand them if we find them again) */
+ /* skip pixel if out of computational area or null */
+ if (pixel_neighbors[n][0] < files->minrow ||
+ pixel_neighbors[n][0] >= files->maxrow ||
+ pixel_neighbors[n][1] < files->mincol ||
+ pixel_neighbors[n][1] >= files->maxcol ||
+ FLAG_GET(files->null_flag, pixel_neighbors[n][0],
+ pixel_neighbors[n][1])
+ )
+ continue;
- for (current = *R_head; current != NULL; current = current->next) {
- /* put in to_check linked list */
- newpixel = (struct pixels *)link_new(files->token);
- newpixel->next = to_check; /*point the new pixel to the current first pixel */
- newpixel->row = current->row;
- newpixel->col = current->col;
- to_check = newpixel; /*change the first pixel to be the new pixel. */
+ segment_get(&files->iseg_seg, ¤t_seg_ID,
+ pixel_neighbors[n][0], pixel_neighbors[n][1]);
- /* put in no_check tree */
- tree_pix.row = current->row;
- tree_pix.col = current->col;
- if (rbtree_insert(no_check_tree, &tree_pix) == 0) /* don't check it again */
- G_warning("could not insert data!?");
- }
+ if (current_seg_ID > 0) {
+ newpixel = (struct pixels *)link_new(files->token);
+ newpixel->next = *neighbors_head; /*point the new pixel to the current first pixel */
+ newpixel->row = pixel_neighbors[n][0];
+ newpixel->col = pixel_neighbors[n][1];
+ *neighbors_head = newpixel; /*change the first pixel to be the new pixel. */
+ /* todo polish... could use a tree and only return pixels from unique segments. */
+ }
+ }
- while (to_check != NULL) { /* removing from to_check list as we go, NOT iterating over the list. */
- G_debug(5,
- "\tfind_pixel_neighbors for row: %d , col %d",
- to_check->row, to_check->col);
+ }
+ else { /*normal processing, look for all adjacent pixels or segments */
+ no_check_tree =
+ rbtree_create(compare_pixels, sizeof(struct pixels));
+ known_iseg = rbtree_create(compare_ids, sizeof(int));
+ to_check = NULL;
- functions->find_pixel_neighbors(to_check->row,
- to_check->col,
- pixel_neighbors, files);
+ /* Copy R in to_check and no_check data structures (don't expand them if we find them again) */
- /* Done using this to_check pixels coords, remove from list */
- current = to_check; /* temporary store the old head */
- to_check = to_check->next; /*head now points to the next element in the list */
- link_dispose(files->token, (VOID_T *) current);
+ for (current = *R_head; current != NULL; current = current->next) {
+ /* put in to_check linked list */
+ newpixel = (struct pixels *)link_new(files->token);
+ newpixel->next = to_check; /*point the new pixel to the current first pixel */
+ newpixel->row = current->row;
+ newpixel->col = current->col;
+ to_check = newpixel; /*change the first pixel to be the new pixel. */
- /*print out to_check */
+ /* put in no_check tree */
+ tree_pix.row = current->row;
+ tree_pix.col = current->col;
+ if (rbtree_insert(no_check_tree, &tree_pix) == 0) /* don't check it again */
+ G_warning("could not insert data!?");
+ }
+
+ while (to_check != NULL) { /* removing from to_check list as we go, NOT iterating over the list. */
+ G_debug(5,
+ "\tfind_pixel_neighbors for row: %d , col %d",
+ to_check->row, to_check->col);
+
+ functions->find_pixel_neighbors(to_check->row,
+ to_check->col,
+ pixel_neighbors, files);
+
+ /* Done using this to_check pixels coords, remove from list */
+ current = to_check; /* temporary store the old head */
+ to_check = to_check->next; /*head now points to the next element in the list */
+ link_dispose(files->token, (VOID_T *) current);
+
+ /*print out to_check */
#ifdef DEBUG
- G_debug(5, "remaining pixel's in to_check, after popping:");
- for (current = to_check; current != NULL; current = current->next)
- G_debug(5, "to_check... row: %d, col: %d", current->row,
- current->col);
- for (current = *neighbors_head; current != NULL;
- current = current->next)
- G_debug(5, "Rn... row: %d, col: %d", current->row, current->col);
+ G_debug(5, "remaining pixel's in to_check, after popping:");
+ for (current = to_check; current != NULL;
+ current = current->next)
+ G_debug(5, "to_check... row: %d, col: %d", current->row,
+ current->col);
+ for (current = *neighbors_head; current != NULL;
+ current = current->next)
+ G_debug(5, "Rn... row: %d, col: %d", current->row,
+ current->col);
#endif
- /*now check the pixel neighbors and add to the lists */
+ /*now check the pixel neighbors and add to the lists */
- /*print what pixel neighbors were found: */
- /* for (n = 0; n < functions->num_pn; n++){
- G_debug(5, "\tpixel_neighbors[n][0]: %d, pixel_neighbors[n][1]: %d", pixel_neighbors[n][0], pixel_neighbors[n][1]);
- } */
+ /*print what pixel neighbors were found: */
+ /* for (n = 0; n < functions->num_pn; n++){
+ G_debug(5, "\tpixel_neighbors[n][0]: %d, pixel_neighbors[n][1]: %d", pixel_neighbors[n][0], pixel_neighbors[n][1]);
+ } */
- /* for each pixel neighbors, check if they should be processed, check segment ID, and add to appropriate lists */
- for (n = 0; n < functions->num_pn; n++) {
+ /* for each pixel neighbors, check if they should be processed, check segment ID, and add to appropriate lists */
+ for (n = 0; n < functions->num_pn; n++) {
- /* skip pixel if out of computational area or null */
- if (pixel_neighbors[n][0] < files->minrow ||
- pixel_neighbors[n][0] >= files->maxrow ||
- pixel_neighbors[n][1] < files->mincol ||
- pixel_neighbors[n][1] >= files->maxcol ||
- FLAG_GET(files->null_flag, pixel_neighbors[n][0],
- pixel_neighbors[n][1])
- )
- continue;
+ /* skip pixel if out of computational area or null */
+ if (pixel_neighbors[n][0] < files->minrow ||
+ pixel_neighbors[n][0] >= files->maxrow ||
+ pixel_neighbors[n][1] < files->mincol ||
+ pixel_neighbors[n][1] >= files->maxcol ||
+ FLAG_GET(files->null_flag, pixel_neighbors[n][0],
+ pixel_neighbors[n][1])
+ )
+ continue;
- tree_pix.row = pixel_neighbors[n][0];
- tree_pix.col = pixel_neighbors[n][1];
- G_debug(5,
- "********* rbtree_find(no_check_tree, &tree_pix) = %p",
- rbtree_find(no_check_tree, &tree_pix));
+ tree_pix.row = pixel_neighbors[n][0];
+ tree_pix.col = pixel_neighbors[n][1];
+ G_debug(5,
+ "********* rbtree_find(no_check_tree, &tree_pix) = %p",
+ rbtree_find(no_check_tree, &tree_pix));
- if (rbtree_find(no_check_tree, &tree_pix) == FALSE) { /* want to check this neighbor */
- segment_get(&files->iseg_seg, ¤t_seg_ID,
- pixel_neighbors[n][0], pixel_neighbors[n][1]);
+ if (rbtree_find(no_check_tree, &tree_pix) == FALSE) { /* want to check this neighbor */
+ segment_get(&files->iseg_seg, ¤t_seg_ID,
+ pixel_neighbors[n][0],
+ pixel_neighbors[n][1]);
- rbtree_insert(no_check_tree, &tree_pix); /* don't check it again */
+ rbtree_insert(no_check_tree, &tree_pix); /* don't check it again */
- //~ G_debug(5, "\tfiles->iseg[][] = %d Ri_seg_ID = %d",
- //~ files->iseg[pixel_neighbors[n][0]]
- //~ [pixel_neighbors[n]
- //~ [1]], Ri_seg_ID);
+ //~ G_debug(5, "\tfiles->iseg[][] = %d Ri_seg_ID = %d",
+ //~ files->iseg[pixel_neighbors[n][0]]
+ //~ [pixel_neighbors[n]
+ //~ [1]], Ri_seg_ID);
- if (current_seg_ID == R_iseg) { /* pixel is member of current segment, add to R */
- G_debug(5, "\tputing pixel_neighbor in Ri");
- /* put pixel_neighbor[n] in Ri */
- newpixel = (struct pixels *)link_new(files->token);
- newpixel->next = *R_head; /*point the new pixel to the current first pixel */
- newpixel->row = pixel_neighbors[n][0];
- newpixel->col = pixel_neighbors[n][1];
- *R_head = newpixel; /*change the first pixel to be the new pixel. */
- *seg_count = *seg_count + 1; /* zero index... Ri[0] had first pixel and set count =1. increment after save data. */
- G_debug(5, "\t*seg_count now = %d", *seg_count);
+ if (current_seg_ID == R_iseg) { /* pixel is member of current segment, add to R */
+ G_debug(5, "\tputing pixel_neighbor in Ri");
+ /* put pixel_neighbor[n] in Ri */
+ newpixel =
+ (struct pixels *)link_new(files->token);
+ newpixel->next = *R_head; /*point the new pixel to the current first pixel */
+ newpixel->row = pixel_neighbors[n][0];
+ newpixel->col = pixel_neighbors[n][1];
+ *R_head = newpixel; /*change the first pixel to be the new pixel. */
+ *seg_count = *seg_count + 1; /* zero index... Ri[0] had first pixel and set count =1. increment after save data. */
+ G_debug(5, "\t*seg_count now = %d", *seg_count);
- /* put pixel_neighbor[n] in to_check -- want to check this pixels neighbors */
- newpixel = (struct pixels *)link_new(files->token);
- newpixel->next = to_check; /*point the new pixel to the current first pixel */
- newpixel->row = pixel_neighbors[n][0];
- newpixel->col = pixel_neighbors[n][1];
- to_check = newpixel; /*change the first pixel to be the new pixel. */
+ /* put pixel_neighbor[n] in to_check -- want to check this pixels neighbors */
+ newpixel =
+ (struct pixels *)link_new(files->token);
+ newpixel->next = to_check; /*point the new pixel to the current first pixel */
+ newpixel->row = pixel_neighbors[n][0];
+ newpixel->col = pixel_neighbors[n][1];
+ to_check = newpixel; /*change the first pixel to be the new pixel. */
- }
- else { /* segment id's were different */
- if (!rbtree_find(known_iseg, ¤t_seg_ID)) { /* we don't have any neighbors yet from this segment */
- if (current_seg_ID != 0)
- /* with seeds, non seed pixels are defaulted to zero. Should we use null instead?? then could skip this check? Or we couldn't insert it??? */
- /* add to known neighbors list */
- rbtree_insert(known_iseg, ¤t_seg_ID); /* todo: could I just try to insert it, if it fails I know it is already there?
- * I guess it would depend on how much faster the find() is, and what fraction of the
- * neighbors are in a duplicate segment... */
+ }
+ else { /* segment id's were different */
+ if (!rbtree_find(known_iseg, ¤t_seg_ID)) { /* we don't have any neighbors yet from this segment */
+ if (current_seg_ID != 0)
+ /* with seeds, non seed pixels are defaulted to zero. Should we use null instead?? then could skip this check? Or we couldn't insert it??? */
+ /* add to known neighbors list */
+ rbtree_insert(known_iseg, ¤t_seg_ID); /* todo: could I just try to insert it, if it fails I know it is already there?
+ * I guess it would depend on how much faster the find() is, and what fraction of the
+ * neighbors are in a duplicate segment... */
- /* put pixel_neighbor[n] in Rin */
- G_debug(5, "Put in neighbors_head");
- newpixel = (struct pixels *)link_new(files->token);
- newpixel->next = *neighbors_head; /*point the new pixel to the current first pixel */
- newpixel->row = pixel_neighbors[n][0];
- newpixel->col = pixel_neighbors[n][1];
- *neighbors_head = newpixel; /*change the first pixel to be the new pixel. */
- }
- }
+ /* put pixel_neighbor[n] in Rin */
+ G_debug(5, "Put in neighbors_head");
+ newpixel =
+ (struct pixels *)link_new(files->token);
+ newpixel->next = *neighbors_head; /*point the new pixel to the current first pixel */
+ newpixel->row = pixel_neighbors[n][0];
+ newpixel->col = pixel_neighbors[n][1];
+ *neighbors_head = newpixel; /*change the first pixel to be the new pixel. */
+ }
+ }
- } /*end if for pixel_neighbor was in "don't check" list */
- } /* end for loop - next pixel neighbor */
+ } /*end if for pixel_neighbor was in "don't check" list */
+ } /* end for loop - next pixel neighbor */
#ifdef DEBUG
- G_debug(5,
- "remaining pixel's in to_check, after processing the last pixel's neighbors:");
- for (current = to_check; current != NULL; current = current->next)
- G_debug(5, "to_check... row: %d, col: %d", current->row,
- current->col);
+ G_debug(5,
+ "remaining pixel's in to_check, after processing the last pixel's neighbors:");
+ for (current = to_check; current != NULL;
+ current = current->next)
+ G_debug(5, "to_check... row: %d, col: %d", current->row,
+ current->col);
- G_debug(5, "\t### end of pixel neighors");
+ G_debug(5, "\t### end of pixel neighors");
#endif
- } /* end while to_check has more elements */
+ } /* end while to_check has more elements */
- /* clean up */
- rbtree_destroy(no_check_tree);
- rbtree_destroy(known_iseg);
+ /* clean up */
+ rbtree_destroy(no_check_tree);
+ rbtree_destroy(known_iseg);
+ }
+ return TRUE;
+ }
- return TRUE;
-}
+ int find_four_pixel_neighbors(int p_row, int p_col,
+ int pixel_neighbors[8][2],
+ struct files *files)
+ {
+ /* Note: this will return neighbors outside of the raster boundary.
+ * Check in the calling routine if the pixel should be processed.
+ */
-int find_four_pixel_neighbors(int p_row, int p_col,
- int pixel_neighbors[8][2], struct files *files)
-{
- /* Note: this will return neighbors outside of the raster boundary.
- * Check in the calling routine if the pixel should be processed.
- */
+ /* north */
+ pixel_neighbors[0][1] = p_col;
+ pixel_neighbors[0][0] = p_row - 1;
- /* north */
- pixel_neighbors[0][1] = p_col;
- pixel_neighbors[0][0] = p_row - 1;
+ /* east */
+ pixel_neighbors[1][0] = p_row;
+ pixel_neighbors[1][1] = p_col + 1;
- /* east */
- pixel_neighbors[1][0] = p_row;
- pixel_neighbors[1][1] = p_col + 1;
+ /* south */
+ pixel_neighbors[2][1] = p_col;
+ pixel_neighbors[2][0] = p_row + 1;
- /* south */
- pixel_neighbors[2][1] = p_col;
- pixel_neighbors[2][0] = p_row + 1;
+ /* west */
+ pixel_neighbors[3][0] = p_row;
+ pixel_neighbors[3][1] = p_col - 1;
- /* west */
- pixel_neighbors[3][0] = p_row;
- pixel_neighbors[3][1] = p_col - 1;
+ return TRUE;
+ }
- return TRUE;
-}
+ int find_eight_pixel_neighbors(int p_row, int p_col,
+ int pixel_neighbors[8][2],
+ struct files *files)
+ {
+ /* get the 4 orthogonal neighbors: */
+ find_four_pixel_neighbors(p_row, p_col, pixel_neighbors, files);
-int find_eight_pixel_neighbors(int p_row, int p_col,
- int pixel_neighbors[8][2], struct files *files)
-{
- /* get the 4 orthogonal neighbors: */
- find_four_pixel_neighbors(p_row, p_col, pixel_neighbors, files);
+ /* and then the diagonals: */
- /* and then the diagonals: */
+ /* north west */
+ pixel_neighbors[4][0] = p_row - 1;
+ pixel_neighbors[4][1] = p_col - 1;
- /* north west */
- pixel_neighbors[4][0] = p_row - 1;
- pixel_neighbors[4][1] = p_col - 1;
+ /* north east */
+ pixel_neighbors[5][0] = p_row - 1;
+ pixel_neighbors[5][1] = p_col + 1;
- /* north east */
- pixel_neighbors[5][0] = p_row - 1;
- pixel_neighbors[5][1] = p_col + 1;
+ /* south east */
+ pixel_neighbors[6][0] = p_row + 1;
+ pixel_neighbors[6][1] = p_col + 1;
- /* south east */
- pixel_neighbors[6][0] = p_row + 1;
- pixel_neighbors[6][1] = p_col + 1;
+ /* south west */
+ pixel_neighbors[7][0] = p_row + 1;
+ pixel_neighbors[7][1] = p_col - 1;
- /* south west */
- pixel_neighbors[7][0] = p_row + 1;
- pixel_neighbors[7][1] = p_col - 1;
+ return TRUE;
+ }
- return TRUE;
-}
-
/* similarity / distance between two points based on their input raster values */
/* assumes first point values already saved in files->bands_seg - only run segment_get once for that value... */
/* TODO: segment_get already happened for a[] values in the main function. Could remove a[] from these parameters */
-double calculate_euclidean_similarity(struct pixels *a, struct pixels *b,
- struct files *files,
- struct functions *functions)
-{
- double val = 0;
- int n;
+ double calculate_euclidean_similarity(struct pixels *a, struct pixels *b,
+ struct files *files,
+ struct functions *functions)
+ {
+ double val = 0;
+ int n;
- /* get values for pixel b */
- segment_get(&files->bands_seg, (void *)files->second_val, b->row, b->col);
+ /* get values for pixel b */
+ segment_get(&files->bands_seg, (void *)files->second_val, b->row,
+ b->col);
- /* euclidean distance, sum the square differences for each dimension */
- for (n = 0; n < files->nbands; n++) {
- val =
- val + (files->bands_val[n] -
- files->second_val[n]) * (files->bands_val[n] -
- files->second_val[n]);
+ /* euclidean distance, sum the square differences for each dimension */
+ for (n = 0; n < files->nbands; n++) {
+ val =
+ val + (files->bands_val[n] -
+ files->second_val[n]) * (files->bands_val[n] -
+ files->second_val[n]);
+ }
+
+ /* val = sqrt(val); *//* use squared distance, save the calculation time. */
+
+ return val;
+
}
- /* val = sqrt(val); *//* use squared distance, save the calculation time. */
+ /* similarity / distance between two points based on their input raster values */
+ /* assumes first point values already saved in files->bands_seg - only run segment_get once for that value... */
+ /* TODO: segment_get already happened for a[] values in the main function. Could remove a[] from these parameters */
+ double calculate_manhattan_similarity(struct pixels *a, struct pixels *b,
+ struct files *files,
+ struct functions *functions)
+ {
+ double val = 0;
+ int n;
- return val;
+ /* get values for pixel b */
+ segment_get(&files->bands_seg, (void *)files->second_val, b->row,
+ b->col);
-}
+ /* euclidean distance, sum the square differences for each dimension */
+ for (n = 0; n < files->nbands; n++) {
+ val += fabs(files->bands_val[n] - files->second_val[n]); /* todo check if fabs is the "fast" way for absolute value */
+ }
+ /* val = sqrt(val); *//* use squared distance, save the calculation time. */
+
+ return val;
+
+ }
+
/*
In the eCognition literature, we find that the key factor in the
multi-scale segmentation algorithm used by Definiens is the scale
@@ -1616,245 +1675,199 @@
object, and Pbbox the perimeter of the bounding box of the object.
*/
-int merge_values(struct pixels *Ri_head, struct pixels *Rk_head,
- int Ri_count, int Rk_count, struct files *files)
-{
- int n, Ri_iseg, Rk_iseg;
- struct pixels *current;
+ int merge_values(struct pixels *Ri_head, struct pixels *Rk_head,
+ int Ri_count, int Rk_count, struct files *files)
+ {
+ int n, Ri_iseg, Rk_iseg;
+ struct pixels *current;
- /*get input values *//*TODO polish, confirm if we can assume we already have bands_val for Ri, so don't need to segment_get() again? note...current very_close implementation requires getting this value again... */
- segment_get(&files->bands_seg, (void *)files->bands_val, Ri_head->row,
- Ri_head->col);
- segment_get(&files->bands_seg, (void *)files->second_val,
- Rk_head->row, Rk_head->col);
+ /*get input values *//*TODO polish, confirm if we can assume we already have bands_val for Ri, so don't need to segment_get() again? note...current very_close implementation requires getting this value again... */
+ segment_get(&files->bands_seg, (void *)files->bands_val, Ri_head->row,
+ Ri_head->col);
+ segment_get(&files->bands_seg, (void *)files->second_val,
+ Rk_head->row, Rk_head->col);
- segment_get(&files->iseg_seg, &Rk_iseg, Rk_head->row, Rk_head->col);
- segment_get(&files->iseg_seg, &Ri_iseg, Ri_head->row, Ri_head->col);
- /* todo polish, maybe we have some of these values already? Or they should be stored in files structure? */
+ segment_get(&files->iseg_seg, &Rk_iseg, Rk_head->row, Rk_head->col);
+ segment_get(&files->iseg_seg, &Ri_iseg, Ri_head->row, Ri_head->col);
+ /* todo polish, maybe we have some of these values already? Or they should be stored in files structure? */
- for (n = 0; n < files->nbands; n++) {
- files->bands_val[n] =
- (files->bands_val[n] * Ri_count +
- files->second_val[n] * Rk_count) / (Ri_count + Rk_count);
- }
+ for (n = 0; n < files->nbands; n++) {
+ files->bands_val[n] =
+ (files->bands_val[n] * Ri_count +
+ files->second_val[n] * Rk_count) / (Ri_count + Rk_count);
+ }
- /* update segment number and candidate flag ==0 */
+ /* update segment number and candidate flag ==0 */
- //~ G_debug(4, "\t\tMerging, segment number: %d, including pixels:",
- //~ files->iseg[Ri_head->row][Ri_head->col]);
+ //~ G_debug(4, "\t\tMerging, segment number: %d, including pixels:",
+ //~ files->iseg[Ri_head->row][Ri_head->col]);
- fprintf(stdout,
- "merging Ri (pixel count): %d (%d) with Rk (count): %d (%d).\n",
- Ri_iseg, Ri_count, Rk_iseg, Rk_count);
+ fprintf(stdout,
+ "merging Ri (pixel count): %d (%d) with Rk (count): %d (%d).\n",
+ Ri_iseg, Ri_count, Rk_iseg, Rk_count);
- /* for each member of Ri and Rk, write new average bands values and segment values */
- for (current = Ri_head; current != NULL; current = current->next) {
- segment_put(&files->bands_seg, (void *)files->bands_val,
- current->row, current->col);
- FLAG_UNSET(files->candidate_flag, current->row, current->col); /*candidate pixel flag, only one merge allowed per t iteration */
- //~ files->candidate_count--;
- //~ G_debug(4, "line 508, \t\t\t\tcc = %d", files->candidate_count);
- G_debug(4, "\t\tRi row: %d, col: %d", current->row, current->col);
- }
- for (current = Rk_head; current != NULL; current = current->next) {
- segment_put(&files->bands_seg, (void *)files->bands_val,
- current->row, current->col);
- segment_put(&files->iseg_seg, &Ri_iseg, current->row, current->col);
- FLAG_UNSET(files->candidate_flag, current->row, current->col);
- //~ files->candidate_count--;
- //~ G_debug(4, "line 516, \t\t\t\tcc = %d", files->candidate_count);
- G_debug(4, "\t\tRk row: %d, col: %d", current->row, current->col);
+ /* for each member of Ri and Rk, write new average bands values and segment values */
+ for (current = Ri_head; current != NULL; current = current->next) {
+ segment_put(&files->bands_seg, (void *)files->bands_val,
+ current->row, current->col);
+ FLAG_UNSET(files->candidate_flag, current->row, current->col); /*candidate pixel flag, only one merge allowed per t iteration */
+ G_debug(4, "\t\tRi row: %d, col: %d", current->row, current->col);
+ }
+ for (current = Rk_head; current != NULL; current = current->next) {
+ segment_put(&files->bands_seg, (void *)files->bands_val,
+ current->row, current->col);
+ segment_put(&files->iseg_seg, &Ri_iseg, current->row,
+ current->col);
+ FLAG_UNSET(files->candidate_flag, current->row, current->col);
+ G_debug(4, "\t\tRk row: %d, col: %d", current->row, current->col);
- }
+ }
- /* merged two segments, decrement count if Rk was an actual segment (not a non-seed pixel) */
- if (Rk_iseg > 0)
- files->nsegs--;
+ /* merged two segments, decrement count if Rk was an actual segment (not a non-seed pixel) */
+ if (Rk_iseg > 0)
+ files->nsegs--;
-
- //~ if (files->seeds_map != NULL) //todo delete??? or is it even correct?
- //~ files->candidate_count += Ri_count + Rk_count - 1;
+ return TRUE;
+ }
- return TRUE;
-}
+ /* calculates and stores the mean value for all pixels in a list, assuming they are all in the same segment */
+ int merge_pixels(struct pixels *R_head, struct files *files)
+ {
+ int n, count = 0;
+ struct pixels *current;
-/* calculates and stores the mean value for all pixels in a list, assuming they are all in the same segment */
-int merge_pixels(struct pixels *R_head, struct files *files)
-{
- int n, count = 0;
- struct pixels *current;
+ /* Note: using files->bands_val for current pixel values, and files->second_val for the accumulated value */
- /* Note: using files->bands_val for current pixel values, and files->second_val for the accumulated value */
-
/* initialize second_val */
for (n = 0; n < files->nbands; n++) {
- files->second_val[n] = 0;
- }
+ files->second_val[n] = 0;
+ }
if (R_head->next != NULL) {
- /* total up bands values for all pixels */
- for (current = R_head; current != NULL; current = current->next) {
- segment_get(&files->bands_seg, (void *)files->bands_val, current->row,
- current->col);
+ /* total up bands values for all pixels */
+ for (current = R_head; current != NULL; current = current->next) {
+ segment_get(&files->bands_seg, (void *)files->bands_val,
+ current->row, current->col);
for (n = 0; n < files->nbands; n++) {
- files->second_val[n] += files->bands_val[n];
+ files->second_val[n] += files->bands_val[n];
}
- count ++;
- }
-
- /* calculate the mean */
- for (n = 0; n < files->nbands; n++) {
- files->second_val[n] = files->second_val[n] / count;
- }
+ count++;
+ }
- /* save the results */
- for (current = R_head; current != NULL; current = current->next) {
+ /* calculate the mean */
+ for (n = 0; n < files->nbands; n++) {
+ files->second_val[n] = files->second_val[n] / count;
+ }
+
+ /* save the results */
+ for (current = R_head; current != NULL; current = current->next) {
segment_put(&files->bands_seg, (void *)files->second_val,
- current->row, current->col);
- }
+ current->row, current->col);
+ }
}
- return TRUE;
-}
+ return TRUE;
+ }
/* besides setting flag, also increments how many pixels remain to be processed */
-int set_candidate_flag(struct pixels *head, int value, struct files *files)
-{
- /* head is linked list of pixels, value is new value of flag */
- struct pixels *current;
+ int set_candidate_flag(struct pixels *head, int value,
+ struct files *files)
+ {
+ /* head is linked list of pixels, value is new value of flag */
+ struct pixels *current;
- for (current = head; current != NULL; current = current->next) {
+ for (current = head; current != NULL; current = current->next) {
- if (value == FALSE) {
- FLAG_UNSET(files->candidate_flag, current->row, current->col);
- //~ files->candidate_count--;
+ if (value == FALSE) {
+ FLAG_UNSET(files->candidate_flag, current->row, current->col);
+ }
+ else if (value == TRUE) {
+ FLAG_SET(files->candidate_flag, current->row, current->col);
+ }
+ else
+ G_fatal_error
+ ("programming bug, helper function called with invalid argument");
}
- else if (value == TRUE) {
- FLAG_SET(files->candidate_flag, current->row, current->col);
- //~ files->candidate_count++;
- }
- else
- G_fatal_error
- ("programming bug, helper function called with invalid argument");
-
- //~ G_debug(4, "line 1253, \t\t\t\tcc = %d", files->candidate_count);
+ return TRUE;
}
- return TRUE;
-}
/* let memory manager know space is available again and reset head to NULL */
-int my_dispose_list(struct link_head *token, struct pixels **head)
-{
- struct pixels *current;
+ int my_dispose_list(struct link_head *token, struct pixels **head)
+ {
+ struct pixels *current;
- while ((*head) != NULL) {
- current = *head; /* remember "old" head */
- *head = (*head)->next; /* move head to next pixel */
- link_dispose(token, (VOID_T *) current); /* remove "old" head */
+ while ((*head) != NULL) {
+ current = *head; /* remember "old" head */
+ *head = (*head)->next; /* move head to next pixel */
+ link_dispose(token, (VOID_T *) current); /* remove "old" head */
+ }
+
+ return TRUE;
}
- return TRUE;
-}
-
/* functions used by binary tree to compare items */
/* TODO "static" was used in break_polygons.c extern was suggested in docs. */
-int compare_ids(const void *first, const void *second)
-{
- int *a = (int *)first, *b = (int *)second;
+ int compare_ids(const void *first, const void *second)
+ {
+ int *a = (int *)first, *b = (int *)second;
- if (*a < *b)
- return -1;
- else if (*a > *b)
- return 1;
- else if (*a == *b)
- return 0;
+ if (*a < *b)
+ return -1;
+ else if (*a > *b)
+ return 1;
+ else if (*a == *b)
+ return 0;
- G_warning(_("find neighbors: Bug in binary tree!"));
- return 1;
+ G_warning(_("find neighbors: Bug in binary tree!"));
+ return 1;
-}
+ }
-int compare_pixels(const void *first, const void *second)
-{
- struct pixels *a = (struct pixels *)first, *b = (struct pixels *)second;
+ int compare_pixels(const void *first, const void *second)
+ {
+ struct pixels *a = (struct pixels *)first, *b =
+ (struct pixels *)second;
- if (a->row < b->row)
- return -1;
- else if (a->row > b->row)
- return 1;
- else {
- /* same row */
- if (a->col < b->col)
+ if (a->row < b->row)
return -1;
- else if (a->col > b->col)
+ else if (a->row > b->row)
return 1;
+ else {
+ /* same row */
+ if (a->col < b->col)
+ return -1;
+ else if (a->col > b->col)
+ return 1;
+ }
+ /* same row and col */
+ return 0;
}
- /* same row and col */
- return 0;
-}
/* Set candidate flag to true/1 or false/0 for all pixels in current processing area
* checks for NULL flag and if it is in current "polygon" if a bounds map is given
* checks if seeds were given */
-int set_all_candidate_flags(struct files *files)
-{
- int row, col;
+ int set_all_candidate_flags(struct files *files)
+ {
+ int row, col;
- //~ if (files->seeds_map == NULL) { /* entire map is considered as candidates */ //todo OK? updated meanings of seeds/candidates
- //G_message("No seeds map, setting all pixels to be candidates");
- //~ if (files->bounds_map == NULL) { /* process entire raster */
for (row = files->minrow; row < files->maxrow; row++) {
for (col = files->mincol; col < files->maxcol; col++) {
- /* TODO: if we are starting from seeds...and only allow merges between unassigned pixels
- * and seeds/existing segments, then this needs an if (and will be very inefficient)
- * maybe consider the sorted array, btree, map... but the number of seeds could still be high for a large map */
- /* MM: could be solved/not necessary if all pixels of an existing segment have the same ID */
if (!(FLAG_GET(files->null_flag, row, col))) {
FLAG_SET(files->candidate_flag, row, col);
- //~ files->candidate_count++;
}
else
FLAG_UNSET(files->candidate_flag, row, col);
}
}
- //~ }
- //~ else { /* process part of the raster, polygon constraints/boundaries */
- //~ for (row = files->minrow; row < files->maxrow; row++) {
- //~ for (col = files->mincol; col < files->maxcol; col++) {
- //~ if (!(FLAG_GET(files->in_bounds_flag, row, col))) {
- //~ FLAG_SET(files->candidate_flag, row, col);
- //~ files->candidate_count++;
- //~ }
- //~ else
- //~ FLAG_UNSET(files->candidate_flag, row, col);
- //~ }
- //~ }
- //~ }
- //~ }
- //~ else { /* seeds were provided */
- //~ //G_message("seeds provided, just setting those pixels as candidates");
- //~ for (row = files->minrow; row < files->maxrow; row++) {
- //~ for (col = files->mincol; col < files->maxcol; col++) {
- //~ if ((FLAG_GET(files->seeds_flag, row, col))) {
- //~ FLAG_SET(files->candidate_flag, row, col);
- //~ files->candidate_count++; //TODO, how deal with this...
- //~ }
- //~ else
- //~ FLAG_UNSET(files->candidate_flag, row, col); //todo maybe can skip this...
- //~ }
- //~ }
- //~ }
+ return TRUE;
+ }
- return TRUE;
-}
-
-
/* TODO polish: helper functions:
*
* starting a list
@@ -1862,20 +1875,20 @@
* */
#ifdef NODEF
-G_message("2b, Found Ri's pixels");
+ G_message("2b, Found Ri's pixels");
/*print out neighbors */
-for (current = Ri_head; current != NULL; current = current->next)
- G_message("Ri: row: %d, col: %d", current->row, current->col);
-G_message("2b, Found Ri's neighbors");
+ for (current = Ri_head; current != NULL; current = current->next)
+ G_message("Ri: row: %d, col: %d", current->row, current->col);
+ G_message("2b, Found Ri's neighbors");
/*print out neighbors */
-for (current = Rin_head; current != NULL; current = current->next)
- G_message("Rin: row: %d, col: %d", current->row, current->col);
-G_message("Found Rk's pixels");
+ for (current = Rin_head; current != NULL; current = current->next)
+ G_message("Rin: row: %d, col: %d", current->row, current->col);
+ G_message("Found Rk's pixels");
/*print out neighbors */
-for (current = Rk_head; current != NULL; current = current->next)
- G_message("Rk: row: %d, col: %d", current->row, current->col);
-G_message("Found Rk's neighbors");
+ for (current = Rk_head; current != NULL; current = current->next)
+ G_message("Rk: row: %d, col: %d", current->row, current->col);
+ G_message("Found Rk's neighbors");
/*print out neighbors */
-for (current = Rkn_head; current != NULL; current = current->next)
- G_message("Rkn: row: %d, col: %d", current->row, current->col);
+ for (current = Rkn_head; current != NULL; current = current->next)
+ G_message("Rkn: row: %d, col: %d", current->row, current->col);
#endif
Modified: grass-addons/grass7/imagery/i.segment/iseg.h
===================================================================
--- grass-addons/grass7/imagery/i.segment/iseg.h 2012-08-03 23:55:50 UTC (rev 52513)
+++ grass-addons/grass7/imagery/i.segment/iseg.h 2012-08-04 00:13:53 UTC (rev 52514)
@@ -68,9 +68,6 @@
/* memory management, linked lists */
struct link_head *token; /* for linkm.h linked list memory management. */
- //~ /* other info */
- //~ int candidate_count; /*Number of remaining candidate pixels */
-
};
struct functions
@@ -124,6 +121,8 @@
int find_eight_pixel_neighbors(int, int, int[8][2], struct files *);
double calculate_euclidean_similarity(struct pixels *, struct pixels *,
struct files *, struct functions *);
+double calculate_manhattan_similarity(struct pixels *, struct pixels *,
+ struct files *, struct functions *);
int my_dispose_list(struct link_head *, struct pixels **);
int compare_ids(const void *, const void *);
int compare_pixels(const void *, const void *);
Modified: grass-addons/grass7/imagery/i.segment/open_files.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/open_files.c 2012-08-03 23:55:50 UTC (rev 52513)
+++ grass-addons/grass7/imagery/i.segment/open_files.c 2012-08-04 00:13:53 UTC (rev 52514)
@@ -14,16 +14,18 @@
int n, s, row, col, srows, scols, inlen, nseg;
DCELL **inbuf; /* buffer array, to store lines from each of the imagery group rasters */
CELL *boundsbuf;
- void *seedsbuf, *ptr; /* todo. correct data type when allowing any data type? */
+ void *seedsbuf, *ptr; /* todo. correct data type when allowing any data type? hmm, since have changed logic, seeds must be CELL. Could update code. */
size_t ptrsize;
RASTER_MAP_TYPE data_type;
struct FPRange *fp_range; /* for getting min/max values on each input raster */
DCELL *min, *max;
- /* for merging seed values */
- struct pixels *R_head, *Rn_head, *newpixel;
- int R_count;
+ /* for merging seed values */
+ struct pixels *R_head, *Rn_head, *newpixel, *current;
+ int R_count;
+ G_verbose_message("Opening files and initializing");
+
/* confirm output maps can be opened (don't want to do all this work for nothing!) */
out_fd = Rast_open_new(files->out_name, CELL_TYPE);
if (out_fd < 0)
@@ -45,7 +47,7 @@
if (files->bounds_map != NULL)
files->orig_null_flag = flag_create(files->nrows, files->ncols);
//if (files->seeds_map != NULL)
- files->seeds_flag = flag_create(files->nrows, files->ncols);
+ files->seeds_flag = flag_create(files->nrows, files->ncols);
/* references for segmentation library: i.cost r.watershed/seg and http://grass.osgeo.org/programming7/segmentlib.html */
@@ -142,11 +144,38 @@
G_fatal_error(_("Unable to allocate memory for initial segment ID's"));
/* NOTE: SEGMENT file should be initialized to zeros for all data. TODO double check this. */
+ /* bounds/constraints (start here to get any possible NULL values) */
+ if (files->bounds_map != NULL) {
+ if (segment_open
+ (&files->bounds_seg, G_tempfile(), files->nrows, files->ncols,
+ srows, scols, sizeof(int), nseg) != TRUE)
+ G_fatal_error("Unable to create bounds temporary files");
+
+ boundsbuf = Rast_allocate_c_buf();
+ bounds_fd = Rast_open_old(files->bounds_map, files->bounds_mapset);
+
+ for (row = 0; row < files->nrows; row++) {
+ Rast_get_c_row(bounds_fd, boundsbuf, row);
+ for (col = 0; col < files->ncols; col++) {
+ files->bounds_val = boundsbuf[col];
+ segment_put(&files->bounds_seg, &files->bounds_val, row, col);
+ if (Rast_is_c_null_value(&boundsbuf[col]) == TRUE) {
+ FLAG_SET(files->null_flag, row, col);
+ }
+ }
+ }
+ Rast_close(bounds_fd);
+ G_free(boundsbuf);
+ } /* end bounds/constraints opening */
+
+
/* ******** load input bands to segment structure and fill initial seg ID's ******** */
G_debug(1, "Reading input rasters into segmentation data files...");
s = 0; /* initial segment ID will be 1 */
for (row = 0; row < files->nrows; row++) {
+
+ /* read in rows of data (each input band from the imagery group and the optional seeds map) */
for (n = 0; n < Ref.nfiles; n++) {
Rast_get_d_row(in_fd[n], inbuf[n], row);
}
@@ -154,7 +183,10 @@
Rast_get_row(seeds_fd, seedsbuf, row, data_type);
ptr = seedsbuf;
}
+
for (col = 0; col < files->ncols; col++) {
+ if (FLAG_GET(files->null_flag, row, col))
+ continue;
null_check = 1; /*Assume there is data */
for (n = 0; n < Ref.nfiles; n++) {
if (Rast_is_d_null_value(&inbuf[n][col]))
@@ -169,31 +201,21 @@
if (null_check != -1) { /*good pixel */
FLAG_UNSET(files->null_flag, row, col); /*flag */
if (files->seeds_map != NULL) {
- //G_message("Rast_is_null_value(&seedsbuf[col], data_type) = %d", Rast_is_null_value(&seedsbuf[col], data_type));
- // if (Rast_is_null_value(&seedsbuf[col], data_type) == TRUE) //switched to ptr navigation... maybe I could have done &(seedsbuf[col]) ??
-
- if (Rast_is_null_value(ptr, data_type) == TRUE) { /* TODO, compiler warnings:
- * open_files.c:182:37: warning: dereferencing ‘void *’ pointer [enabled by default]
- * open_files.c:182:27: warning: taking address of expression of type ‘void’ [enabled by default] */
- // not needed, initialized to zero. files->iseg[row][col] = 0; /* place holder... todo, Markus, is this OK to leave out? Or better to set it, since this is just done once... */
+ if (Rast_is_null_value(ptr, data_type) == TRUE) {
+ // not needed, initialized to zero. files->iseg[row][col] = 0; /* place holder... todo, Markus, is this OK to leave out? Or safer to set it, since this is just done once... */
FLAG_UNSET(files->seeds_flag, row, col); //todo shouldn't need to this, flag is initialized to zero?
}
else {
-// s++; /* sequentially number each seed pixel with its own segment ID */
-
FLAG_SET(files->seeds_flag, row, col); //todo might not need this... just look for seg ID > 0 ? If go this route, need to enforce constraints are positive integers.
-// segment_put(&files->iseg_seg, &s, row, col);
/* seed value is starting segment ID. TODO document: seeds must be positive integers, and will be assigned as starting segment IDs. */
- segment_put(&files->iseg_seg, ptr, row, col); //can I just use ptr as the address with the value I want to store? TODO enforce that seeds map is an integer.
-// G_message("set seed for row: %d, col: %d", row, col);
-
+ segment_put(&files->iseg_seg, ptr, row, col); //can I just use ptr as the address with the value I want to store? TODO enforce that seeds map is an integer.
}
ptr = G_incr_void_ptr(ptr, ptrsize);
}
else { /* no seeds provided */
s++; /* sequentially number all pixels with their own segment ID */
segment_put(&files->iseg_seg, &s, row, col); /*starting segment number */
- FLAG_SET(files->seeds_flag, row, col); /*all pixels are seeds */
+ FLAG_SET(files->seeds_flag, row, col); /*all pixels are seeds */
}
}
else { /*don't use this pixel */
@@ -204,41 +226,10 @@
}
}
- /* number of initial segments, will decrement when merge */
- if (files->seeds_map == NULL)
- files->nsegs = s;
- else
- {
- /* TODO: Markus, is there an easy GRASS function to count the unique values in the seeds map???
- * or count during the processing? */
- }
-
- /* bounds/constraints */
+ /* keep original copy of null flag if we have boundary constraints */
if (files->bounds_map != NULL) {
- if (segment_open
- (&files->bounds_seg, G_tempfile(), files->nrows, files->ncols,
- srows, scols, sizeof(int), nseg) != TRUE)
- G_fatal_error("Unable to create bounds temporary files");
-
- boundsbuf = Rast_allocate_c_buf();
- bounds_fd = Rast_open_old(files->bounds_map, files->bounds_mapset);
-
for (row = 0; row < files->nrows; row++) {
- Rast_get_c_row(bounds_fd, boundsbuf, row);
for (col = 0; col < files->ncols; col++) {
- files->bounds_val = boundsbuf[col];
- segment_put(&files->bounds_seg, &files->bounds_val, row, col);
- if (Rast_is_c_null_value(&boundsbuf[col]) == TRUE) {
- FLAG_SET(files->null_flag, row, col);
- }
- }
- }
- Rast_close(bounds_fd);
- G_free(boundsbuf);
-
- /* keep original copy of null flag if we have boundary constraints */
- for (row = 0; row < files->nrows; row++) {
- for (col = 0; col < files->ncols; col++) {
if (FLAG_GET(files->null_flag, row, col))
FLAG_SET(files->orig_null_flag, row, col);
else /* todo polish, flags are initialized to zero... could just skip this else? */
@@ -250,55 +241,68 @@
G_debug(1, "no boundary constraint supplied.");
}
- //~ /* other info */
- //~ files->candidate_count = 0; /* counter for remaining candidate pixels */
-
- /* translate seeds to unique segments TODO MM mentioned it here... */
- /* todo decide if we need to take the seeds value, and use it to start the segments... or if each pixel starts a unique segment. */
-
/* linked list memory management linkm */
- link_set_chunk_size(100); /* TODO polish: fine tune this number */
+ link_set_chunk_size(1000); /* TODO polish: fine tune this number */
files->token = link_init(sizeof(struct pixels));
- /* if we have seeds that are segments (not pixels) we need to update the bands_seg */
- if(files->seeds_map != NULL){
+ /* if we have seeds that are segments (not pixels) we need to update the bands_seg */
+ /* also renumber the segment ID's in case they were classified (duplicating numbers) instead of output from i.segment. */
+ if (files->seeds_map != NULL) {
- /*initialization*/
+ /*initialization */
files->minrow = files->mincol = 0;
files->maxrow = files->nrows;
files->maxcol = files->ncols;
- R_count=1;
- R_head=NULL;
- Rn_head=NULL;
- newpixel=NULL;
+ R_count = 1;
+ R_head = NULL;
+ Rn_head = NULL;
+ newpixel = NULL;
+ current = NULL;
set_all_candidate_flags(files);
for (row = 0; row < files->nrows; row++) {
- for (col = 0; col < files->ncols; col++) {
- if(!(FLAG_GET(files->candidate_flag, row, col)) || FLAG_GET(files->null_flag, row, col)) continue;
- /*start R_head*/
+ G_percent(row, files->nrows, 1); /* I think this is the longest part of open_files() - not entirely accurate for the actual %, but will give the user something to see. */
+ for (col = 0; col < files->ncols; col++) {
+ if (!(FLAG_GET(files->candidate_flag, row, col)) ||
+ FLAG_GET(files->null_flag, row, col))
+ continue;
+ /*start R_head */
newpixel = (struct pixels *)link_new(files->token);
newpixel->next = NULL;
newpixel->row = row;
newpixel->col = col;
R_head = newpixel;
- /*get pixel list, todo polish, could use custom (shorter) function, not using all of what fsn() does...*/
- find_segment_neighbors(&R_head, &Rn_head, &R_count, files, functions);
-
- /*merge pixels*/
+ /*get pixel list, todo polish, could use custom (shorter) function, not using all of what fsn() does... */
+ find_segment_neighbors(&R_head, &Rn_head, &R_count, files, functions); /* todo, I suppose there is a small chance that a renumbered segment matches and borders an original segment. This would be a good reason to write a custom fnp() function to chop out the neighbors and also check the candidate flag. */
+
+ /* update the segment ID *//* TODO, Markus, this could also be done in merge_pixels to avoid iterating this list twice.
+ * for now I've put it here, to make merge_pixels() more general. Unless you think initialization speed is more important then future flexibility? */
+
+ s++;
+ for (current = R_head; current != NULL;
+ current = current->next) {
+ segment_put(&files->iseg_seg, &s, current->row,
+ current->col);
+ FLAG_UNSET(files->candidate_flag, current->row,
+ current->col);
+ }
+
+ /*merge pixels (updates the bands_seg) */
merge_pixels(R_head, files);
-
- /*todo calculate perimeter (?and area?) here?*/
-
- /*clean up*/
+
+ /*todo calculate perimeter (?and area?) here? */
+
+ /*clean up */
my_dispose_list(files->token, &R_head);
my_dispose_list(files->token, &Rn_head);
- R_count=1;
+ R_count = 1;
+ }
}
- }
- }
+ }
+ files->nsegs = s;
+
/* Free memory */
for (n = 0; n < Ref.nfiles; n++) {
Modified: grass-addons/grass7/imagery/i.segment/parse_args.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/parse_args.c 2012-08-03 23:55:50 UTC (rev 52513)
+++ grass-addons/grass7/imagery/i.segment/parse_args.c 2012-08-04 00:13:53 UTC (rev 52514)
@@ -12,7 +12,7 @@
{
/* reference: http://grass.osgeo.org/programming7/gislib.html#Command_Line_Parsing */
- struct Option *group, *seeds, *bounds, *output, *method, *threshold, *min_segment_size, *endt; /* Establish an Option pointer for each option */
+ struct Option *group, *seeds, *bounds, *output, *method, *similarity, *threshold, *min_segment_size, *endt; /* Establish an Option pointer for each option */
struct Flag *diagonal, *weighted, *path, *limited; /* Establish a Flag pointer for each option */
struct Option *outband; /* TODO scrub: put all outband code inside of #ifdef DEBUG */
@@ -42,6 +42,14 @@
#endif
method->description = _("Segmentation method.");
+ similarity = G_define_option();
+ similarity->key = "similarity";
+ similarity->type = TYPE_STRING;
+ similarity->required = YES;
+ similarity->answer = "euclidean";
+ similarity->options = "euclidean, manhattan";
+ similarity->description = _("Distance calculation method.");
+
min_segment_size = G_define_option();
min_segment_size->key = "minsize";
min_segment_size->type = TYPE_INTEGER;
@@ -85,8 +93,6 @@
bounds->description =
_("Optional bounding/constraining raster map, must be integer values, each area will be segmented independent of the others.");
- /* TODO input for distance function */
-
/* debug parameters */
endt = G_define_option();
endt->key = "endt";
@@ -152,6 +158,14 @@
G_debug(1, "segmentation method: %d", functions->method);
+ /* distance methods for similarity measurement */
+ if (strncmp(similarity->answer, "euclidean", 5) == 0)
+ functions->calculate_similarity = &calculate_euclidean_similarity;
+ else if (strncmp(similarity->answer, "manhattan", 5) == 0)
+ functions->calculate_similarity = &calculate_manhattan_similarity;
+ else
+ G_fatal_error("Couldn't assign similarity method."); /*shouldn't be able to get here */
+
//~ functions->very_close = atof(very_close->answer);
functions->min_segment_size = atoi(min_segment_size->answer);
@@ -169,9 +183,6 @@
/* TODO polish, check if function pointer or IF statement is faster */
files->weighted = weighted->answer; /* default/0 for performing the scaling, but selected/1 if user has weighted values so scaling should be skipped. */
-
- functions->calculate_similarity = &calculate_euclidean_similarity; /* TODO add user input for this */
-
if (seeds->answer == NULL) { /* no starting seeds, will use all pixels as seeds */
files->seeds_map = NULL;
}
@@ -181,11 +192,9 @@
G_find_raster2(files->seeds_map, "")) == NULL) {
G_fatal_error(_("Starting seeds map not found."));
}
- //~ if (Rast_map_type(files->seeds_map, files->seeds_mapset) !=
- //~ CELL_TYPE) {
- //~ G_fatal_error(_("Starting seeds map must be CELL type (integers)"));
- //~ } //todo: don't need this check, want it for polygon constraints, but for seeds we are just looking for null vs. not null
- // hmm, actually will need to do that, use seeds value as starting segment ID
+ if (Rast_map_type(files->seeds_map, files->seeds_mapset) != CELL_TYPE) {
+ G_fatal_error(_("Starting seeds map must be CELL type (integers)"));
+ }
}
if (bounds->answer == NULL) { /*no polygon constraints */
Modified: grass-addons/grass7/imagery/i.segment/write_output.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/write_output.c 2012-08-03 23:55:50 UTC (rev 52513)
+++ grass-addons/grass7/imagery/i.segment/write_output.c 2012-08-04 00:13:53 UTC (rev 52514)
@@ -18,7 +18,7 @@
CELL *outbuf;
DCELL *meanbuf;
struct Colors colors;
- struct History history;
+ struct History history;
outbuf = Rast_allocate_c_buf(); /* hold one row of data to put into raster */
@@ -63,12 +63,12 @@
Rast_make_random_colors(&colors, 1, files->nrows * files->ncols); /* TODO polish - number segments from 1 - max ? and then can use that max here. */
Rast_write_colors(files->out_name, G_mapset(), &colors);
- /* add command line to history */
- /* todo polish, any other information that would be interesting? Number of passes? Number of segments made? */
- /* see i.pca as an example of setting custom info */
- Rast_short_history(files->out_name, "raster", &history);
- Rast_command_history(&history);
- Rast_write_history(files->out_name, &history);
+ /* add command line to history */
+ /* todo polish, any other information that would be interesting? Number of passes? Number of segments made? */
+ /* see i.pca as an example of setting custom info */
+ Rast_short_history(files->out_name, "raster", &history);
+ Rast_command_history(&history);
+ Rast_write_history(files->out_name, &history);
/* free memory */
G_free(outbuf);
More information about the grass-commit
mailing list