[GRASS-SVN] r52092 - grass-addons/grass7/imagery/i.segment
svn_grass at osgeo.org
svn_grass at osgeo.org
Fri Jun 15 22:45:26 PDT 2012
Author: momsen
Date: 2012-06-15 22:45:26 -0700 (Fri, 15 Jun 2012)
New Revision: 52092
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/write_output.c
Log:
linked list structures in place for Ri, Rk, and neighbors. link_dispose() doesn't seem to work. Bug in algorithm at 2nd iteration.
Modified: grass-addons/grass7/imagery/i.segment/create_isegs.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/create_isegs.c 2012-06-15 23:55:32 UTC (rev 52091)
+++ grass-addons/grass7/imagery/i.segment/create_isegs.c 2012-06-16 05:45:26 UTC (rev 52092)
@@ -86,7 +86,7 @@
for (i = 0; i < 10; i++) {
#ifdef LINKM
p = (struct pixels *)link_new(head);
- link_dispose(head, (VOID_T *) p);
+ link_dispose((struct link_head *)head, (VOID_T *) p);
#else
p = (struct pixels *)G_malloc(sizeof(struct pixels));
G_free(p);
@@ -106,58 +106,23 @@
int ll_test(struct files *files, struct functions *functions)
{
- int row, col, n, m, t;
- double threshold, Ri_similarity, Rk_similarity, tempsim;
+ int row, col, n, count;
+ struct pixels *Rkn, *current, *newpixel, *Rin_head; /*current will be used to iterate over any of the linked lists. */
- /* linkm - linked list memory allocation. */
- struct link_head *Token; /* seems we can "manage multiple lists" will use one token for all lists, since all have same size elements. */
- struct pixels *Rin, *Rkn, *current, *newpixel, *Rin_head; /*current will be used to iterate over any of the linked lists. */
- int Ri[100][2], Rk[100][2]; /* 100 or so maximum members, second dimension is for: 0: row 1: col */
- int Ri_count, Rk_count; /*crutch for now, probably won't need later. */
- struct pixels *Ri_bestn; /* best neighbor pixel for Ri, not a linked list, just one pixel... */
-
- int temparray[2];
-
G_verbose_message("testing linked lists");
/*allocate linked list memory */
/*todo: should the be done in open_files, where other memory things go? or just leave here, data structure / memory for the actual segmentation? */
- G_debug(1, "setting up linked lists");
- Token = (struct link_head *)link_init(sizeof(struct pixels));
- G_debug(1, "have token");
+ //~ G_debug(1, "setting up linked lists");
+ //~ Token = (struct link_head *)link_init(sizeof(struct pixels));
+ //~ G_debug(1, "have token");
Rin_head = NULL;
+ Rkn = NULL;
-#ifdef NODEF
- /*set next pointers to null. TODO: use an element with row/col empty and NULL for next pointer? */
- Rin = (struct pixels *)link_new(Token);
- G_debug(1, "have Rin, first pixel in list");
- Rin->next = NULL;
- G_debug(1, "set pointer to NULL");
-
- Rkn = (struct pixels *)link_new(Token);
- G_debug(1, "have Rkn, first pixel in list");
- Rkn->next = NULL;
-
- Ri_bestn = (struct pixels *)link_new(Token);
- G_debug(1, "have Ri_best, first pixel in list");
- Ri_bestn->next = NULL;
-#endif
-
-#ifdef NODEF
- /* code that worked in speed test: */
- head = (struct link_head *)link_init(sizeof(struct pixels));
-
- p = (struct pixels *)link_new(head);
- link_dispose(head, (VOID_T *) p);
-
- link_cleanup(head);
-
-#endif
-
/* make a neighbor list */
for (n = 0; n < 5; n++) {
- newpixel = (struct pixels *)link_new(Token);
+ newpixel = (struct pixels *)link_new(files->token);
newpixel->next = Rin_head; /*point the new pixel to the current first pixel */
newpixel->row = n;
newpixel->col = n + 2;
@@ -168,16 +133,51 @@
}
+ for (n = 0; n < 5; n++) {
+ newpixel = (struct pixels *)link_new(files->token);
+ newpixel->next = Rkn; /*point the new pixel to the current first pixel */
+ newpixel->row = 5 * n;
+ newpixel->col = n;
+ Rkn = newpixel; /*change the first pixel to be the new pixel. */
+
+ G_message("Added: Rkn %d: row: %d, col: %d", n, Rkn->row, Rkn->col);
+
+ }
+
+
G_message(" Test pass token result: %d",
- test_pass_token(&Rin_head, Token));
+ test_pass_token(&Rin_head, files));
G_message("Printing out:");
/*print out neighbors */
for (current = Rin_head; current != NULL; current = current->next)
G_debug(1, "Rin: row: %d, col: %d", current->row, current->col);
+ for (current = Rkn; current != NULL; current = current->next)
+ G_debug(1, "Rkn: row: %d, col: %d", current->row, current->col);
+ /* remove all from Rkn list, 5 from Rin list */
+ for (n = 0; n < 5; n++) {
+ current = Rin_head; /* get first in list */
+ Rin_head = current->next; /* point head to the next one *//*pop */
+ link_dispose((struct link_head *)current, (VOID_T *) files->token);
+ }
+
+ for (current = Rkn; current != NULL; current = current->next) {
+ link_dispose((struct link_head *)current, (VOID_T *) files->token);
+ }
+ Rkn = NULL; /* TODO: if emptying whole list - can just empty and then set head to null ? */
+
+ G_message("Printing out, after removed:");
+ /*print out neighbors */
+ for (current = Rin_head; current != NULL; current = current->next)
+ G_debug(1, "Rin: row: %d, col: %d", current->row, current->col);
+
+ for (current = Rkn; current != NULL; current = current->next)
+ G_debug(1, "Rkn: row: %d, col: %d", current->row, current->col);
+
+
/* **************write fake data to test I/O portion of module */
G_verbose_message("writing fake data to segmentation file");
@@ -191,19 +191,43 @@
}
}
- link_cleanup((struct link_head *)Token);
+ /*test how many pixels can be made and disposed of */
+ for (n = 0; n < functions->threshold; n++) {
+ /*make tokens */
+ test_pass_token(&Rkn, files);
+ count += 5;
+ G_debug(1, "estimate of tokens created %d", count);
+ /*dispose tokens */
+ for (current = Rkn; current != NULL; current = current->next)
+ link_dispose((struct link_head *)Rkn, (VOID_T *) files->token);
+
+ G_debug(1, "are they gone?");
+ for (current = Rkn; current != NULL; current = current->next)
+ G_debug(1, "Rkn: row: %d, col: %d", current->row, current->col);
+
+ Rkn = NULL; /* TODO: if emptying whole list - can just empty and then set head to null ? */
+
+ G_debug(1,
+ "Checking after set head to null.... TODO: anyway to find out if linkm memory manager knows they are gone???");
+ for (current = Rkn; current != NULL; current = current->next)
+ G_debug(1, "Rkn: row: %d, col: %d", current->row, current->col);
+
+
+ }
+
+
G_message("end linked list test");
return 0;
}
-int test_pass_token(struct pixels **head, struct link_head *token)
+int test_pass_token(struct pixels **head, struct files *files)
{
int n;
struct pixels *newpixel;
for (n = 10; n < 15; n++) {
- newpixel = (struct pixels *)link_new(token);
+ newpixel = (struct pixels *)link_new(files->token);
newpixel->next = *head; /*point the new pixel to the current first pixel */
newpixel->row = n;
newpixel->col = n * 2;
@@ -218,7 +242,7 @@
int region_growing(struct files *files, struct functions *functions)
{
- int row, col, n, m, t;
+ int row, col, t;
double threshold, Ri_similarity, Rk_similarity, tempsim;
int endflag; /* =1 if there were no merges on that processing iteration */
int pathflag; /* =1 if we didn't find mutual neighbors, and should continue with Rk */
@@ -234,14 +258,11 @@
/* lets get this running, and just use fixed dimension arrays for now. t is limited to 90, segments will be small. */
/* linkm - linked list memory allocation. */
- struct link_head *Token; /* seems we can "manage multiple lists" will use one token for all lists, since all have same size elements. */
- struct pixels *Rin, *Rkn, *current; /*current will be used to iterate over any of the linked lists. */
- int Ri[100][2], Rk[100][2]; /* 100 or so maximum members, second dimension is for: 0: row 1: col */
- int Ri_count, Rk_count; /*crutch for now, probably won't need later. */
- struct pixels *Ri_bestn; /* best neighbor pixel for Ri, not a linked list, just one pixel... */
+ //~ struct link_head *Token; /* seems we can "manage multiple lists" will use one token for all lists, since all have same size elements. */
+ struct pixels *Ri_head, *Rk_head, *Rin_head, *Rkn_head, *current, *newpixel; /*current will be used to iterate over any of the linked lists. */
+ int Ri_count, Rk_count; /*TODO when to calculate these. */
+ struct pixels *Ri_bestn; /* best neighbor pixel for Ri, don't use as a linked list, just one pixel... */
- int temparray[2];
-
G_verbose_message("Running region growing algorithm");
t = 0;
@@ -249,17 +270,15 @@
/*allocate linked list memory */
- /*todo: should this be done in open_files, where other memory things go? or just leave here, data structure / memory for the actual segmentation? */
- Token = (struct link_head *)link_init(sizeof(struct pixels));
- /*set next pointers to null. TODO: use an element with row/col empty and NULL for next pointer? */
- Rin = (struct pixels *)link_new(Token);
- Rin->next = NULL;
- Rkn = (struct pixels *)link_new(Token);
- Rkn->next = NULL;
- Ri_bestn = (struct pixels *)link_new(Token);
- Ri_bestn->next = NULL;
- G_debug(1, "Have 'head' pixel's allocated from linkm");
+ /* done in open_files() */
+ /*set next pointers to null. */
+ Ri_head = NULL;
+ Rk_head = NULL;
+ Rin_head = NULL;
+ Rkn_head = NULL;
+ Ri_bestn = NULL;
+
do {
/* do while loop on t to slowly lower threshold. also check that endflag==0 (no merges were made) */
@@ -304,63 +323,48 @@
segment_get(&files->out_seg, (void *)files->out_val, row, col); /*TODO small time savings - if candidate_count reaches zero, bail out of these loops too? */
if (files->out_val[1] == 1) { /* out_val[1] is the candidate pixel flag, want to process the 1's */
- /* ... need to switch to lists/stacks/maps... */
-
- /*need to empty/reset Ri, Rn, and Rk */
- /* TODO: this will be different when Ri is different data structure. */
- for (n = 0; n < 100; n++) {
- for (m = 0; m < 2; m++) {
- Ri[n][m] = Rk[n][m] = 0;
- }
- }
+ /*free memory for linked lists */
+ my_dispose(&Ri_head, files);
+ my_dispose(&Rk_head, files);
+ my_dispose(&Rin_head, files);
+ my_dispose(&Rkn_head, files); /* TODO, better style for repeating this for all structures? */
Rk_count = 0;
- /*free memory for linked lists */
- for (current = Rin; Rin->next != NULL;
- current = current->next) {
- link_dispose(Token, (VOID_T *) current);
- }
- Rin = current; /* this should be the "empty" slot at the end of the list. */
-
- for (current = Rkn; Rkn->next != NULL;
- current = current->next) {
-
- link_dispose(Token, (VOID_T *) current);
- }
- Rkn = current; /* this should be the "empty" slot at the end of the list. */
-
/* First pixel in Ri is current pixel. We may add more later if it is part of a segment */
- Ri_count = 1; /*we'll have the focus pixel to start with. */
+ Ri_count = 1; /* TODO, count as we go, or when process? */
+ newpixel = (struct pixels *)link_new(files->token);
+ newpixel->next = Ri_head;
+ newpixel->row = row;
+ newpixel->col = col;
+ Ri_head = newpixel;
- Ri[0][0] = row;
- Ri[0][1] = col;
-
pathflag = 1;
// while (pathflag == 1 && files->candidate_count > 0) { /*if don't find mutual neighbors on first try, will use Rk as next Ri. */
G_debug(1, "Next starting pixel: row, %d, col, %d",
- Ri[0][0], Ri[0][1]);
+ Ri_head->row, Ri_head->col);
/* Setting Ri to be not a candidate allows using "itself" when at edge of raster.
* Otherwise need to use a list/count/something to know the number of pixel neighbors */
- set_candidate_flag(Ri, 0, 0, files); /* TODO: error trap? */
+ set_candidate_flag(Ri_head, 0, files); /* TODO: error trap? */
G_debug(1, "line 165, \t\t\t\tcc = %d",
files->candidate_count);
/* find segment neighbors */
if (find_segment_neighbors
- (Ri, Rin, &Ri_count, files, functions, Token) != 0) {
+ (&Ri_head, &Rin_head, &Ri_count, files,
+ functions) != 0) {
G_fatal_error("find_segment_neighbors() failed");
}
- /*TODO: for above function call, Rin is a pointer... so passing the pointer allows the what Rin is pointing at to be changed. I hope! */
- if (Rin->next != NULL) {
+
+ if (Rin_head == NULL) {
G_debug(1, "2a, Segment had no valid neighbors"); /*this could happen if there is a segment surrounded by pixels that have already been processed */
pathflag = 0;
Ri_count = 0;
- set_candidate_flag(Ri, Ri_count, 0, files); /* TODO: error trap? */
+ set_candidate_flag(Ri_head, 0, files); /* TODO: error trap? */
files->candidate_count++; /* already counted out Ri[0]; */
G_debug(1, "line 176, \t\t\t\tcc = %d",
files->candidate_count);
@@ -369,73 +373,81 @@
G_debug(1, "2b, Found Ri's pixels");
/*print out neighbors */
- for (n = 0; n < Ri_count; n++)
- G_debug(1, "Ri %d: row: %d, col: %d", n, Ri[n][0],
- Ri[n][1]);
+ for (current = Ri_head; current != NULL;
+ current = current->next)
+ G_debug(1, "Ri: row: %d, col: %d", current->row,
+ current->col);
+
+
G_debug(1, "2b, Found Ri's neighbors");
/*print out neighbors */
- for (current = Rin; Rin->next != NULL;
+ for (current = Rin_head; current != NULL;
current = current->next)
- G_debug(1, "Rin %d: row: %d, col: %d", n,
- Rin->row, Rin->col);
+ G_debug(1, "Rin: row: %d, col: %d", current->row,
+ current->col);
/* find Ri's most similar neighbor */
Ri_bestn = NULL;
Ri_similarity = LDBL_MAX; /* set current similarity to max value */
- segment_get(&files->bands_seg, (void *)files->bands_val, Ri[0][0], Ri[0][1]); /* current segment values */
+ segment_get(&files->bands_seg, (void *)files->bands_val, Ri_head->row, Ri_head->col); /* current segment values */
- for (current = Rin; Rin->next != NULL; current = current->next) { /* for each of Ri's neighbors */
- temparray[0] = current->row;
- temparray[1] = current->col; /* TODO, change calc sim to accept pixels parameter instead of array */
-
- tempsim = (*functions->calculate_similarity) (Ri[0], temparray, files, functions); /*TODO: does this pass just the single point, row/col ???? */
+ for (current = Rin_head; current != NULL; current = current->next) { /* for each of Ri's neighbors */
+ tempsim =
+ (*functions->calculate_similarity) (Ri_head,
+ current,
+ files,
+ functions);
G_debug(1,
"simularity = %g for neighbor : row: %d, col %d.",
tempsim, current->row, current->col);
if (tempsim < Ri_similarity) {
Ri_similarity = tempsim;
- Ri_bestn = current; /*TODO want to point to the current pixel... when current changes need this to stay put! */
+ Ri_bestn = current; /*TODO want to point to the current pixel...confirm when current changes need this to stay put! */
+ G_debug(1,
+ "Current lowest Ri_similarity = %g, for neighbor pixel row: %d col: %d",
+ Ri_similarity, Ri_bestn->row,
+ Ri_bestn->col);
}
}
- G_debug(1,
- "Lowest Ri_similarity = %g, for neighbor pixel row: %d col: %d",
- Ri_similarity, Ri_bestn->row, Ri_bestn->col);
+ if (Ri_bestn != NULL)
+ G_debug(1,
+ "Lowest Ri_similarity = %g, for neighbor pixel row: %d col: %d",
+ Ri_similarity, Ri_bestn->row,
+ Ri_bestn->col);
if (Ri_bestn != NULL && Ri_similarity < threshold) { /* small TODO: should this be < or <= for threshold? */
/* we'll have the neighbor pixel to start with. */
G_debug(1, "3a: Working with Rk");
+ Ri_bestn->next = NULL; /* Don't want to carry any of the other pixels with this one... */
Rk_count = 1;
- Rk[0][0] = Ri_bestn->row;
- Rk[0][1] = Ri_bestn->col;
+ Rk_head = Ri_bestn; /* TODO, OK like this? Maybe forget Ri_bestn, just use Rk from the beginning? */
/* TODO need to copy the data, not just use Ri itself! *//* Rkn = Ri; *//* we know Ri should be a neighbor of Rk *//*Todo: is there a way to skip similarity calculations on these? keep a count, and pop them before doing the similarity check? */
- find_segment_neighbors(Rk, Rkn, &Rk_count, files, functions, Token); /* data structure for Rk's neighbors, and pixels in Rk if we don't already have it */
+ find_segment_neighbors(&Rk_head, &Rkn_head, &Rk_count, files, functions); /* data structure for Rk's neighbors, and pixels in Rk if we don't already have it */
G_debug(1, "Found Rk's pixels");
/*print out neighbors */
- for (n = 0; n < Rk_count; n++)
- G_debug(1, "Rk %d: row: %d, col: %d", n,
- Rk[n][0], Rk[n][1]);
+ for (current = Rk_head; current != NULL;
+ current = current->next)
+ G_debug(1, "Rk: row: %d, col: %d",
+ current->row, current->col);
G_debug(1, "Found Rk's neighbors");
/*print out neighbors */
+ for (current = Rkn_head; current != NULL;
+ current = current->next)
+ G_debug(1, "Rkn: row: %d, col: %d",
+ current->row, current->col);
- for (current = Rkn; Rkn->next != NULL;
- current = current->next) {
- G_debug(1, "Rkn : row: %d, col: %d", Rkn->row,
- Rkn->col);
- }
/*find Rk's most similar neighbor */
Rk_similarity = Ri_similarity; /*Ri gets first priority - ties won't change anything, so we'll accept Ri and Rk as mutually best neighbors */
- segment_get(&files->bands_seg, (void *)files->bands_val, Rk[0][0], Rk[0][1]); /* current segment values */
+ segment_get(&files->bands_seg, (void *)files->bands_val, Rk_head->row, Rk_head->col); /* current segment values */
- for (current = Rkn; Rkn->next != NULL; current = current->next) { /* for each of Rk's neighbors */
- temparray[0] = current->row;
- temparray[1] = current->col; /* TODO, change calc sim to accept pixels parameter instead of array */
- tempsim = functions->calculate_similarity(Rk[0], temparray, files, functions); /*TODO: need an error trap here, if something goes wrong with calculating similarity? */
+ for (current = Rkn_head; current != NULL; current = current->next) { /* for each of Rk's neighbors */
+ tempsim = functions->calculate_similarity(Rk_head, current, files, functions); /*TODO: need an error trap here, if something goes wrong with calculating similarity? */
if (tempsim < Rk_similarity) {
Rk_similarity = tempsim;
break; /* exit for Rk's neighbors loop here, we know that Ri and Rk aren't mutually best neighbors */
@@ -444,7 +456,7 @@
if (Rk_similarity == Ri_similarity) { /* so they agree, both are mutually most similar neighbors, none of Rk's other neighbors were more similar */
/* TODO: put these steps in merge_segments(Ri, Rk) function? */
- merge_values(Ri, Rk, Ri_count, Rk_count, files); /* TODO error trap */
+ merge_values(Ri_head, Rk_head, Ri_count, Rk_count, files); /* TODO error trap */
endflag = 0; /* we've made at least one merge, so need another t iteration */
pathflag = 0; /* go to next row,column pixel - end of Rk -> Ri chain since we found mutual best neighbors */
}
@@ -454,7 +466,7 @@
Ri_similarity, Rk_similarity);
/* did this at beginning of trail loop */
- set_candidate_flag(Ri, Ri_count, 0, files); /* remove all Ri members from candidate pixels (set flag) */
+ set_candidate_flag(Ri_head, 0, files); /* remove all Ri members from candidate pixels (set flag) */
files->candidate_count++; /* add one back, we had already set Ri[0] flag at the beginning. */
G_debug(1, "line 247, \t\t\t\tcc = %d",
files->candidate_count);
@@ -488,19 +500,18 @@
/* free memory *//*TODO: anything else? */
- link_cleanup((struct link_head *)Token);
+ /* in close_files() link_cleanup((struct link_head *)Token); */
return 0;
}
-int find_segment_neighbors(int Ri[][2], struct pixels *neighbors,
- int *seg_count, struct files *files,
- struct functions *functions,
- struct link_head *token)
+int find_segment_neighbors(struct pixels **R_head,
+ struct pixels **neighbors_head, int *seg_count,
+ struct files *files, struct functions *functions)
{
// G_debug(1, "\tin find_segment_neighbors()");
int n, m, Ri_seg_ID = -1;
- struct pixels *newpixel;
+ struct pixels *newpixel, *current;
/* neighbor list will be a listing of pixels that are neighbors? Include segment numbers? Only include unique segments?
* Maybe the most complete return would be a structure array, structure to include the segment ID and a list of points in it?
@@ -508,12 +519,12 @@
*/
- /* parameter: Ri, current segment membership, could be single pixel or list of pixels. */
+ /* parameter: R, current segment membership, could be single pixel or list of pixels. */
/* parameter: neighbors/Rin, neighbor pixels, could have a list already, or could be empty ? Or just the head of a list? */
/* TODO local data structures... but maybe they should be allocated out in the main function, is it really slow to create/free on each pass? */
- int to_check[100][2]; /* queue or stack - need to check the neighbors of these pixels */
+ struct pixels *to_check; /* need to check the neighbors of these pixels */
/* put no_check in files structure for now... */
/* int[100][2] no_check; *//* sorted array or btree: list of pixels (by row / column ?) that have been put into the to_check queue, been processed, or are not candidate pixels */
@@ -523,9 +534,9 @@
int pixel_neighbors[8][2]; /* TODO: data type? put in files to allocate memory once? */
- int current_pixel = 0; /* TODO: for now, row index for pixel_neighbors[][]. With linked list will be the popped pixel in each loop. */
+ /*int current_pixel = 0; *//* TODO: for now, row index for pixel_neighbors[][]. With linked list will be the popped pixel in each loop. */
- /* Notes, these are in fucntions structure:
+ /* Notes, these are in functions structure:
* functions->num_pn int, 4 or 8, for number of pixel neighbors */
/*initialize data.... TODO: maybe remember min max row/col that was looked at each time, initialize in open_files, and reset smaller region at end of this functions */
@@ -536,46 +547,59 @@
}
}
- for (n = 0; n < 100; n++) {
- for (m = 0; m < 2; m++) {
- to_check[n][m] = 0;
- }
- }
+ to_check = NULL;
/* Put Ri in to be checked and no check lists (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 (n = 0; n < *seg_count; n++) {
- to_check[n][0] = Ri[n][0];
- to_check[n][1] = Ri[n][1];
+ for (current = *R_head; current != NULL; current = current->next) {
+
+ 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. */
+
val_no_check = 1;
- segment_put(&files->no_check, &val_no_check, Ri[n][0], Ri[n][1]);
-
+ segment_put(&files->no_check, &val_no_check, current->row,
+ current->col);
}
/* 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 */
/* get Ri's segment ID */
- segment_get(&files->out_seg, (void *)files->out_val, Ri[0][0], Ri[0][1]);
+ segment_get(&files->out_seg, (void *)files->out_val, (*R_head)->row,
+ (*R_head)->col);
Ri_seg_ID = files->out_val[0];
- while (current_pixel >= 0) { /* change to not empty once there is a linked list... */
- G_debug(1, "\tfind neighbors(): current_pixel: %d", current_pixel);
- /* current_pixel = pop next to_check element; */
+ while (to_check != NULL) { /* removing from to_check list as we go, NOT iterating over the list. */
+ G_debug(1,
+ "\tfind neighbors(): head to_check pixel: row: %d, col: %d",
+ to_check->row, to_check->col);
+ /* current_pixel = just use to_check - the row/col, and remove at end */
G_debug(1,
- "\tbefore fpn: to_check[current_pixel][0] %d , to_check[current_pixel][1] %d",
- to_check[current_pixel][0], to_check[current_pixel][1]);
+ "\tfind_pixel_neighbors for row: %d , col %d",
+ to_check->row, to_check->col);
- functions->find_pixel_neighbors(to_check[current_pixel][0],
- to_check[current_pixel][1],
+ functions->find_pixel_neighbors(to_check->row,
+ to_check->col,
pixel_neighbors, files);
- current_pixel--; /* Done using this pixels coords, now check neighbors and add to the lists */
- G_debug(1,
- "\tafter fpn: to_check[current_pixel][0] %d , to_check[current_pixel][1] %d",
- to_check[current_pixel][0], to_check[current_pixel][1]);
+ /* 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((struct link_head *)current, (VOID_T *) files->token);
+
+ /*print out to_check */
+ G_debug(1, "remaining pixel's in to_check, after popping:");
+ for (current = to_check; current != NULL; current = current->next)
+ G_debug(1, "to_check... row: %d, col: %d", current->row,
+ current->col);
+
+ /*now check the pixel neighbors and add to the lists */
+
/*debug what neighbors were found: */
/* for (n = 0; n < functions->num_pn; n++){
G_debug(1, "\tpixel_neighbors[n][0]: %d, pixel_neighbors[n][1]: %d", pixel_neighbors[n][0], pixel_neighbors[n][1]);
@@ -586,13 +610,12 @@
segment_get(&files->no_check, &val_no_check,
pixel_neighbors[n][0], pixel_neighbors[n][1]);
G_debug(1,
- "\twith pixel neighbor %d, row: %d col: %d, val_no_check = %d",
+ "\twith pixel neigh %d, row: %d col: %d, val_no_check = %d",
n, pixel_neighbors[n][0], pixel_neighbors[n][1],
val_no_check);
if (val_no_check == 0) { /* want to check this neighbor */
val_no_check = 1;
- segment_put(&files->no_check, &val_no_check,
- pixel_neighbors[n][0], pixel_neighbors[n][1]);
+ segment_put(&files->no_check, &val_no_check, pixel_neighbors[n][0], pixel_neighbors[n][1]); /* don't check it again */
segment_get(&files->out_seg, (void *)files->out_val, pixel_neighbors[n][0], pixel_neighbors[n][1]); /*TODO : do I need a second "out_val" data structure? */
@@ -603,30 +626,47 @@
if (files->out_val[0] == Ri_seg_ID) {
G_debug(1, "\tputing pixel_neighbor in Ri");
/* put pixel_neighbor[n] in Ri */
- Ri[*seg_count][0] = pixel_neighbors[n][0];
- Ri[*seg_count][1] = pixel_neighbors[n][1];
+ 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(1, "\t*seg_count now = %d", *seg_count);
/* put pixel_neighbor[n] in to_check -- want to check this pixels neighbors */
- current_pixel++;
- to_check[current_pixel][0] = pixel_neighbors[n][0];
- to_check[current_pixel][1] = pixel_neighbors[n][1];
+ 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 {
/* put pixel_neighbor[n] in Rin */
-
- newpixel = (struct pixels *)link_new(token);
- newpixel->next = neighbors; /*point the new pixel to the current first pixel */
+ G_debug(1, "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 = newpixel; /*change the first pixel to be the new pixel. */
+ *neighbors_head = newpixel; /*change the first pixel to be the new pixel. */
}
} /*end if valid candidate pixel */
+ else
+ G_debug(1, "pixel was not a valid candidate pixel");
+
} /*end if for pixel_neighbor was in "don't check" list */
- } /* end for loop - next neighbor */
+ } /* end for loop - next pixel neighbor */
+ G_debug(1,
+ "remaining pixel's in to_check, after processing the last pixel's neighbors:");
+ for (current = to_check; current != NULL; current = current->next)
+ G_debug(1, "to_check... row: %d, col: %d", current->row,
+ current->col);
+
+
+
} /* while to_check has more elements */
return 0;
@@ -687,14 +727,15 @@
/* similarity / distance between two points based on their input raster values */
/* assumes first point values already saved in files->bands_seg - only run segment_get once for that value... */
/* TODO: segment_get already happened for a[] values in the main function. Could remove a[] from these parameters */
-double calculate_euclidean_similarity(int a[2], int b[2], struct files *files,
+double calculate_euclidean_similarity(struct pixels *a, struct pixels *b,
+ struct files *files,
struct functions *functions)
{
double val = 0;
int n;
- /* get values for point b[] */
- segment_get(&files->bands_seg, (void *)files->second_val, b[0], b[1]);
+ /* get values for pixel b */
+ segment_get(&files->bands_seg, (void *)files->second_val, b->row, b->col);
/* euclidean distance, sum the square differences for each dimension */
for (n = 0; n < files->nbands; n++) {
@@ -707,16 +748,17 @@
}
-int merge_values(int Ri[100][2], int Rk[100][2], int Ri_count, int Rk_count,
- struct files *files)
+int merge_values(struct pixels *Ri_head, struct pixels *Rk_head, int Ri_count,
+ int Rk_count, struct files *files)
{ /* TODO: correct assumption that this should be a weighted mean. */
int n;
+ struct pixels *current;
/*get input values, maybe if handle earlier gets correctly this can be avoided. */
- segment_get(&files->bands_seg, (void *)files->bands_val, Ri[0][0],
- Ri[0][1]);
- segment_get(&files->bands_seg, (void *)files->second_val, Rk[0][0],
- Rk[0][1]);
+ segment_get(&files->bands_seg, (void *)files->bands_val, Ri_head->row,
+ Ri_head->col);
+ segment_get(&files->bands_seg, (void *)files->second_val, Rk_head->row,
+ Rk_head->col);
for (n = 0; n < files->nbands; n++) {
files->bands_val[n] =
@@ -726,7 +768,8 @@
/* update segment number and process flag ==0 */
- segment_get(&files->out_seg, (void *)files->out_val, Ri[0][0], Ri[0][1]);
+ segment_get(&files->out_seg, (void *)files->out_val, Ri_head->row,
+ Ri_head->col);
files->out_val[1] = 0; /*candidate pixel flag, only one merge allowed per t iteration */
/* if separate out candidate flag, can do all changes with helper function...otherwise remember: */
@@ -735,23 +778,23 @@
files->out_val[0]);
/* for each member of Ri and Rk, write new average bands values and segment values */
- for (n = 0; n < Ri_count; n++) {
- segment_put(&files->bands_seg, (void *)files->bands_val, Ri[n][0],
- Ri[n][1]);
- segment_put(&files->out_seg, (void *)files->out_val, Ri[n][0],
- Ri[n][1]);
+ for (current = Ri_head; current != NULL; current = current->next) {
+ segment_put(&files->bands_seg, (void *)files->bands_val, current->row,
+ current->col);
+ segment_put(&files->out_seg, (void *)files->out_val, current->row,
+ current->col);
files->candidate_count--;
G_debug(1, "line 508, \t\t\t\tcc = %d", files->candidate_count);
- G_debug(1, "\t\tRi row: %d, col: %d", Ri[n][0], Ri[n][1]);
+ G_debug(1, "\t\tRi row: %d, col: %d", current->row, current->col);
}
- for (n = 0; n < Rk_count; n++) {
- segment_put(&files->bands_seg, (void *)files->bands_val, Rk[n][0],
- Rk[n][1]);
- segment_put(&files->out_seg, (void *)files->out_val, Rk[n][0],
- Rk[n][1]);
+ for (current = Rk_head; current != NULL; current = current->next) {
+ segment_put(&files->bands_seg, (void *)files->bands_val, current->row,
+ current->col);
+ segment_put(&files->out_seg, (void *)files->out_val, current->row,
+ current->col);
files->candidate_count--;
G_debug(1, "line 516, \t\t\t\tcc = %d", files->candidate_count);
- G_debug(1, "\t\tRk row: %d, col: %d", Rk[n][0], Rk[n][1]);
+ G_debug(1, "\t\tRk row: %d, col: %d", current->row, current->col);
}
@@ -761,18 +804,16 @@
}
/* TODO.. helper function, maybe make more general? */
-int set_candidate_flag(int Ri[100][2], int count, int value,
- struct files *files)
+int set_candidate_flag(struct pixels *head, int value, struct files *files)
{
- /* Ri is list of pixels, value is new value of flag */
- int n;
+ /* head is linked list of pixels, value is new value of flag */
+ struct pixels *current;
- /* TODO: Ri data structure... eventually just need to process all pixels in Ri. */
- for (n = 0; n <= count; n++) {
- segment_get(&files->out_seg, (void *)files->out_val, Ri[n][0], Ri[n][1]); /* this may change... */
+ for (current = head; current != NULL; current = current->next) {
+ segment_get(&files->out_seg, (void *)files->out_val, current->row, current->col); /* this may change... */
files->out_val[1] = value; /*candidate pixel flag */
- segment_put(&files->out_seg, (void *)files->out_val, Ri[n][0],
- Ri[n][1]);
+ segment_put(&files->out_seg, (void *)files->out_val, current->row,
+ current->col);
/* also increment how many pixels remain to be processed */
@@ -785,3 +826,16 @@
}
return 0;
}
+
+/* let memory manager know space is available again and reset head to NULL */
+int my_dispose(struct pixels **head, struct files *files)
+{
+ struct pixels *current;
+
+ for (current = *head; current != NULL; current = current->next)
+ link_dispose((struct link_head *)current, (VOID_T *) files->token);
+
+ *head = NULL;
+
+ return 0;
+}
Modified: grass-addons/grass7/imagery/i.segment/iseg.h
===================================================================
--- grass-addons/grass7/imagery/i.segment/iseg.h 2012-06-15 23:55:32 UTC (rev 52091)
+++ grass-addons/grass7/imagery/i.segment/iseg.h 2012-06-16 05:45:26 UTC (rev 52092)
@@ -15,6 +15,14 @@
#include <grass/segment.h>
#include <grass/linkm.h>
+/* pixel stack */
+struct pixels
+{
+ struct pixels *next;
+ int row;
+ int col;
+};
+
struct files
{
/* user parameters */
@@ -34,6 +42,8 @@
SEGMENT no_check; /* pixels that have already been checked during this neighbor finding routine */
+ struct link_head *token; /* for linkm linked list memory management. */
+
/* RASTER_MAP_TYPE data_type; Removed: input is always DCELL, output is CELL.
* TODO: if input might be smaller then DCELL, we could detect size and allocate accordingly. */
/*
@@ -63,21 +73,14 @@
/* Some function pointers to set one time in parse_args() */
int (*find_pixel_neighbors) (int, int, int[8][2], struct files *); /*parameters: row, col, pixel_neighbors */
- double (*calculate_similarity) (int[2], int[2], struct files *, /*parameters: two points (row,col) to compare */
- struct functions *);
+ double (*calculate_similarity) (struct pixels *, struct pixels *, struct files *, struct functions *); /*parameters: two points (row,col) to compare */
+
int num_pn; /* number of pixel neighbors int, 4 or 8. TODO: can remove if pixel neighbors is list instead of array. But maybe this one is small enough that is faster as array? */
float threshold; /* similarity threshold */
};
-/* pixel stack */
-struct pixels
-{
- struct pixels *next;
- int row;
- int col;
-};
/* parse_args.c */
/* gets input from user, validates, and sets up functions */
@@ -90,17 +93,17 @@
int create_isegs(struct files *, struct functions *);
int io_debug(struct files *, struct functions *);
int ll_test(struct files *, struct functions *);
-int test_pass_token(struct pixels **, struct link_head *);
+int test_pass_token(struct pixels **, struct files *);
int region_growing(struct files *, struct functions *);
-int find_segment_neighbors(int[][2], struct pixels *, int *, struct files *, struct functions *, struct link_head *); /* TODO: need data structure for Ri, Rin */
-int set_candidate_flag(int[100][2], int, int, struct files *);
-int merge_values(int[100][2], int[100][2], int, int, struct files *); /* I assume this is a weighted mean? */
+int find_segment_neighbors(struct pixels **, struct pixels **, int *, struct files *, struct functions *); /* TODO: need data structure for Ri, Rin */
+int set_candidate_flag(struct pixels *, int, struct files *);
+int merge_values(struct pixels *, struct pixels *, int, int, struct files *); /* I assume this is a weighted mean? */
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(int[2], int[2], struct files *,
- struct functions *);
+double calculate_euclidean_similarity(struct pixels *, struct pixels *,
+ struct files *, struct functions *);
+int my_dispose(struct pixels **, struct files *);
-
/* write_output.c */
int write_output(struct files *);
int close_files(struct files *);
Modified: grass-addons/grass7/imagery/i.segment/open_files.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/open_files.c 2012-06-15 23:55:32 UTC (rev 52091)
+++ grass-addons/grass7/imagery/i.segment/open_files.c 2012-06-16 05:45:26 UTC (rev 52092)
@@ -125,6 +125,12 @@
files->candidate_count = 0; /* counter for remaining candidate pixels */
+
+ /* linked list memory management linkm */
+ link_set_chunk_size(10000); /* TODO: fine tune this number - high for now with dispose not working! */
+ files->token = (struct link_head *)link_init(sizeof(struct pixels));
+
+
/* 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-06-15 23:55:32 UTC (rev 52091)
+++ grass-addons/grass7/imagery/i.segment/write_output.c 2012-06-16 05:45:26 UTC (rev 52092)
@@ -9,7 +9,7 @@
int write_output(struct files *files)
{
- int out_fd, row, col, n;
+ int out_fd, row, col;
CELL *outbuf;
outbuf = Rast_allocate_c_buf(); /*hold one row of data to put into raster */
@@ -56,6 +56,12 @@
G_free(files->second_val);
G_free(files->out_val);
+ G_debug(1, "close_files() before link_cleanup()");
+ /* link_cleanup((struct link_head *)files->token); */
+ link_cleanup(files->token);
+ G_debug(1, "close_files() after link_cleanup()");
+
+
/* anything else left to clean up? */
return 0;
More information about the grass-commit
mailing list