[GRASS-SVN] r52352 - grass-addons/grass7/imagery/i.segment

svn_grass at osgeo.org svn_grass at osgeo.org
Sun Jul 8 21:13:56 PDT 2012


Author: momsen
Date: 2012-07-08 21:13:55 -0700 (Sun, 08 Jul 2012)
New Revision: 52352

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/times.txt
   grass-addons/grass7/imagery/i.segment/write_output.c
Log:
changed the find neighbor no_check flag from raster wide array to a tree.

Modified: grass-addons/grass7/imagery/i.segment/create_isegs.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/create_isegs.c	2012-07-08 13:49:31 UTC (rev 52351)
+++ grass-addons/grass7/imagery/i.segment/create_isegs.c	2012-07-09 04:13:55 UTC (rev 52352)
@@ -3,8 +3,6 @@
 /* Currently only region growing is implemented */
 
 #include <stdlib.h>
-#include <float.h>		/* to get value of LDBL_MAX -> change this if there is a more usual grass way */
-																				  /* #include <math.h>    *//* for sqrt() and pow() */
 #include <grass/gis.h>
 #include <grass/glocale.h>
 #include <grass/raster.h>
@@ -15,7 +13,6 @@
 
 #ifdef DEBUG
 	#include <time.h>
-	#include <stdbool.h> /* TODO decide if _bool is needed for FLAGs */
 #endif
 
 #define LINKM
