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

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Jul 30 20:56:38 PDT 2012


Author: momsen
Date: 2012-07-30 20:56:38 -0700 (Mon, 30 Jul 2012)
New Revision: 52480

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:
iseg moved from RAM to SEG.  Seeds have been implemented. Seeded segments will merge with each other.

Modified: grass-addons/grass7/imagery/i.segment/create_isegs.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/create_isegs.c	2012-07-30 16:53:28 UTC (rev 52479)
+++ grass-addons/grass7/imagery/i.segment/create_isegs.c	2012-07-31 03:56:38 UTC (rev 52480)
@@ -12,8 +12,9 @@
 #include <grass/rbtree.h>	/* Red Black Tree library functions */
 #include "iseg.h"
 
+#include <time.h>		//todo polish...remove at end
+
 #ifdef DEBUG
-#include <time.h>
 #include <limits.h>
 #endif
 
@@ -102,15 +103,21 @@
 			FLAG_SET(files->null_flag, row, col);
 		}
 	    }
-	    G_debug(1, "minrow: %d, maxrow: %d, mincol: %d, maxcol: %d",
-		    files->minrow, files->maxrow, files->mincol,
-		    files->maxcol);
 
 	    /* clear candidate flag, so only need to reset the processing area on each iteration. todo polish, can be removed after all loops only cover the processing area */
 	    flag_clear_all(files->candidate_flag);
 
 	}			/* end of else, set up for bounded segmentation */
 
+	/* consider maxrow/maxcol as nrow, ncol, loops will have: row < maxrow
+	 * so need to increment by one */
+	files->maxrow++;
+	files->maxcol++;
+	G_debug(1,
+		"minrow: %d, maxrow: %d, nrows: %d, mincol: %d, maxcol: %d, ncols: %d",
+		files->minrow, files->maxrow, files->nrows, files->mincol,
+		files->maxcol, files->ncols);
+
 	/* run the segmentation algorithm */
 
 	if (functions->method == 1) {
@@ -174,10 +181,12 @@
     /* idea is for large maps, if the width of SEG tiles in RAM is less than the width of the map, this should avoid a lot of I/O */
     /* this is probably closer to a z-order curve then peano order. */
 
+    s = -1;
     /*blank slate */
     for (row = 0; row < files->nrows; row++) {
 	for (col = 0; col < files->ncols; col++) {
-	    files->iseg[row][col] = -1;
+	    //files->iseg[row][col] = -1;
+	    segment_put(&files->iseg_seg, (void *)s, row, col);
 	}
     }
     s = 0;
@@ -203,7 +212,8 @@
 	j--;
 	col = col | (1 & (i >> j));
 	G_message("Done: i: %li, row: %d, col: %d", i, row, col);
-	files->iseg[row][col] = s;
+	//~ files->iseg[row][col] = s;
+	segment_put(&files->iseg_seg, (void *)s, row, col);
 	s++;
     }
 
@@ -375,7 +385,9 @@
     for (row = 0; row < files->nrows; row++) {
 	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;
+	    //~ files->iseg[row][col] = col + row;
+	    //todo need variable..
+	    //segment_put(&files->iseg_seg, (void *)s, row, col);
 	}
 	G_percent(row, files->nrows, 1);
     }
@@ -456,7 +468,8 @@
 
 	start = clock();
 	for (i = 0; i < max; i++) {
-	    temp = files->iseg[12][12];
+	    //~ temp = files->iseg[12][12];
+	    //todo
 	}
 	end = clock();
 	cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
