void test_collapsing_find_simple(CuTest* tc) { label_t equivs[] = {0, 0, 1, 2}; /* 0 1 2 3 */ label_t minlabel = collapsing_find_minlabel(3, equivs); CuAssertIntEquals(tc, minlabel, 0); CuAssertIntEquals(tc, equivs[0], 0); CuAssertIntEquals(tc, equivs[1], 0); CuAssertIntEquals(tc, equivs[2], 0); CuAssertIntEquals(tc, equivs[3], 0); }
static dimage_label_t relabel_image(il* on_pixels, int maxlabel, dimage_label_t* equivs, int* object) { int i; dimage_label_t maxcontiguouslabel = 0; dimage_label_t *number; number = malloc(sizeof(dimage_label_t) * maxlabel); assert(number); for (i = 0; i < maxlabel; i++) number[i] = LABEL_MAX; for (i=0; i<il_size(on_pixels); i++) { int onpix; int minlabel; onpix = il_get(on_pixels, i); minlabel = collapsing_find_minlabel(object[onpix], equivs); if (number[minlabel] == LABEL_MAX) number[minlabel] = maxcontiguouslabel++; object[onpix] = number[minlabel]; } free(number); return maxcontiguouslabel; }
int DFIND2(const IMGTYPE* image, int nx, int ny, int* object, int* pnobjects) { int ix, iy, i; int maxgroups = initial_max_groups; label_t *equivs = malloc(sizeof(label_t) * maxgroups); int maxlabel = 0; /* Keep track of 'on' pixels to avoid later rescanning */ il* on_pixels = il_new(256); /* Find blobs and track equivalences */ for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { int thislabel, thislabelmin; object[nx*iy+ix] = -1; if (!image[nx*iy+ix]) continue; /* Store location of each 'on' pixel. */ il_append(on_pixels, nx * iy + ix); /* If the pixel to the left [exists and] is on, this pixel joins its group. */ if (ix && image[nx*iy+ix-1]) { /* Old group */ object[nx*iy+ix] = object[nx*iy+ix-1]; } else { /* New blob */ // FIXME this part should become uf_new_group() if (maxlabel >= maxgroups) { maxgroups *= 2; equivs = realloc(equivs, sizeof(label_t) * maxgroups); assert(equivs); } object[nx*iy+ix] = maxlabel; equivs[maxlabel] = maxlabel; maxlabel++; if (maxlabel == LABEL_MAX) { logverb("Ran out of labels. Relabelling...\n"); maxlabel = relabel_image(on_pixels, maxlabel, equivs, object); logverb("After relabelling, we need %i labels\n", maxlabel); if (maxlabel == LABEL_MAX) { ERROR("Ran out of labels."); exit(-1); } } } thislabel = object[nx*iy + ix]; /* Compute minimum equivalence label for this pixel */ thislabelmin = collapsing_find_minlabel(thislabel, equivs); if (iy == 0) continue; /* Check three pixels above this one which are 'neighbours' */ for (i = MAX(0, ix - 1); i <= MIN(ix + 1, nx - 1); i++) { if (image[nx*(iy-1)+i]) { int otherlabel = object[nx*(iy-1) + i]; /* Find min of the other */ int otherlabelmin = collapsing_find_minlabel(otherlabel, equivs); /* Merge groups if necessary */ if (thislabelmin != otherlabelmin) { int oldlabelmin = MAX(thislabelmin, otherlabelmin); int newlabelmin = MIN(thislabelmin, otherlabelmin); thislabelmin = newlabelmin; equivs[oldlabelmin] = newlabelmin; equivs[thislabel] = newlabelmin; /* Update other pixel too */ object[nx*(iy-1) + i] = newlabelmin; } } } object[nx*iy + ix] = thislabelmin; } } /* Re-label the groups before returning */ maxlabel = relabel_image(on_pixels, maxlabel, equivs, object); //logverb("After final relabelling, %i labels were used.\n", maxlabel); if (pnobjects) *pnobjects = maxlabel; free(equivs); il_free(on_pixels); return 1; }