@@ -294,13 +291,14 @@
 
 int seg_speed_test(struct files *files, struct functions *functions)
 {
-	int i, j, n, max;
+	int i, j, k, n, max;
 	clock_t start, end;
     double temp, cpu_time_used;
     int (*get) (struct files *, int, int); /* files, row, col */
-	struct RB_TREE *no_check_tree; 
+	struct RB_TREE *no_check_tree, *known_iseg_tree; 
 	struct RB_TRAV trav;
-	struct pixels *to_check, *newpixel, *current;
+	struct pixels *to_check, *newpixel, *current, *tree_pix;
+	FLAG *check_flag;
 	G_message("checking speed of RAM vs SEG vs get function performance");
 	
 	G_message("Access in the same region, so shouldn't have any disk I/O");
@@ -350,7 +348,6 @@
 	G_message("to check storage requirements... system dependent... :");
 	G_message("unsigned char: %lu", sizeof(unsigned char));
 	G_message("unsigned char pointer: %lu", sizeof(unsigned char *));
-	G_message("_Bool: %lu", sizeof(_Bool));
 	G_message("int: %lu", sizeof(int));
 	G_message("unsigned int: %lu", sizeof(unsigned int));
 	G_message("double: %lu", sizeof(double));
@@ -359,31 +356,51 @@
 	max = 100000;
 	G_message("repeating everything %d times.", max);
 
-	{ /* compare rbtree with linked list */
-	//~ no_check_tree = rbtree_create(compare_ids, sizeof(int));
-	//~ rbtree_init_trav(&trav, no_check_tree);
+	{ /* compare rbtree with linked list and array */
+
 	n = 100;
 	start = clock();
 	for (i=0; i<max; i++){
-		no_check_tree = rbtree_create(compare_ids, sizeof(int));
+		no_check_tree = rbtree_create(compare_ids, sizeof(struct pixels));
+		/*build*/
+		for(j=0; j<n; j++){
+			tree_pix->row = tree_pix->col = j;
+			rbtree_insert(no_check_tree, &tree_pix);
+		}
+		//~ /*access*/
 		rbtree_init_trav(&trav, no_check_tree);
+		//~ while ((data = rbtree_traverse(&trav)) != NULL) {
+			//~ if (my_compare_fn(data, threshold_data) == 0) break;
+				//~ G_message("%d", data);
+		//~ }
+		/*free memory*/
+		rbtree_destroy(no_check_tree);
+	}
+	end = clock();
+	cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
+	G_message("Using rbtree of pixels (just build/destroy), %d elements, time: %g", n, cpu_time_used);
 
+	start = clock();
+	for (i=0; i<max; i++){
+		known_iseg_tree = rbtree_create(compare_ids, sizeof(int));
 		/*build*/
 		for(j=0; j<n; j++){
-			rbtree_insert(no_check_tree, &j);
+			rbtree_insert(known_iseg_tree, &j);
 		}
 		//~ /*access*/
+		rbtree_init_trav(&trav, known_iseg_tree);
 		//~ while ((data = rbtree_traverse(&trav)) != NULL) {
 			//~ if (my_compare_fn(data, threshold_data) == 0) break;
 				//~ G_message("%d", data);
 		//~ }
 		/*free memory*/
-		rbtree_destroy(no_check_tree);
+		rbtree_destroy(known_iseg_tree);
 	}
 	end = clock();
 	cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
-	G_message("Using rbtree (just build/destroy), %d elements, time: %g", n, cpu_time_used);
+	G_message("Using rbtree ints (just build/destroy), %d elements, time: %g", n, cpu_time_used);
 
+
 	to_check = NULL;
 	
 	start = clock();
@@ -414,12 +431,12 @@
 	
 		start = clock();
 	for (i=0; i<max; i++){
-		no_check_tree = rbtree_create(compare_ids, sizeof(int));
-		rbtree_init_trav(&trav, no_check_tree);
+		known_iseg_tree = rbtree_create(compare_ids, sizeof(int));
+		rbtree_init_trav(&trav, known_iseg_tree);
 
 		/*build*/
 		for(j=0; j<n; j++){
-			rbtree_insert(no_check_tree, &j);
+			rbtree_insert(known_iseg_tree, &j);
 		}
 		//~ /*access*/
 		//~ while ((data = rbtree_traverse(&trav)) != NULL) {
@@ -427,11 +444,11 @@
 				//~ G_message("%d", data);
 		//~ }
 		/*free memory*/
-		rbtree_destroy(no_check_tree);
+		rbtree_destroy(known_iseg_tree);
 	}
 	end = clock();
 	cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
-	G_message("Using rbtree, %d elements, time: %g", n, cpu_time_used);
+	G_message("Using rbtree ints, %d elements, time: %g", n, cpu_time_used);
 
 	to_check = NULL;
 	
@@ -457,6 +474,40 @@
 	cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
 	G_message("Using linked list and linkm, %d elements, time: %g", n, cpu_time_used);
 	
+	k=100;
+	n=50;
+    check_flag = flag_create(k, k);
+	start = clock();
+	for (i=0; i<max; i++){
+		/*set to zero*/
+		flag_clear_all(check_flag);
+		/*write and access*/
+		for(j=0; j<n; j++){
+			flag_set(check_flag, j, j);
+			temp = flag_get(check_flag, j, j);
+		}
+	}
+	end = clock();
+	cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
+	G_message("Using %d pixel flag array (all cleared), %d elements set and get, time: %g", k*k, n, cpu_time_used);
+	
+
+	k=10000;
+    check_flag = flag_create(k, k);
+	start = clock();
+	for (i=0; i<max; i++){
+		/*set to zero*/
+		flag_clear_all(check_flag);
+		/*write and access*/
+		for(j=0; j<n; j++){
+			flag_set(check_flag, j, j);
+			temp = flag_get(check_flag, j, j);
+		}
+	}
+	end = clock();
+	cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
+	G_message("Using %d pixel flag array (all cleared), %d elements set and get, time: %g", k*k, n, cpu_time_used);
+
 }
 	
 	return TRUE;
@@ -497,7 +548,7 @@
 
     G_verbose_message("Running region growing algorithm");
 
-    t = 0;
+    t = 1;
     files->candidate_count = 0;
 
     /*set next pointers to null. */
@@ -558,16 +609,18 @@
 		files->candidate_count);
 
 	/*process candidate pixels */
-	G_verbose_message("\nRow percent complete for pass number %d: ", t);
+	G_verbose_message("Pass %d: ", t);
 	/*check each pixel, start the processing only if it is a candidate pixel */
 	/* for validation, select one of the two... could make this IFDEF or input parameter */
 	/* reverse order 
 	 */
 #ifdef REVERSE
 	for (row = files->nrows - 1; row >= 0; row--) {
+		G_percent(files->nrows - row, files->nrows, 1);
 	    for (col = files->ncols - 1; col >= 0; col--) {
 #else
 	for (row = 0; row < files->nrows; row++) {
+		G_percent(row, files->nrows, 1);	/* TODO, can a message be included with G_percent? */
 	    for (col = 0; col < files->ncols; col++) {
 #endif
 
@@ -585,7 +638,7 @@
 		    /* 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 = Ri_head;
+		    newpixel->next = NULL;
 		    newpixel->row = row;
 		    newpixel->col = col;
 		    Ri_head = newpixel;
@@ -653,7 +706,7 @@
 
 			/* find Ri's most similar neighbor */
 			Ri_bestn = NULL;
-			Ri_similarity = LDBL_MAX;	/* set current similarity to max value */
+			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 (current = Rin_head; current != NULL; current = current->next) {	/* for each of Ri's neighbors */
@@ -691,7 +744,7 @@
 				  Ri_bestn->col)))
 				/* this check is important:
 				 * best neighbor is not a valid candidate, was already merged earlier in this time step */
-				Ri_similarity = threshold + 1;
+				Ri_bestn = NULL;
 			}
 
 			if (Ri_bestn != NULL && Ri_similarity < threshold) {	/* small TODO: should this be < or <= for threshold? */
@@ -803,9 +856,9 @@
 
     G_debug(4, "Finished one pass, t was = %d", t);
     t++;
-    }
-    while (t <= functions->end_t && endflag == FALSE) ;
+    } while (t <= functions->end_t && endflag == FALSE);
     /*end t loop *//*TODO, should there be a max t that it can iterate for?  Include t in G_message? */
+    
 	if(endflag == FALSE) G_message(_("Merging processes stopped due to reaching max iteration limit, more merges may be possible"));
 
 
@@ -922,7 +975,7 @@
 
 					/* find Ri's most similar neighbor */
 					Ri_bestn = NULL;
-					Ri_similarity = LDBL_MAX;	/* set current similarity to max value */
+					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 (current = Rin_head; current != NULL; current = current->next) {	/* for each of Ri's neighbors */
@@ -1018,12 +1071,12 @@
 			       struct functions *functions)
     {
 	int n, current_seg_ID, Ri_seg_ID = -1;
-	struct pixels *newpixel, *current, *to_check;	/* need to check the pixel neighbors of to_check */
-	int pixel_neighbors[8][2];	/* TODO: data type?  put in files to allocate memory once? */
+	struct pixels *newpixel, *current, *to_check, tree_pix;	/* need to check the pixel neighbors of to_check */
+	int pixel_neighbors[8][2];	/* TODO: data type? use list instead?  put in files to allocate memory once? */
 	
 //TODO remove...	/* files->no_check is a FLAG structure, only used here but allocating memory in open_files */
-	struct RB_TREE *no_check_tree; /* SEGMENT ID that should no longer be checked on this current find_neighbors() run */
-
+	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;
 #endif
@@ -1037,7 +1090,6 @@
 
 	/* parameter: R, current segment membership, could be single pixel or list of pixels.
 	 * parameter: neighbors/Rin/Rik, neighbor pixels, could have a list already, or could be empty ?
-	 * files->out_seg is currently an array [0] for seg ID and [1] for "candidate pixel"
 	 * functions->num_pn  int, 4 or 8, for number of pixel neighbors 
 	 * */
 
@@ -1052,42 +1104,33 @@
 	/* *** initialize data *** */
 	
 	/* get Ri's segment ID */
-	Ri_seg_ID = files->iseg[(*R_head)->row][(*R_head)->col];	/* old data structure needed, this... keep for readability? */
+	Ri_seg_ID = files->iseg[(*R_head)->row][(*R_head)->col];
 	
 //	flag_clear_all(files->no_check);
-	no_check_tree = rbtree_create(compare_ids, sizeof(int));
+	no_check_tree = rbtree_create(compare_pixels, sizeof(struct pixels));
+	known_iseg = rbtree_create(compare_ids, sizeof(int));
 	to_check = NULL;
 
-#ifdef DEBUG
-	rbtree_init_trav(&trav, no_check_tree);
-#endif
-
 	/* Copy R in to_check and no_check data structures (don't expand them if we find them again) */
-	/* NOTE: in pseudo code also have a "current segment" list, but think we can just pass Ri and use it directly */
 
 	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. */
-//todo delete	    flag_set(files->no_check, current->row, current->col);
-	}
+	
+		/* 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!?");
 
-//~ G_message("starting to insert dummy no_check values");
-//~ current_seg_ID = -5;
-//~ rbtree_insert(no_check_tree, &current_seg_ID);
-//~ G_message("inserted -5");
-//~ current_seg_ID = -10;
-//~ rbtree_insert(no_check_tree, &current_seg_ID);
-//~ G_message("inserted -10");
-
-	rbtree_insert(no_check_tree, &Ri_seg_ID);
-	G_debug(5, "inserted Ri_seg_ID number %d into RBtree.", Ri_seg_ID);
-
-	/* empty "neighbor" list  Note: this step is in pseudo code, but think we just pass in Rin - it was already initialized, and later could have Ri data available to start from */
-
+		//todo delete	    flag_set(files->no_check, current->row, current->col);
+	
+	}	
+	
 	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",
