[GRASS-SVN] r52505 - grass-addons/grass7/imagery/i.segment
svn_grass at osgeo.org
svn_grass at osgeo.org
Thu Aug 2 13:29:38 PDT 2012
Author: momsen
Date: 2012-08-02 13:29:32 -0700 (Thu, 02 Aug 2012)
New Revision: 52505
Modified:
grass-addons/grass7/imagery/i.segment/create_isegs.c
grass-addons/grass7/imagery/i.segment/i.segment.html
grass-addons/grass7/imagery/i.segment/iseg.h
grass-addons/grass7/imagery/i.segment/main.c
grass-addons/grass7/imagery/i.segment/open_files.c
grass-addons/grass7/imagery/i.segment/write_output.c
Log:
starting seeds methodology updated
Modified: grass-addons/grass7/imagery/i.segment/create_isegs.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/create_isegs.c 2012-08-02 13:25:40 UTC (rev 52504)
+++ grass-addons/grass7/imagery/i.segment/create_isegs.c 2012-08-02 20:29:32 UTC (rev 52505)
@@ -812,7 +812,7 @@
functions->end_t);
t = 1;
- files->candidate_count = 0;
+ //~ files->candidate_count = 0;
/*set linked list head pointers to null. */
Ri_head = NULL;
@@ -828,8 +828,8 @@
do {
#ifdef PROFILE
pass_start = clock();
+#endif
fprintf(stdout, "pass %d\n", t);
-#endif
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);
@@ -841,8 +841,8 @@
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);
+ //~ G_debug(4, "Starting to process %d candidate pixels",
+ //~ files->candidate_count);
/*process candidate pixels for this iteration */
@@ -894,7 +894,7 @@
#endif
G_debug(4, "Starting pixel from next row/col, not from Rk");
- if (FLAG_GET(files->candidate_flag, row, col)) {
+ 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);
@@ -1035,8 +1035,6 @@
Ri_similarity, Ri_bestn->row,
Ri_bestn->col);
- //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
@@ -1046,7 +1044,6 @@
* 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 */
@@ -1127,12 +1124,10 @@
/* 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);
+ //~ 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)))
+ 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) */
@@ -1151,8 +1146,8 @@
else { /* Ri didn't have a neighbor */
G_debug(4, "Segment had no neighbors");
set_candidate_flag(Ri_head, FALSE, files);
- G_debug(4, "line 176, \t\t\t\tcc = %d",
- files->candidate_count);
+ //~ G_debug(4, "line 176, \t\t\t\tcc = %d",
+ //~ files->candidate_count);
}
if (pathflag) { /*initialize Ri, Rin, Rk, Rin using Rk as Ri. */
@@ -1179,7 +1174,7 @@
}
} /*end pathflag do loop */
- } /*end if pixel is candidate pixel */
+ } /*end if pixel is candidate and seed pixel */
} /*next column (or next z) */
#ifdef ROWMAJOR
} /*next row */
@@ -1624,7 +1619,7 @@
int merge_values(struct pixels *Ri_head, struct pixels *Rk_head,
int Ri_count, int Rk_count, struct files *files)
{
- int n, Ri_iseg = 42, Rk_iseg = 43;
+ 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... */
@@ -1649,7 +1644,7 @@
//~ files->iseg[Ri_head->row][Ri_head->col]);
fprintf(stdout,
- "merging Ri (pixel count): %d (%d) with Rk (count): %d (%d).\t",
+ "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 */
@@ -1657,8 +1652,8 @@
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);
+ //~ 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) {
@@ -1666,21 +1661,60 @@
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);
+ //~ 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);
}
- /* merged two segments, decrement count
- * if seeds were provided, need to adjust the candidate_count*/
- if (files->seeds_map == NULL)
+ /* merged two segments, decrement count if Rk was an actual segment (not a non-seed pixel) */
+ if (Rk_iseg > 0)
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 */
+
+
+ //~ if (files->seeds_map != NULL) //todo delete??? or is it even correct?
+ //~ files->candidate_count += Ri_count + Rk_count - 1;
+
+ 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;
+
+ /* 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;
}
+ 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);
+ for (n = 0; n < files->nbands; 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;
+ }
+
+ /* 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);
+ }
+
+ }
+
return TRUE;
}
@@ -1695,17 +1729,17 @@
if (value == FALSE) {
FLAG_UNSET(files->candidate_flag, current->row, current->col);
- files->candidate_count--;
+ //~ files->candidate_count--;
}
else if (value == TRUE) {
FLAG_SET(files->candidate_flag, current->row, current->col);
- files->candidate_count++;
+ //~ 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);
+ //~ G_debug(4, "line 1253, \t\t\t\tcc = %d", files->candidate_count);
}
return TRUE;
}
@@ -1771,7 +1805,7 @@
{
int row, col;
- if (files->seeds_map == NULL) { /* entire map is considered as candidates */
+ //~ 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++) {
@@ -1782,7 +1816,7 @@
/* 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++;
+ //~ files->candidate_count++;
}
else
FLAG_UNSET(files->candidate_flag, row, col);
@@ -1801,20 +1835,20 @@
//~ }
//~ }
//~ }
- }
- 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...
- }
- }
- }
+ //~ }
+ //~ 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;
Modified: grass-addons/grass7/imagery/i.segment/i.segment.html
===================================================================
--- grass-addons/grass7/imagery/i.segment/i.segment.html 2012-08-02 13:25:40 UTC (rev 52504)
+++ grass-addons/grass7/imagery/i.segment/i.segment.html 2012-08-02 20:29:32 UTC (rev 52505)
@@ -1,5 +1,6 @@
<h2>DESCRIPTION</h2>
<H2>NOTES</h2>
+The final forced merge (if minsize is set > 1) ignores the (optional) seed map.
<H2>EXAMPLES</h2>
<h2>TODO</h2>
For Region Growing, the current limit with CELL storage is 2 billion starting segment ID's. Workaround: If the original image has a larger number of pixels, please use the starting seeds option to limit the number of starting segments.
Modified: grass-addons/grass7/imagery/i.segment/iseg.h
===================================================================
--- grass-addons/grass7/imagery/i.segment/iseg.h 2012-08-02 13:25:40 UTC (rev 52504)
+++ grass-addons/grass7/imagery/i.segment/iseg.h 2012-08-02 20:29:32 UTC (rev 52505)
@@ -61,13 +61,15 @@
int nsegs; /* number of segments */
/* processing flags */
+ /* candidate flag for if a cell/segment has already been merged in that pass. */
+ /* seeds flag for if a cell/segment is a seed (can be Ri to start a merge). All cells are valid seeds if a starting seeds map is not supplied. */
FLAG *candidate_flag, *null_flag, *orig_null_flag, *seeds_flag;
/* 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 */
+ //~ /* other info */
+ //~ int candidate_count; /*Number of remaining candidate pixels */
};
@@ -102,7 +104,7 @@
int parse_args(int, char *[], struct files *, struct functions *);
/* open_files.c */
-int open_files(struct files *);
+int open_files(struct files *, struct functions *);
/* create_isegs.c */
int create_isegs(struct files *, struct functions *);
@@ -117,6 +119,7 @@
struct files *, struct functions *);
int set_candidate_flag(struct pixels *, int, struct files *);
int merge_values(struct pixels *, struct pixels *, int, int, struct files *);
+int merge_pixels(struct pixels *, struct files *);
int find_four_pixel_neighbors(int, int, int[][2], struct files *);
int find_eight_pixel_neighbors(int, int, int[8][2], struct files *);
double calculate_euclidean_similarity(struct pixels *, struct pixels *,
Modified: grass-addons/grass7/imagery/i.segment/main.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/main.c 2012-08-02 13:25:40 UTC (rev 52504)
+++ grass-addons/grass7/imagery/i.segment/main.c 2012-08-02 20:29:32 UTC (rev 52505)
@@ -41,7 +41,7 @@
G_fatal_error(_("Error in parse_args()"));
G_debug(1, "Main: starting open_files()");
- if (open_files(&files) != TRUE)
+ if (open_files(&files, &functions) != TRUE)
G_fatal_error(_("Error in open_files()"));
G_debug(1, "Main: starting create_isegs()");
Modified: grass-addons/grass7/imagery/i.segment/open_files.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/open_files.c 2012-08-02 13:25:40 UTC (rev 52504)
+++ grass-addons/grass7/imagery/i.segment/open_files.c 2012-08-02 20:29:32 UTC (rev 52505)
@@ -7,7 +7,7 @@
#include <grass/segment.h> /* segmentation library */
#include "iseg.h"
-int open_files(struct files *files)
+int open_files(struct files *files, struct functions *functions)
{
struct Ref Ref; /* group reference list */
int *in_fd, seeds_fd, bounds_fd, null_check, out_fd, mean_fd;
@@ -20,6 +20,10 @@
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;
+
/* 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)
@@ -40,7 +44,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 */
@@ -175,10 +179,13 @@
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.
- segment_put(&files->iseg_seg, &s, row, col);
- G_message("set seed for row: %d, col: %d", row, col);
+// 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);
}
ptr = G_incr_void_ptr(ptr, ptrsize);
@@ -186,6 +193,7 @@
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 */
}
}
else { /*don't use this pixel */
@@ -197,8 +205,14 @@
}
/* 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 */
if (files->bounds_map != NULL) {
if (segment_open
@@ -236,8 +250,8 @@
G_debug(1, "no boundary constraint supplied.");
}
- /* other info */
- files->candidate_count = 0; /* counter for remaining candidate pixels */
+ //~ /* 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. */
@@ -247,6 +261,44 @@
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){
+
+ /*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;
+ 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*/
+ 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*/
+ merge_pixels(R_head, files);
+
+ /*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;
+ }
+ }
+ }
+
/* Free memory */
for (n = 0; n < Ref.nfiles; n++) {
Modified: grass-addons/grass7/imagery/i.segment/write_output.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/write_output.c 2012-08-02 13:25:40 UTC (rev 52504)
+++ grass-addons/grass7/imagery/i.segment/write_output.c 2012-08-02 20:29:32 UTC (rev 52505)
@@ -18,7 +18,9 @@
CELL *outbuf;
DCELL *meanbuf;
struct Colors colors;
+ struct History history;
+
outbuf = Rast_allocate_c_buf(); /* hold one row of data to put into raster */
meanbuf = Rast_allocate_d_buf();
@@ -51,13 +53,6 @@
G_percent(row, files->nrows, 1);
}
- /* TODO polish: update the data found by r.info
- * current: | Data Description: |
- * | generated by i.segment |
- * It would be nice to save the segmentation settings (just the CL? Or something more human readable?)
- * * MM: see e.g. i.pca for an example of setting custom info
- */
-
/* close and save file */
Rast_close(out_fd);
if (files->out_band != NULL)
@@ -68,6 +63,13 @@
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);
+
/* free memory */
G_free(outbuf);
G_free(meanbuf);
@@ -96,6 +98,7 @@
G_debug(1, "destroying flags");
flag_destroy(files->null_flag);
flag_destroy(files->candidate_flag);
+ flag_destroy(files->seeds_flag);
G_debug(1, "close_files() before link_cleanup()");
link_cleanup(files->token);
More information about the grass-commit
mailing list