@@ -730,13 +743,13 @@
 
 int get_segID_RAM(struct files *files, int row, int col)
 {
-    return files->iseg[row][col];
+    return 0;			//todo... segment_put(&files->iseg_seg, (void *)s, row, col);    files->iseg[row][col];
 }
 #endif
 
 int region_growing(struct files *files, struct functions *functions)
 {
-    int row, col, t;
+    int row, col, t, testing;	//todo remove testing
     double threshold, Ri_similarity, Rk_similarity, tempsim;
     int endflag;		/* =TRUE if there were no merges on that processing iteration */
     int pathflag;		/* =TRUE if we didn't find mutual neighbors, and should continue with Rk */
@@ -744,6 +757,16 @@
 	*Rc_head, *Rc_tail, *Rcn_head, *current, *newpixel, *Ri_bestn;
     int Ri_count, Rk_count, Rc_count;	/* number of pixels/cells in Ri and Rk */
 
+    //todo polish, remove or comment when done?
+    clock_t start, end;
+    clock_t merge_start, merge_end;
+    double merge_accum, merge_lap;
+    clock_t fn_start, fn_end;
+    double fn_accum, fn_lap;
+
+    merge_accum = fn_accum = 0;
+    start = clock();
+
     /* files->token has the "link_head" for linkm: linked list memory allocation.
      * 
      * 4 linked lists of pixels:
@@ -760,7 +783,7 @@
     t = 1;
     files->candidate_count = 0;
 
-    /*set next pointers to null. */
+    /*set linked list head pointers to null. */
     Ri_head = NULL;
     Rk_head = NULL;
     Rin_head = NULL;
@@ -775,6 +798,7 @@
 
 	G_debug(3, "#######   Starting outer do loop! t = %d    #######", t);
 	/* todo, delete this?  G_verbose_message("Pass %d: ", t); */
+	fprintf(stdout, "pass %d\n", t);
 	G_percent(t, functions->end_t, 1);
 
 	threshold = functions->threshold;	/* TODO, consider making this a function of t. */
@@ -792,7 +816,7 @@
 	/*check each pixel, start the processing only if it is a candidate pixel */
 	for (row = 0; row < files->nrows; row++) {
 	    for (col = 0; col < files->ncols; col++) {
-
+		//if (col == 3) return TRUE;
 		G_debug(4, "Starting pixel from next row/col, not from Rk");
 
 		if (FLAG_GET(files->candidate_flag, row, col)) {
@@ -820,14 +844,23 @@
 			G_debug(4, "Next starting pixel: row, %d, col, %d",
 				Ri_head->row, Ri_head->col);
 
+			pathflag = FALSE;
+
 			/* find segment neighbors, if we don't already have them */
 			if (Rin_head == NULL) {
+			    fn_start = clock();
 			    if (find_segment_neighbors
 				(&Ri_head, &Rin_head, &Ri_count, files,
 				 functions) != TRUE) {
 				G_fatal_error
 				    ("find_segment_neighbors() failed");
 			    }
+			    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);
 			}
 
 			if (Rin_head != NULL) {	/*found neighbors, find best neighbor then see if is mutually best neighbor */
@@ -921,23 +954,31 @@
 					"Lowest Ri_similarity = %g, for neighbor pixel row: %d col: %d",
 					Ri_similarity, Ri_bestn->row,
 					Ri_bestn->col);
-					
-//if bounds map, can't check if it is a candidate.  TODO better way to include this check after decide on using the candidate flag here.
-if(files->seeds_map == 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;
-				    pathflag = FALSE;
+
+				//if seeds map, can't check if it is a candidate.  TODO better way to include this check after decide on using the candidate flag here.
+				if (files->seeds_map == 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;
+					//pathflag = FALSE;
+				    }
 				}
 			    }
-}
 			    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);
@@ -983,10 +1024,22 @@
 				}	/* have checked all of Rk's neighbors */
 
 				if (Rk_similarity == Ri_similarity) {	/* mutually most similar neighbors */
+
+				    segment_get(&files->iseg_seg, &testing,
+						Ri_head->row, Ri_head->col);
+				    //~ G_message("\t\tbefore call merge()... testing: %d, Ri_head->row: %d, Ri_head->col: %d", testing, Ri_head->row, Ri_head->col);
+				    merge_start = clock();
 				    merge_values(Ri_head, Rk_head, Ri_count,
 						 Rk_count, files);
+				    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);
 				    endflag = FALSE;	/* we've made at least one merge, so want another t iteration */