@@ -1098,7 +1141,6 @@
 					    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);
@@ -1117,88 +1159,68 @@
 		
 	    /*now check the pixel neighbors and add to the lists */
 
-	    /*debug what neighbors were found: */
+	    /*debug 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 (n = 0; n < functions->num_pn; n++) {	/* with pixel neighbors */
 
-		//~TODO delete    G_debug(5,
-			//~ "\twith pixel neigh %d, row: %d col: %d, val_no_check = %d",
-			//~ n, pixel_neighbors[n][0], pixel_neighbors[n][1],
-			//~ flag_get(files->no_check, pixel_neighbors[n][0],
-				 //~ pixel_neighbors[n][1]));
 		// TODO delete   if (flag_get(files->no_check, pixel_neighbors[n][0], pixel_neighbors[n][1]) == FALSE) 
-		current_seg_ID = files->iseg[pixel_neighbors[n][0]][pixel_neighbors[n][1]];
+		tree_pix.row = pixel_neighbors[n][0];
+		tree_pix.col = pixel_neighbors[n][1];
 		G_debug(5, "\tcurrent_seg_ID = %d", current_seg_ID);
-		G_debug(5, "********* rbtree_find(no_check_tree, &current_seg_ID) = %p", rbtree_find(no_check_tree, &current_seg_ID)); 
-		G_debug(5, "if evaluation: %d", rbtree_find(no_check_tree, &current_seg_ID) == FALSE);
+		G_debug(5, "********* rbtree_find(no_check_tree, &tree_pix) = %p", rbtree_find(no_check_tree, &tree_pix)); 
+		G_debug(5, "if evaluation: %d", rbtree_find(no_check_tree, &tree_pix) == FALSE);
 
