static int update_rid(struct globals *globals, int row, int col, int new_id) { int rown, coln, n; int neighbors[8][2]; int this_id; int ngbr_id; struct rc next; struct rclist rilist; int no_check; /* get this ID */ Segment_get(&globals->rid_seg, (void *) &this_id, row, col); Segment_put(&globals->rid_seg, (void *) &new_id, row, col); /* breadth-first search */ next.row = row; next.col = col; rclist_init(&rilist); do { globals->find_neighbors(next.row, next.col, neighbors); n = globals->nn - 1; do { rown = neighbors[n][0]; coln = neighbors[n][1]; no_check = 0; if (rown < globals->row_min || rown >= globals->row_max || coln < globals->col_min || coln >= globals->col_max) no_check = 1; if (!no_check && (FLAG_GET(globals->null_flag, rown, coln))) no_check = 1; if (!no_check) { /* get neighbour ID */ Segment_get(&globals->rid_seg, (void *) &ngbr_id, rown, coln); /* same neighbour */ if (ngbr_id == this_id) { rclist_add(&rilist, rown, coln); Segment_put(&globals->rid_seg, (void *) &new_id, rown, coln); } } } while (n--); /* end do loop - next neighbor */ } while (rclist_drop(&rilist, &next)); /* while there are cells to check */ rclist_destroy(&rilist); return 1; }
static int find_best_neighbour(struct globals *globals, int row, int col, int this_id, struct NB_TREE *nbtree, int *reg_size, struct ngbr_stats **Rbest, int *best_n_row, int *best_n_col) { int rown, coln, n, count; int neighbors[8][2]; struct rc next, ngbr_rc; struct rclist rilist; int no_check; int ngbr_id; struct RB_TREE *visited; struct ngbr_stats Ri, Rk, *Rfound; double sim, best_sim; int best_n_id; int have_Ri; Ri.mean = G_malloc(globals->datasize); Rk.mean = G_malloc(globals->datasize); nbtree_clear(nbtree); FLAG_UNSET(globals->candidate_flag, row, col); visited = rbtree_create(cmp_rc, sizeof(struct rc)); ngbr_rc.row = row; ngbr_rc.col = col; rbtree_insert(visited, &ngbr_rc); /* breadth-first search */ next.row = row; next.col = col; rclist_init(&rilist); count = 1; best_n_id = -1; best_sim = 2; do { have_Ri = 0; globals->find_neighbors(next.row, next.col, neighbors); n = globals->nn - 1; do { rown = neighbors[n][0]; coln = neighbors[n][1]; no_check = 0; if (rown < globals->row_min || rown >= globals->row_max || coln < globals->col_min || coln >= globals->col_max) no_check = 1; if (!no_check && (FLAG_GET(globals->null_flag, rown, coln))) no_check = 1; ngbr_rc.row = rown; ngbr_rc.col = coln; if (!no_check && !rbtree_find(visited, &ngbr_rc)) { rbtree_insert(visited, &ngbr_rc); /* get neighbor ID */ Segment_get(&globals->rid_seg, (void *) &ngbr_id, rown, coln); /* same neighbour */ if (ngbr_id == this_id) { count++; rclist_add(&rilist, rown, coln); FLAG_UNSET(globals->candidate_flag, rown, coln); } else { /* different neighbour */ /* compare to this cell next.row, next.col */ if (!have_Ri) { Segment_get(globals->bands_out, (void *) Ri.mean, next.row, next.col); have_Ri = 1; } Segment_get(globals->bands_out, (void *) Rk.mean, rown, coln); sim = globals->calculate_similarity(&Ri, &Rk, globals); if (best_sim > sim) { best_sim = sim; best_n_id = ngbr_id; *best_n_row = rown; *best_n_col = coln; } /* find in neighbor tree */ Rk.id = ngbr_id; if ((Rfound = nbtree_find(nbtree, &Rk))) { Rfound->count++; if (*Rbest && (*Rbest)->count < Rfound->count) *Rbest = Rfound; } else { Rk.count = 1; Rk.row = rown; Rk.col = coln; nbtree_insert(nbtree, &Rk); if (!(*Rbest)) *Rbest = nbtree_find(nbtree, &Rk); } } } } while (n--); /* end do loop - next neighbor */ } while (rclist_drop(&rilist, &next)); /* while there are cells to check */ rclist_destroy(&rilist); rbtree_destroy(visited); G_free(Ri.mean); G_free(Rk.mean); *reg_size = count; return best_n_id; }
static int check_reg_size(struct globals *globals, int minsize, int row, int col) { int rown, coln, n; int neighbors[8][2]; int this_id; int ngbr_id; LARGEINT reg_size; struct RB_TREE *visited; struct rc next, ngbr_rc; struct rclist rilist; int no_check; if (!(FLAG_GET(globals->candidate_flag, row, col))) return minsize; FLAG_UNSET(globals->candidate_flag, row, col); visited = rbtree_create(cmp_rc, sizeof(struct rc)); ngbr_rc.row = row; ngbr_rc.col = col; rbtree_insert(visited, &ngbr_rc); /* get this ID */ Segment_get(&globals->rid_seg, (void *) &this_id, row, col); /* breadth-first search */ next.row = row; next.col = col; rclist_init(&rilist); reg_size = 1; do { globals->find_neighbors(next.row, next.col, neighbors); n = globals->nn - 1; do { rown = neighbors[n][0]; coln = neighbors[n][1]; no_check = 0; if (rown < globals->row_min || rown >= globals->row_max || coln < globals->col_min || coln >= globals->col_max) no_check = 1; if (!no_check && (FLAG_GET(globals->null_flag, rown, coln))) no_check = 1; ngbr_rc.row = rown; ngbr_rc.col = coln; if (!no_check && !rbtree_find(visited, &ngbr_rc)) { rbtree_insert(visited, &ngbr_rc); /* get neighbour ID */ Segment_get(&globals->rid_seg, (void *) &ngbr_id, rown, coln); /* same neighbour */ if (ngbr_id == this_id) { reg_size++; rclist_add(&rilist, rown, coln); FLAG_UNSET(globals->candidate_flag, rown, coln); } } } while (n--); /* end do loop - next neighbor */ } while (rclist_drop(&rilist, &next)); /* while there are cells to check */ rclist_destroy(&rilist); rbtree_destroy(visited); return reg_size; }
static int read_seed(struct globals *globals, SEGMENT *seeds_seg, struct rc *Ri, int new_id) { int n, i, Ri_id, Rk_id; struct rc ngbr_rc, next; struct rclist rilist; int neighbors[8][2]; G_debug(4, "read_seed()"); /* get Ri's segment ID from input seeds */ Segment_get(seeds_seg, &Ri_id, Ri->row, Ri->col); /* set new segment id */ if (Segment_put(&globals->rid_seg, &new_id, Ri->row, Ri->col) != 1) G_fatal_error(_("Unable to write to temporary file")); /* set candidate flag */ FLAG_SET(globals->candidate_flag, Ri->row, Ri->col); /* initialize region stats */ globals->rs.count = 1; globals->rs.id = new_id; Segment_get(&globals->bands_seg, (void *)globals->bands_val, Ri->row, Ri->col); for (i = 0; i < globals->nbands; i++) { globals->rs.sum[i] = globals->bands_val[i]; globals->rs.mean[i] = globals->bands_val[i]; } /* go through seed, spreading outwards from head */ rclist_init(&rilist); rclist_add(&rilist, Ri->row, Ri->col); while (rclist_drop(&rilist, &next)) { G_debug(5, "find_pixel_neighbors for row: %d , col %d", next.row, next.col); globals->find_neighbors(next.row, next.col, neighbors); for (n = 0; n < globals->nn; n++) { ngbr_rc.row = neighbors[n][0]; ngbr_rc.col = neighbors[n][1]; if (ngbr_rc.row < 0 || ngbr_rc.row >= globals->nrows || ngbr_rc.col < 0 || ngbr_rc.col >= globals->ncols) { continue; } if (FLAG_GET(globals->null_flag, ngbr_rc.row, ngbr_rc.col)) { continue; } if (FLAG_GET(globals->candidate_flag, ngbr_rc.row, ngbr_rc.col)) { continue; } Segment_get(seeds_seg, (void *) &Rk_id, ngbr_rc.row, ngbr_rc.col); G_debug(5, "Rk ID = %d Ri ID = %d", Rk_id, Ri_id); if (Rk_id != Ri_id) { continue; } /* set segment id */ if (Segment_put(&globals->rid_seg, &new_id, ngbr_rc.row, ngbr_rc.col) != 1) G_fatal_error(_("Unable to write to temporary file")); /* set candidate flag */ FLAG_SET(globals->candidate_flag, ngbr_rc.row, ngbr_rc.col); /* add to list of cells to check */ rclist_add(&rilist, ngbr_rc.row, ngbr_rc.col); /* update region stats */ Segment_get(&globals->bands_seg, (void *)globals->bands_val, ngbr_rc.row, ngbr_rc.col); for (i = 0; i < globals->nbands; i++) { globals->rs.sum[i] += globals->bands_val[i]; } globals->rs.count++; } } if (rgtree_find(globals->reg_tree, &(globals->rs)) != NULL) { G_fatal_error(_("Segment %d is already registered!"), new_id); } /* insert into region tree */ if (globals->rs.count >= globals->min_reg_size) { for (i = 0; i < globals->nbands; i++) globals->rs.mean[i] = globals->rs.sum[i] / globals->rs.count; rgtree_insert(globals->reg_tree, &(globals->rs)); } else { if (globals->rs.count > 1) update_band_vals(Ri->row, Ri->col, &(globals->rs), globals); } if (globals->rs.count > 1) globals->n_regions -= (globals->rs.count - 1); return 1; }