Browse Source

i.segment update, fix mess by two people working at the module at the same time

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@55033 15284696-431f-4ddb-bdfa-cd5b030d7da7
Markus Metz 12 years ago
parent
commit
96ac4bca60

+ 105 - 70
imagery/i.segment/create_isegs.c

@@ -208,7 +208,7 @@ int region_growing(struct globals *globals)
     Rk_bestn_rs.sum = G_malloc(globals->datasize);
     Rk_bestn_rs.sum = G_malloc(globals->datasize);
     
     
     t = 0;
     t = 0;
-    n_merges = 1;
+    n_merges = 2;
 
 
     /* threshold calculation */
     /* threshold calculation */
     alpha2 = globals->alpha * globals->alpha;
     alpha2 = globals->alpha * globals->alpha;
@@ -218,7 +218,7 @@ int region_growing(struct globals *globals)
     /* make the divisor a constant ? */
     /* make the divisor a constant ? */
     divisor = globals->nrows + globals->ncols;
     divisor = globals->nrows + globals->ncols;
 
 
-    while (t < globals->end_t && n_merges > 0) {
+    while (t < globals->end_t && n_merges > 1) {
 
 
 	G_message(_("Pass %d:"), ++t);
 	G_message(_("Pass %d:"), ++t);
 
 
@@ -489,7 +489,7 @@ int region_growing(struct globals *globals)
     }
     }
 
 
     /*end t loop *//*TODO, should there be a max t that it can iterate for?  Include t in G_message? */
     /*end t loop *//*TODO, should there be a max t that it can iterate for?  Include t in G_message? */
-    if (n_merges > 0)
+    if (n_merges > 1)
 	G_message(_("Segmentation processes stopped at %d due to reaching max iteration limit, more merges may be possible"), t);
 	G_message(_("Segmentation processes stopped at %d due to reaching max iteration limit, more merges may be possible"), t);
     else
     else
 	G_message(_("Segmentation converged after %d iterations."), t);
 	G_message(_("Segmentation converged after %d iterations."), t);
@@ -571,7 +571,7 @@ int region_growing(struct globals *globals)
 						   globals);
 						   globals);
 		    }
 		    }
 
 