-/* ######################
- * bad logic... previously, was tracking no_check pixels
- * want to get both neighbors AND membership of R
- * Changing to no_check saving the segment ID's - need someway to find membership!
- * 
- * do speed check on Rbtree vs. linked list membership list???
- * 
- * A.  revert to saving no_check pixels. could still use tree for no_check pixels,
- * 		 compare function could use row then col.
- *   Could have RBtree to save unique segment id's as well, so neighbor list could be reduced as well.
- * return membership and neighbors would still be lists.
- * 
- * B.  save membership pixels in a tree.  So with each new pixel to check:
- * 			if current seg ID equals R_segID && can't find it in the tree, then add it to membership tree
- * 			else if current seg ID is not in neighbor tree, then add it to neighbor list
- * with B, would it be worth changing the neighbor list to a tree?
- * */
+		if(rbtree_find(no_check_tree, &tree_pix) == FALSE) {	/* want to check this neighbor */
+			current_seg_ID = files->iseg[pixel_neighbors[n][0]][pixel_neighbors[n][1]];		
 
+		    rbtree_insert(no_check_tree, &tree_pix);	/* don't check it again */
 
-		if(rbtree_find(no_check_tree, &current_seg_ID) == FALSE) {	/* want to check this neighbor */
-		    if(rbtree_insert(no_check_tree, &current_seg_ID)==0)	/* don't check it again */
-				G_warning("could not insert data!?");
-
 		    if (!(FLAG_GET(files->null_flag, pixel_neighbors[n][0], pixel_neighbors[n][1]))) {	/* all pixels, not just valid pixels */
 
-			G_debug(5, "\tfiles->iseg[][] = %d Ri_seg_ID = %d",
-				files->
-				iseg[pixel_neighbors[n][0]][pixel_neighbors[n]
-							    [1]], Ri_seg_ID);
-			if (files->
-			    iseg[pixel_neighbors[n][0]][pixel_neighbors[n][1]]
-			    == Ri_seg_ID) {
-			    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);
+				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 == Ri_seg_ID) { /* 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 */
-			    /* put pixel_neighbor[n] in Rin */
-			    G_debug(5, "Put in neighbors_head");
-			    /* TODO - helper function for adding pixel to a list */
-			    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. */
+				}
+				else {	/* segment id's were different */
+					//if current ID not found in known neighbors list
+						//add to known neighbors list
+						/* put pixel_neighbor[n] in Rin */
+						G_debug(5, "Put in neighbors_head");
+						/* TODO - helper function for adding pixel to a list */
+						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 not a null pixel */
 		    else
 			G_debug(5,
@@ -1213,14 +1235,7 @@
 	    for (current = to_check; current != NULL; current = current->next)
 			G_debug(5, "to_check... row: %d, col: %d", current->row,
 				current->col);
-			
-		/* todo? just to see if it worked?  G_message("no_check segment ID's: hmm, how implement?"); */
-/*
-	while ((data = rbtree_traverse(&trav)) != NULL) {
-		if (my_compare_fn(data, threshold_data) == 0) break;
-			G_message("%d", data);
-	}
-*/	
+	
 	    G_debug(5, "\t### end of pixel neighors");
 	    #endif
 	}			/* while to_check has more elements */
@@ -1282,7 +1297,7 @@
 
 	/* get the 4 diagonal neighbors */
 	G_warning("Diagonal neighbors Not Implemented");
-	/*TODO... continue as above */
+	/*TODO... continue as above? or "nicer" way to do it? */
 	return TRUE;
     }
 
@@ -1398,7 +1413,7 @@
 	struct pixels *current;
 
 	while ((*head) != NULL) {
-	    current = *head;	/* rememer "old" head */
+	    current = *head;	/* remember "old" head */
 	    *head = (*head)->next;	/* move head to next pixel */
 	    link_dispose(token, (VOID_T *) current);	/* remove "old" head */
 	}
@@ -1407,7 +1422,6 @@
     }
 
 /* function used by binary tree to compare items */
-/* TODO, I don't understand the purpose of all this C syntax...will this give me just a simple numeric comparison??? */
 
 /* TODO
  * "static" was used in break_polygons.c  extern was suggested in docs.  */
@@ -1428,3 +1442,23 @@
 	return 1;
 	
 }
