[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, &current_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, &current_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, &current_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, &current_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, &current_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, &current_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, &current_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