-		    if (do_merge) {
+		    if (Ri_nn > 0) {
 
 
 			nbtree_clear(Ri_ngbrs);
 			nbtree_clear(Ri_ngbrs);
 			
 			
@@ -1029,6 +1029,102 @@ static int search_neighbors(struct ngbr_stats *Ri,
     return 1;
     return 1;
 }
 }
 
 
+int update_band_vals(int row, int col, struct reg_stats *rs,
+                     struct globals *globals) {
+    /* update band values with sum */
+    /* rs->id must be set */
+    struct RB_TREE *rc_check_tree;	/* cells already checked */
+    struct rclist rlist;
+    struct rc next, ngbr_rc;
+    int neighbors[8][2];
+    int rid, count, n;
+    int no_check;
+    
+    G_debug(4, "update_band_vals()");
+
+    if (rs->count >= globals->min_reg_size) {
+	G_fatal_error(_("Region stats should go in tree, %d >= %d"),
+	              rs->count, globals->min_reg_size);
+    }
+
+    segment_get(&globals->rid_seg, (void *) &rid, row, col);
+    
+    if (rid != rs->id) {
+	G_fatal_error(_("Region ids are different"));
+    }
+
+    /* go through region, spreading outwards from head */
+    rclist_init(&rlist);
+
+    rc_check_tree = rbtree_create(compare_rc, sizeof(struct rc));
+    ngbr_rc.row = row;
+    ngbr_rc.col = col;
+    rbtree_insert(rc_check_tree, &ngbr_rc);
+    count = 1;
+
+    /* update region stats */
+    segment_put(&globals->bands_seg, (void *)rs->sum,
+		ngbr_rc.row, ngbr_rc.col);
+
+    next.row = row;
+    next.col = col;
+    do {
+	G_debug(5, "find_pixel_neighbors for row: %d , col %d",
+		next.row, next.col);
+
+	globals->find_neighbors(next.row, next.col, neighbors);
+
+	n = globals->nn - 1;
+	do {
+
+	    ngbr_rc.row = neighbors[n][0];
+	    ngbr_rc.col = neighbors[n][1];
+
+	    no_check = (ngbr_rc.row < 0 || ngbr_rc.row >= globals->nrows ||
+		ngbr_rc.col < 0 || ngbr_rc.col >= globals->ncols);
+
+	    if (!no_check) {
+		if ((FLAG_GET(globals->null_flag, ngbr_rc.row, ngbr_rc.col)) == 0) {
+		
+		    /* already checked ? */
+		    if (!rbtree_find(rc_check_tree, &ngbr_rc)) {
+
+			/* not yet checked, don't check it again */
+			rbtree_insert(rc_check_tree, &ngbr_rc);
+
+			segment_get(&globals->rid_seg, (void *) &rid,
+				    ngbr_rc.row, ngbr_rc.col);
+			
+			if (rid == rs->id) {
+
+			    /* want to check this neighbor's neighbors */
+			    rclist_add(&rlist, ngbr_rc.row, ngbr_rc.col);
+
+			    /* update region stats */
+			    segment_put(&globals->bands_seg,
+					(void *)rs->sum,
+					ngbr_rc.row, ngbr_rc.col);
+			    count++;
+			}
+		    }
+		}
+	    }
+	} while (n--);
+    } while (rclist_drop(&rlist, &next));
+
+    /* clean up */
+    rbtree_destroy(rc_check_tree);
+    rclist_destroy(&rlist);
+    
+    if (count != rs->count) {
+	G_fatal_error(_("Region size is %d, should be %d"),
+	              count, rs->count);
+    }
+
+    return count;
+}
+
+
 static int merge_regions(struct ngbr_stats *Ri, struct reg_stats *Ri_rs,
 static int merge_regions(struct ngbr_stats *Ri, struct reg_stats *Ri_rs,
 		         struct ngbr_stats *Rk, struct reg_stats *Rk_rs,
 		         struct ngbr_stats *Rk, struct reg_stats *Rk_rs,
 		         int do_cand, struct globals *globals)
 		         int do_cand, struct globals *globals)
@@ -1228,72 +1324,7 @@ static int merge_regions(struct ngbr_stats *Ri, struct reg_stats *Ri_rs,
     Ri->id = Ri_rs->id;
     Ri->id = Ri_rs->id;
 
 
     if (Ri_rs->count < globals->min_reg_size) {
     if (Ri_rs->count < globals->min_reg_size) {
-	/* update band values with sum */
-	/* rs->id must be set */
-	struct RB_TREE *rc_check_tree;	/* cells already checked */
-	int rid;
-	int no_check;
-	
-	/* go through region, spreading outwards from head */
-	rclist_init(&rlist);
-
-	rc_check_tree = rbtree_create(compare_rc, sizeof(struct rc));
-	ngbr_rc.row = Ri->row;
-	ngbr_rc.col = Ri->col;
-	rbtree_insert(rc_check_tree, &ngbr_rc);
-
-	/* update region stats */
-	segment_put(&globals->bands_seg, (void *)Ri_rs->sum,
-		    ngbr_rc.row, ngbr_rc.col);
-
-	next.row = Ri->row;
-	next.col = Ri->col;
-	do {
-	    G_debug(5, "find_pixel_neighbors for row: %d , col %d",
-		    next.row, next.col);
-
-	    globals->find_neighbors(next.row, next.col, neighbors);
-
-	    n = globals->nn - 1;
-	    do {
-
-		ngbr_rc.row = neighbors[n][0];
-		ngbr_rc.col = neighbors[n][1];
-
-		no_check = (ngbr_rc.row < 0 || ngbr_rc.row >= globals->nrows ||
-		    ngbr_rc.col < 0 || ngbr_rc.col >= globals->ncols);
-
-		if (!no_check) {
-		    if ((FLAG_GET(globals->null_flag, ngbr_rc.row, ngbr_rc.col)) == 0) {
-		    
-			/* already checked ? */
-			if (!rbtree_find(rc_check_tree, &ngbr_rc)) {
-
-			    /* not yet checked, don't check it again */
-			    rbtree_insert(rc_check_tree, &ngbr_rc);
-
-			    segment_get(&globals->rid_seg, (void *) &rid,
-					ngbr_rc.row, ngbr_rc.col);
-			    
-			    if (rid == Ri_rs->id) {
-
-				/* want to check this neighbor's neighbors */
-				rclist_add(&rlist, ngbr_rc.row, ngbr_rc.col);
-
-				/* update region stats */
-				segment_put(&globals->bands_seg,
-					    (void *)Ri_rs->sum,
-					    ngbr_rc.row, ngbr_rc.col);
-			    }
-			}
-		    }
-		}
-	    } while (n--);
-	} while (rclist_drop(&rlist, &next));
-
-	/* clean up */
-	rbtree_destroy(rc_check_tree);
-	rclist_destroy(&rlist);
+	update_band_vals(Ri->row, Ri->col, Ri_rs, globals);
     }
     }
 
 
     return TRUE;
     return TRUE;
@@ -1527,5 +1558,9 @@ static int calculate_reg_stats(int row, int col, struct reg_stats *rs,
 	} while (i--);
 	} while (i--);
     }
     }
     
     