+
+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 if (*a->row == *b->row) todo - a little faster to use else.  But what if (can) a null pixel be passed?
+	else {
+            /* same row */
+	    if (a->col < b->col)
+		    return -1;
+	    else if (a->col > b->col)
+		    return 1;
+        }
+	/* same row and col todo, same as above, need an == check to be sure?*/
+	return 0;
+}

Modified: grass-addons/grass7/imagery/i.segment/iseg.h
===================================================================
--- grass-addons/grass7/imagery/i.segment/iseg.h	2012-07-08 13:49:31 UTC (rev 52351)
+++ grass-addons/grass7/imagery/i.segment/iseg.h	2012-07-09 04:13:55 UTC (rev 52352)
@@ -125,6 +125,7 @@
 				      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 *);
 
 /* write_output.c */
 int write_output(struct files *);

Modified: grass-addons/grass7/imagery/i.segment/open_files.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/open_files.c	2012-07-08 13:49:31 UTC (rev 52351)
+++ grass-addons/grass7/imagery/i.segment/open_files.c	2012-07-09 04:13:55 UTC (rev 52352)
@@ -79,7 +79,7 @@
     scols = 64;
 
     /* TODO: make calculations for this */
-    nseg = 8;
+    nseg = 10000;
 
 
     /* ******* create temporary segmentation files ********* */