-				    pathflag = FALSE;	/* go to next row,column pixel - end of Rk -> Ri chain since we found mutual best neighbors */
+				    //pathflag = FALSE; /* go to next row,column pixel - end of Rk -> Ri chain since we found mutual best neighbors */
 				}
 				else {	/* they weren't mutually best neighbors */
 				    G_debug(4,
@@ -997,6 +1050,11 @@
 				    set_candidate_flag(Ri_head, FALSE, files);
 				    G_debug(4, "line 247, \t\t\t\tcc = %d",
 					    files->candidate_count);
+
+				    if (!(FLAG_GET
+					  (files->candidate_flag,
+					   Rk_head->row, Rk_head->col)))
+					pathflag = TRUE;
 				}
 			    }	/* end if (Ri_bestn != NULL && Ri_similarity < threshold) */
 			    else {
@@ -1008,13 +1066,13 @@
 				set_candidate_flag(Ri_head, FALSE, files);
 				G_debug(4,
 					"3b Ri's best neighbor was not valid candidate, or their similarity was > threshold");
-				pathflag = FALSE;
+				//pathflag = FALSE;
 			    }
 
 			}	/* end if(Rin_head != NULL) */
 			else {	/* Ri didn't have a neighbor */
 			    G_debug(4, "Segment had no neighbors");
-			    pathflag = FALSE;
+			    //pathflag = FALSE;
 			    set_candidate_flag(Ri_head, FALSE, files);
 			    G_debug(4, "line 176, \t\t\t\tcc = %d",
 				    files->candidate_count);
@@ -1188,6 +1246,11 @@
     if (t > 2)
 	G_verbose_message("temporary(?) message, number of passes: %d",
 			  t - 1);
+    end = clock();
+    fprintf(stdout, "time spent merging: %g\n", merge_accum);
+    fprintf(stdout, "time spent finding neighbors: %g\n", fn_accum);
+    fprintf(stdout, "total time: %g\n",
+	    ((double)(end - start) / CLOCKS_PER_SEC));
 
     return TRUE;
 }
@@ -1196,7 +1259,7 @@
 			   struct pixels **neighbors_head, int *seg_count,
 			   struct files *files, struct functions *functions)
 {
-    int n, current_seg_ID, Ri_seg_ID = -1;
+    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 */
@@ -1225,7 +1288,13 @@
 
     /* *** initialize data *** */
 
-    Ri_seg_ID = files->iseg[(*R_head)->row][(*R_head)->col];
+    //Ri_seg_ID = files->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. */
+
+    //~ G_message("fpn() for iseg: %d", R_iseg);
     no_check_tree = rbtree_create(compare_pixels, sizeof(struct pixels));
     known_iseg = rbtree_create(compare_ids, sizeof(int));
     to_check = NULL;
@@ -1299,17 +1368,18 @@
 		    rbtree_find(no_check_tree, &tree_pix));
 
 	    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]];
+		segment_get(&files->iseg_seg, &current_seg_ID,
+			    pixel_neighbors[n][0], pixel_neighbors[n][1]);
+		//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 */
 