+    if (rs->count >= globals->min_reg_size)
+	G_fatal_error(_("Region of size %d should be in search tree"),
+		      rs->count);
+    
     return ret;
     return ret;
 }
 }

+ 14 - 11
imagery/i.segment/i.segment.html

@@ -60,10 +60,11 @@ number of pixel sides the segment has.
 <h3>Seeds</h3>
 <h3>Seeds</h3>
 The seeds map can be used to provide either seed pixels (random or 
 The seeds map can be used to provide either seed pixels (random or 
 selected points from which to start the segmentation process) or 
 selected points from which to start the segmentation process) or 
-seed segments (results of previous segmentations or 
-classifications). The different approaches are automatically 
-detected by the program: any pixels that have identical seed values 
-and are contiguous will be assigned a unique segment ID.
+seed segments. If the seeds are the results of a previous segmentation 
+with lower threshold, hierarchical segmentation can be performed. The 
+different approaches are automatically detected by the program: any 
+pixels that have identical seed values and are contiguous will be 
+assigned a unique segment ID.
 <p>
 <p>
 It is expected that the <em>minsize</em> will be set to 1 if a seed 
 It is expected that the <em>minsize</em> will be set to 1 if a seed 
 map is used, but the program will allow other values to be used. If 
 map is used, but the program will allow other values to be used. If 
@@ -131,10 +132,12 @@ i.segment group=ortho_group output=ortho_segs_l5 threshold=0.3 \
           seeds=ortho_segs_l4
           seeds=ortho_segs_l4
 </pre></div>
 </pre></div>
 <p>
 <p>
-The output ortho_segs_l4 with threshold=0.2 looks best. There is some 
-noise in the image, lets next force all segments smaller than 5 pixels 
-to be merged into their most similar neighbor (even if they are less 
-similar then required by our threshold):<br>
+The output ortho_segs_l4 with threshold=0.2 still has too many segments, 
+but the output with threshold=0.3 has too few segments. A threshold 
+value of 0.25 seems to be a good choice. There is also some noise in 
+the image, lets next force all segments smaller than 10 pixels to be 
+merged into their most similar neighbor (even if they are less similar 
+than required by our threshold):<br>
 
 
 <p>Set the region to match the entire map(s) in the group. <br>
 <p>Set the region to match the entire map(s) in the group. <br>
 <div class="code"><pre>
 <div class="code"><pre>
@@ -145,11 +148,11 @@ Run i.segment on the full map:
 
 
 <div class="code"><pre>
 <div class="code"><pre>
 i.segment group=ortho_group output=ortho_segs_final \
 i.segment group=ortho_group output=ortho_segs_final \
-          threshold=0.2 min=5
+          threshold=0.25 min=10
 </pre></div>
 </pre></div>
 <p></p>
 <p></p>
-Processing the entire ortho image with nearly 10 million pixels took about 
-15 minutes for the first run.
+Processing the entire ortho image with nearly 10 million pixels took 
+about 20 minutes for the final run.
 
 
 <h2>TODO</h2>
 <h2>TODO</h2>
 <h3>Functionality</h3>
 <h3>Functionality</h3>

+ 1 - 0
imagery/i.segment/iseg.h

@@ -117,6 +117,7 @@ double calculate_shape(struct reg_stats *, struct reg_stats *,
                        int, struct globals *);
                        int, struct globals *);
 int fetch_reg_stats(int , int , struct reg_stats *, 
 int fetch_reg_stats(int , int , struct reg_stats *, 
                            struct globals *);
                            struct globals *);
+int update_band_vals(int, int, struct reg_stats *, struct globals *);
 
 
 /* void calculate_reg_stats(int, int, struct reg_stats *, 
 /* void calculate_reg_stats(int, int, struct reg_stats *, 
                          struct globals *); */
                          struct globals *); */

+ 1 - 1
imagery/i.segment/main.c

@@ -36,7 +36,7 @@ int main(int argc, char *argv[])
     G_add_keyword(_("segmentation"));
     G_add_keyword(_("segmentation"));
     G_add_keyword(_("object recognition"));
     G_add_keyword(_("object recognition"));
     module->description =
     module->description =