Modified: grass-addons/grass7/imagery/i.segment/parse_args.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/parse_args.c	2012-07-08 13:49:31 UTC (rev 52351)
+++ grass-addons/grass7/imagery/i.segment/parse_args.c	2012-07-09 04:13:55 UTC (rev 52352)
@@ -44,8 +44,8 @@
 	min_segment_size->key = "min"; /*TODO is there a preference for long or short key names? min is pretty generic...but short... */
 	min_segment_size->type = TYPE_INTEGER;
 	min_segment_size->required = YES;
-	min_segment_size->answer = "1"; /* TODO, should a "typical" default be provided? */
-	min_segment_size->options = "1-100000"; /*must be positive number, is >0 allowed in "options" or is 100,000 suitably large? */
+	min_segment_size->answer = "1"; /* default: no merges */
+	min_segment_size->options = "1-100000";
 	min_segment_size->description = _("Minimum number of pixels (cells) in a segment.  The final merge step will ignore the threshold for any segments with fewer pixels.");
     
     /* optional parameters */
@@ -72,12 +72,6 @@
     bounds->required = NO;
     bounds->description =
 	_("Optional bounding/constraining raster map, must be integer values, each area will be segmented independent of the others.");
-    /*    bounds->description = _("Optional vector map with polygons to bound (constrain) segmentation."); */
-    /* TODO: if performing second segmentation, will already have raster map from this module
-     * If have preexisting boundaries (landuse, etc) will have vector map?
-     * Seems we need to have it in raster format for processing, is it OK to have the user run v.to.rast before doing the segmentation?
-     * Or for hierarchical segmentation, will it be easier to have the polygons?
-     *  */
 
     /* TODO input for distance function */
 
@@ -120,7 +114,7 @@
 
     if (weighted->answer == FALSE &&
 	(functions->threshold <= 0 || functions->threshold >= 1))
-	G_fatal_error(_("threshold should be >= 0 and <= 1"));	/* TODO OK to have fatal error here, seems this would be an invalid entry. */
+	G_fatal_error(_("threshold should be >= 0 and <= 1"));
 
     /* segmentation methods:  0 = debug, 1 = region growing */
     /* TODO, instead of string compare, does the Option structure have these already numbered? */