-		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 == Ri_seg_ID) {	/* pixel is member of current segment, add to R */
+		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);
@@ -1330,9 +1400,10 @@
 		}
 		else {		/* segment id's were different */
 		    if (!rbtree_find(known_iseg, &current_seg_ID)) {	/* we don't have any neighbors yet from this segment */
-
-			/* 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?
+			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... */
 
@@ -1448,10 +1519,29 @@
 
 }
 
+/*
+   In the eCognition literature, we find that the key factor in the
+   multi-scale segmentation algorithm used by Definiens is the scale
+   factor f:
+
+   f = W.Hcolor + (1 - W).Hshape
+   Hcolor = sum(b = 1:nbands)(Wb.SigmaB)
+   Hshape = Ws.Hcompact + (1 - Ws).Hsmooth
+   Hcompact = PL/sqrt(Npx)
+   Hsmooth = PL/Pbbox
+
+   Where W is a user-defined weight of importance of object radiometry vs
+   shape (usually .9 vs .1), Wb is the weigh given to band B, SigmaB is
+   the std dev of the object for band b, Ws is a user-defined weight
+   giving the importance of compactedness vs smoothness, PL is the
+   perimeter lenght of the object, Npx the number of pixels within the
+   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;
+    int n, Ri_iseg = 42, Rk_iseg = 43;
     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... */
@@ -1460,6 +1550,15 @@
     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? */
+    //      G_message("Ri_iseg get(): %d", segment_get(&files->iseg_seg, &Ri_iseg, Ri_head->row, Ri_head->col));
+    //~ G_message("Rk_iseg get(): %d", segment_get(&files->iseg_seg, &Rk_iseg, Rk_head->row, Rk_head->col));
+    //~ G_message("Ri_iseg get(): %d", segment_get(&files->iseg_seg, &Ri_iseg, Ri_head->row, Ri_head->col));
+    //~ G_message("here is what I have:  Ri_iseg: %d, Ri_head->row: %d, Ri_head->col: %d", Ri_iseg, Ri_head->row, Ri_head->col);
+    //~ G_message("here is what I have:  Rk_iseg: %d, Rk_head->row: %d, Rk_head->col: %d", Rk_iseg, Rk_head->row, Rk_head->col);
+
     for (n = 0; n < files->nbands; n++) {
 	files->bands_val[n] =
 	    (files->bands_val[n] * Ri_count +
@@ -1468,9 +1567,14 @@
 
     /* 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).\t",
+	    Ri_iseg, Ri_count, Rk_iseg, Rk_count);
+    //~ G_message("Ri_head->row: %d, Ri_head->col: %d", Ri_head->row, Ri_head->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,
@@ -1483,8 +1587,9 @@
     for (current = Rk_head; current != NULL; current = current->next) {
 	segment_put(&files->bands_seg, (void *)files->bands_val,
 		    current->row, current->col);
-	files->iseg[current->row][current->col] =
-	    files->iseg[Ri_head->row][Ri_head->col];
+	//~ files->iseg[current->row][current->col] =
+	//~ files->iseg[Ri_head->row][Ri_head->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);
@@ -1492,9 +1597,14 @@
 
     }
 
-    /* merged two segments, decrement count */
-    files->nsegs--;
-    /* todo seeds: need if statement here, if merging "unseeded" pixel, don't want to decrement. */
+    /* merged two segments, decrement count 
+     * if seeds were provided, need to adjust the candidate_count*/
+    if (files->seeds_map == NULL)
+	files->nsegs--;
+    else {
+	files->candidate_count += Ri_count + Rk_count - 1;
+	/* todo if allow seeded segments to merge, need to decrement nsegs if Rk_count = 1 and it isn't a seed */
+    }
 
     return TRUE;
 }
@@ -1580,57 +1690,58 @@
 }
 
 /* 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 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;
 
-	if(files->seeds_map == NULL) { /* entire map is considered as 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++;
+    if (files->seeds_map == NULL) {	/* entire map is considered as 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
-		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 {                  /* 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 */
-	
+    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...
+	    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...
 	    }
-	    else
-		FLAG_UNSET(files->candidate_flag, row, col); //todo maybe can skip this...
 	}
     }
-	}
-	
-	
+
+
     return TRUE;
 }
 

Modified: grass-addons/grass7/imagery/i.segment/iseg.h
===================================================================
--- grass-addons/grass7/imagery/i.segment/iseg.h	2012-07-30 16:53:28 UTC (rev 52479)
+++ grass-addons/grass7/imagery/i.segment/iseg.h	2012-07-31 03:56:38 UTC (rev 52480)
@@ -20,6 +20,9 @@
  * it also add some while loops that just have G_debug statements in them. */
 /* #define DEBUG */
 
+/* PROFILE will add some rough time checks for finding neighbors and merging. */
+/* #define PROFILE */
+
 /* pixel stack */
 struct pixels
 {
@@ -40,7 +43,7 @@
 
     /* files */
     char *out_name;		/* name of output raster map */
-    const char *seeds_map, *seeds_mapset, *bounds_map, *bounds_mapset;		/* optional segment seeds and polygon constraints/boundaries */
+    const char *seeds_map, *seeds_mapset, *bounds_map, *bounds_mapset;	/* optional segment seeds and polygon constraints/boundaries */
     char *out_band;		/* for debug */
 
     /* file processing */
@@ -53,7 +56,9 @@
     int minrow, maxrow, mincol, maxcol;
 
     /* results */
-    int **iseg;			/* segment ID assignment */
+    SEGMENT iseg_seg;		/* segment ID assignment */
+    //    int iseg_val;
+    //    int **iseg;                       /* segment ID assignment */
     int nsegs;			/* number of segments */
 
     /* processing flags */

Modified: grass-addons/grass7/imagery/i.segment/open_files.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/open_files.c	2012-07-30 16:53:28 UTC (rev 52479)
+++ grass-addons/grass7/imagery/i.segment/open_files.c	2012-07-31 03:56:38 UTC (rev 52480)
@@ -14,7 +14,8 @@
     int i, 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;		/* todo. correct data type when allowing any data type? */
+    void *seedsbuf, *ptr;	/* todo. correct data type when allowing any data type? */
+    size_t ptrsize;
     RASTER_MAP_TYPE data_type;
     struct FPRange *fp_range;	/* for getting min/max values on each input raster */
     DCELL *min, *max;
@@ -39,7 +40,7 @@
     files->candidate_flag = flag_create(files->nrows, files->ncols);
     if (files->bounds_map != NULL)
 	files->orig_null_flag = flag_create(files->nrows, files->ncols);
-	if (files->seeds_map != NULL)
+    if (files->seeds_map != NULL)
 	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 */
@@ -73,6 +74,14 @@
 			  Ref.file[n].mapset);
     }
 