-	_("Identifies segments (objects) from imagery data.");
+	_("Identify segments (objects) from imagery.");
 
 
     parse_args(argc, argv, &globals);
     parse_args(argc, argv, &globals);
 	
 	

+ 3 - 0
imagery/i.segment/open_files.c

@@ -458,6 +458,9 @@ static int read_seed(struct globals *globals, SEGMENT *seeds_seg, struct rc *Ri,
 
 
 	rgtree_insert(globals->reg_tree, &(globals->rs));
 	rgtree_insert(globals->reg_tree, &(globals->rs));
     }
     }
+    else {
+	update_band_vals(Ri->row, Ri->col, &(globals->rs), globals);
+    }
 
 
     return 1;
     return 1;
 }
 }

+ 5 - 8
imagery/i.segment/parse_args.c

@@ -44,7 +44,7 @@ int parse_args(int argc, char *argv[], struct globals *globals)
     similarity = G_define_option();
     similarity = G_define_option();
     similarity->key = "similarity";
     similarity->key = "similarity";
     similarity->type = TYPE_STRING;
     similarity->type = TYPE_STRING;
-    similarity->required = YES;
+    similarity->required = NO;
     similarity->answer = "euclidean";
     similarity->answer = "euclidean";
     similarity->options = "euclidean,manhattan";
     similarity->options = "euclidean,manhattan";
     similarity->description = _("Similarity calculation method");
     similarity->description = _("Similarity calculation method");
@@ -65,7 +65,7 @@ int parse_args(int argc, char *argv[], struct globals *globals)
     radio_weight = G_define_option();
     radio_weight = G_define_option();
     radio_weight->key = "radio_weight";
     radio_weight->key = "radio_weight";
     radio_weight->type = TYPE_DOUBLE;
     radio_weight->type = TYPE_DOUBLE;
-    radio_weight->required = YES;
+    radio_weight->required = NO;
     radio_weight->answer = "1";
     radio_weight->answer = "1";
     radio_weight->options = "0-1";
     radio_weight->options = "0-1";
     radio_weight->label =
     radio_weight->label =
@@ -75,7 +75,7 @@ int parse_args(int argc, char *argv[], struct globals *globals)
     smooth_weight = G_define_option();
     smooth_weight = G_define_option();
     smooth_weight->key = "smooth_weight";
     smooth_weight->key = "smooth_weight";
     smooth_weight->type = TYPE_DOUBLE;
     smooth_weight->type = TYPE_DOUBLE;
-    smooth_weight->required = YES;
+    smooth_weight->required = NO;
     smooth_weight->answer = "0.5";
     smooth_weight->answer = "0.5";
     smooth_weight->options = "0-1";
     smooth_weight->options = "0-1";
     smooth_weight->label =
     smooth_weight->label =
@@ -106,24 +106,21 @@ int parse_args(int argc, char *argv[], struct globals *globals)
     seeds = G_define_standard_option(G_OPT_R_INPUT);
     seeds = G_define_standard_option(G_OPT_R_INPUT);
     seeds->key = "seeds";
     seeds->key = "seeds";
     seeds->required = NO;
     seeds->required = NO;
-    seeds->description = _("Name for output raster map with starting seeds");
-    seeds->guisection = _("Optional outputs");
+    seeds->description = _("Name for input raster map with starting seeds");
 
 
     /* Polygon constraints. */
     /* Polygon constraints. */
     bounds = G_define_standard_option(G_OPT_R_INPUT);
     bounds = G_define_standard_option(G_OPT_R_INPUT);
     bounds->key = "bounds";
     bounds->key = "bounds";
     bounds->required = NO;
     bounds->required = NO;
-    bounds->label = _("Name for output bounding/constraining raster map");
+    bounds->label = _("Name for input bounding/constraining raster map");
     bounds->description =
     bounds->description =
 	_("Must be integer values, each area will be segmented independent of the others");
 	_("Must be integer values, each area will be segmented independent of the others");
-    bounds->guisection = _("Optional outputs");
 
 
     outband = G_define_standard_option(G_OPT_R_OUTPUT);
     outband = G_define_standard_option(G_OPT_R_OUTPUT);
     outband->key = "goodness";
     outband->key = "goodness";
     outband->required = NO;
     outband->required = NO;
     outband->description =
     outband->description =
 	_("Name for output goodness of fit estimate");
 	_("Name for output goodness of fit estimate");
-    outband->guisection = _("Optional outputs");
 
 
     diagonal = G_define_flag();
     diagonal = G_define_flag();
     diagonal->key = 'd';
     diagonal->key = 'd';