@@ -161,7 +155,7 @@
     }
     else {			/* polygon constraints given */
 	files->bounds_map = bounds->answer;
-	if ((files->bounds_mapset = G_find_raster(files->bounds_map, "")) == NULL) {	/* TODO, warning here:  parse_args.c:149:27: warning: assignment discards ‘const’ qualifier from pointer target type [enabled by default] */
+	if ((files->bounds_mapset = G_find_raster(files->bounds_map, "")) == NULL) {	/* TODO, compiler warning here:  parse_args.c:149:27: warning: assignment discards ‘const’ qualifier from pointer target type [enabled by default] */
 	    G_fatal_error(_("Segmentation constraint/boundary map not found."));
 	}
 	if (Rast_map_type(files->bounds_map, files->bounds_mapset) !=

Modified: grass-addons/grass7/imagery/i.segment/times.txt
===================================================================
--- grass-addons/grass7/imagery/i.segment/times.txt	2012-07-08 13:49:31 UTC (rev 52351)
+++ grass-addons/grass7/imagery/i.segment/times.txt	2012-07-09 04:13:55 UTC (rev 52352)
@@ -17,10 +17,13 @@
 unsigned int: 4
 double: 8
 repeating everything 100000 times.
-Using rbtree (just build/destroy), 100 elements, time: 3.94
-Using linked list and linkm (build/access/free), 100 elements, time: 0.3
-Using rbtree, 1000 elements, time: 51.03
-Using linked list and linkm, 1000 elements, time: 3.21
+Using rbtree of pixels (just build/destroy), 100 elements, time: 0.25
+Using rbtree ints (just build/destroy), 100 elements, time: 3.1
+Using linked list and linkm (build/access/free), 100 elements, time: 0.27
+Using rbtree ints, 1000 elements, time: 49.37
+Using linked list and linkm, 1000 elements, time: 2.64
+Using 10000 pixel flag array (all cleared), 50 elements set and get, time: 0.32
+Using 100000000 pixel flag array (all cleared), 50 elements set and get, time: 2560.09
 
 
 Storage requirement:
@@ -44,7 +47,16 @@
 user	429m55.276s
 sys	1m0.640s
 
+changing to tree: real	777m50.251s
+But there was one very large segment.
 
+
+-w threshold=3:
+real	140m42.401s
+The SW corner is still mostly one segment.
+
+So the processing time is sensitive to the size of the segments.
+
 g.region s=222000 e=637000
 cells:      56334
 < 5 minutes
@@ -66,6 +78,10 @@
 pass 294
 real	7m22.592s
 
+changing flag to tree:
+real	8m26.741s
+
+
 g.region s=219000
 cells: 176018
 41min

Modified: grass-addons/grass7/imagery/i.segment/write_output.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/write_output.c	2012-07-08 13:49:31 UTC (rev 52351)
+++ grass-addons/grass7/imagery/i.segment/write_output.c	2012-07-09 04:13:55 UTC (rev 52352)
@@ -34,7 +34,6 @@
 
     G_debug(1, "start data transfer from segmentation file to raster");
     /* transfer data from segmentation file to raster */
-    /* output segmentation file: each element includes the segment ID then processing flag(s).  So just need the first part of it. */
 
     for (row = 0; row < files->nrows; row++) {
 	Rast_set_c_null_value(outbuf, files->ncols);	/*set buffer to NULLs, only write those that weren't originally masked */
@@ -84,20 +83,26 @@
     int i;
 
     /* close segmentation files and output raster */
-    G_debug(1, "closing files");
+    G_debug(1, "closing bands_seg...");
     segment_close(&files->bands_seg);
-    segment_close(&files->bounds_seg);
-
+    G_debug(1, "closing bounds_seg...");
+    if (files->bounds_map != NULL) 
+        segment_close(&files->bounds_seg);
+    
+    G_debug(1, "freeing _val");
     G_free(files->bands_val);
     G_free(files->second_val);
 
+    G_debug(1, "freeing iseg");
     for (i = 0; i < files->nrows; i++)
 	G_free(files->iseg[i]);
     G_free(files->iseg);
 
+    G_debug(1, "destroying flags");
     flag_destroy(files->null_flag);
     flag_destroy(files->candidate_flag);
 //    flag_destroy(files->no_check);
+
     G_debug(1, "close_files() before link_cleanup()");
     link_cleanup(files->token);
     G_debug(1, "close_files() after link_cleanup()");



More information about the grass-commit mailing list