+    /* open seeds raster */
+    if (files->seeds_map != NULL) {
+	seeds_fd = Rast_open_old(files->seeds_map, "");
+	data_type = Rast_get_map_type(seeds_fd);
+	seedsbuf = Rast_allocate_buf(data_type);
+	ptrsize = Rast_cell_size(data_type);
+    }
+
     /* Get min/max values of each input raster for scaling */
 
     if (files->weighted == FALSE) {	/*default, we will scale */
@@ -100,7 +109,7 @@
     scols = 64;
 
     /* TODO: make calculations for this, check i.cost and i.watershed */
-    nseg = 16;
+    nseg = 1000;		//16;
 
 
     /* ******* create temporary segmentation files ********* */
@@ -123,24 +132,34 @@
     files->bands_val = (double *)G_malloc(inlen);
     files->second_val = (double *)G_malloc(inlen);
 
-    files->iseg = G_malloc(files->nrows * sizeof(int *));
-    for (i = 0; i < files->nrows; i++)
-	files->iseg[i] = G_malloc(files->ncols * sizeof(int));
+    //~ files->iseg = G_malloc(files->nrows * sizeof(int *));
+    //~ for (i = 0; i < files->nrows; i++)
+    //~ files->iseg[i] = G_malloc(files->ncols * sizeof(int));
+    //~ 
+    //~ /*check the last one to make sure there was enough memory */
+    //~ if (files->iseg[i - 1] != NULL) {       /* everything is OK, and assume all previous memory allocations are OK too. */
+    //~ }
+    //~ else
+    //~ G_fatal_error(_("Unable to allocate memory for initial segment ID's"));
 
-    /*check the last one to make sure there was enough memory */
-    if (files->iseg[i - 1] != NULL) {	/* everything is OK, and assume all previous memory allocations are OK too. */
-    }
-    else
+    if (segment_open
+	(&files->iseg_seg, G_tempfile(), files->nrows, files->ncols, srows,
+	 scols, inlen, nseg) != TRUE)
 	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. */
 
     /* ********  load input bands to segment structure and fill iseg array ******** */
     G_debug(1, "Reading input rasters into segmentation data files...");
-    s = 1;			/* initial segment ID */
+    s = 0;			/* initial segment ID will be 1 */
 
     for (row = 0; row < files->nrows; row++) {
 	for (n = 0; n < Ref.nfiles; n++) {
 	    Rast_get_d_row(in_fd[n], inbuf[n], row);
 	}
+	if (files->seeds_map != NULL) {
+	    Rast_get_row(seeds_fd, seedsbuf, row, data_type);
+	    ptr = seedsbuf;
+	}
 	for (col = 0; col < files->ncols; col++) {
 	    null_check = 1;	/*Assume there is data */
 	    for (n = 0; n < Ref.nfiles; n++) {
@@ -154,44 +173,44 @@
 	    segment_put(&files->bands_seg, (void *)files->bands_val, row, col);	/* store input bands */
 
 	    if (null_check != -1) {	/*good pixel */
-		files->iseg[row][col] = s;	/*starting segment number TODO: for seeds this will be different */
 		FLAG_UNSET(files->null_flag, row, col);	/*flag */
-		s++;		/* sequentially number all pixels with their own segment ID */
+		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, OK? */
+			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 use the zero as seg ID?  If go this route, need to enforce constraints are positive integers.
+			//files->iseg[row][col] = s;    /*starting segment number TODO: for seeds this will be different */
+			segment_put(&files->iseg_seg, &s, row, col);
+			G_message("set seed for row: %d, col: %d", row, col);
+
+		    }
+		    ptr = G_incr_void_ptr(ptr, ptrsize);
+		}
+		else {		/* no seeds provided */
+		    s++;	/* sequentially number all pixels with their own segment ID */
+		    //files->iseg[row][col] = s;    
+		    segment_put(&files->iseg_seg, &s, row, col);	/*starting segment number */
+		}
 	    }
 	    else {		/*don't use this pixel */
-		files->iseg[row][col] = -1;	/* place holder...TODO this could be a conflict if constraints included a -1 */
+		//files->iseg[row][col] = -1;   /* place holder...TODO this could be a conflict if constraints included a -1 ??? wrote that awhile ago...still true???*/
+		//TODO, do we need a -1 here?  Or just leave as the zero it was initialized with?  Need a -1 if we don't use the NULL_FLAG...
 		FLAG_SET(files->null_flag, row, col);	/*flag */
 	    }
 	}
     }
 
     /* number of initial segments, will decrement when merge */
-    files->nsegs = s - 1;
+    files->nsegs = s;
 
-	/* starting seeds */
-	/* save as flag, will reset candidate flags to match seed flags on each iteration */
-	if (files->seeds_map != NULL) {
-		seeds_fd = Rast_open_old(files->seeds_map, "");
-		data_type = Rast_get_map_type(seeds_fd);
-		seedsbuf = Rast_allocate_buf(data_type);
-		
-		for (row = 0; row < files->nrows; row++) {
-			Rast_get_row(seeds_fd, seedsbuf, row, data_type);
-			for (col = 0; col < files->ncols; col++) {
-			
-			if (Rast_is_null_value(&seedsbuf[col], 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]
-																		  */
-			
-				FLAG_SET(files->seeds_flag, row, col);
-			}
-			}
-		}
-		Rast_close(seeds_fd);
-		G_free(seedsbuf);
-	}
-
     /* bounds/constraints */
     if (files->bounds_map != NULL) {
 	if (segment_open
@@ -229,11 +248,17 @@
 	G_debug(1, "no boundary constraint supplied.");
     }
 
+    //~ for (row = 0; row < files->nrows; row++) {
+    //~ for (col = 0; col < files->ncols; col++) {
+    //~ segment_get(&files->iseg_seg, &s, row, col);
+    //~ G_message("row: %d, col: %d, iseg: %d", row, col, s);
+    //~ }}
 
     /* 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 */
@@ -247,6 +272,11 @@
 	Rast_close(in_fd[n]);
     }
 
+    if (files->seeds_map != NULL) {
+	Rast_close(seeds_fd);
+	G_free(seedsbuf);
+    }
+
     G_free(inbuf);
     G_free(in_fd);
     G_free(fp_range);

Modified: grass-addons/grass7/imagery/i.segment/parse_args.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/parse_args.c	2012-07-30 16:53:28 UTC (rev 52479)
+++ grass-addons/grass7/imagery/i.segment/parse_args.c	2012-07-31 03:56:38 UTC (rev 52480)
@@ -182,8 +182,8 @@
 	    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)"));
+	//~ 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
     }
 

Modified: grass-addons/grass7/imagery/i.segment/write_output.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/write_output.c	2012-07-30 16:53:28 UTC (rev 52479)
+++ grass-addons/grass7/imagery/i.segment/write_output.c	2012-07-31 03:56:38 UTC (rev 52480)
@@ -24,6 +24,7 @@
 
     /* force all data to disk */
     segment_flush(&files->bands_seg);
+    segment_flush(&files->iseg_seg);
 
     /* open output raster map */
     G_debug(1, "preparing output raster");
@@ -39,7 +40,8 @@
 	    segment_get(&files->bands_seg, (void *)files->bands_val, row,
 			col);
 	    if (!(FLAG_GET(files->null_flag, row, col))) {
-		outbuf[col] = files->iseg[row][col];
+		//              outbuf[col] = files->iseg[row][col];
+		segment_get(&files->iseg_seg, &(outbuf[col]), row, col);
 		meanbuf[col] = files->bands_val[0];
 	    }
 	}
@@ -91,9 +93,10 @@
     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);
+    //~ for (i = 0; i < files->nrows; i++)
+    //~ G_free(files->iseg[i]);
+    //~ G_free(files->iseg);
+    segment_close(&files->iseg_seg);
 
     G_debug(1, "destroying flags");
     flag_destroy(files->null_flag);



More information about the grass-commit mailing list