Ejemplo n.º 1
0
/*
 * Add a completed configuration to the list.
 */
void
addconf(struct config *cf0)
{
	struct config *cf;
	struct nvlist *nv;
	const char *name;

	name = cf0->cf_name;
	cf = emalloc(sizeof *cf);
	if (ht_insert(cfhashtab, name, cf)) {
		error("configuration `%s' already defined", name);
		free(cf);
		goto bad;
	}
	*cf = *cf0;

	/*
	 * Look for "swap generic".
	 */
	for (nv = cf->cf_swap; nv != NULL; nv = nv->nv_next)
	    if (nv->nv_str == s_generic)
		break;
	if (nv != NULL) {
		/*
		 * Make sure no root or dump device specified, and no
		 * other swap devices.  Note single | here (check all).
		 */
		nv = cf->cf_swap;
		if (exclude(cf->cf_root, name, "root device") |
		    exclude(nv->nv_next, name, "additional swap devices") |
		    exclude(cf->cf_dump, name, "dump device"))
			goto bad;
	} else {
		nv = cf->cf_root;
		if (nv == NULL) {
			error("%s: no root device specified", name);
			goto bad;
		}
		if (resolve(&cf->cf_root, name, "root", nv, 'a') |
		    lresolve(&cf->cf_swap, name, "swap", nv, 'b') |
		    resolve(&cf->cf_dump, name, "dumps", nv, 'b'))
			goto bad;
	}
	*nextcf = cf;
	nextcf = &cf->cf_next;
	return;
bad:
	nvfreel(cf0->cf_root);
	nvfreel(cf0->cf_swap);
	nvfreel(cf0->cf_dump);
}
/**
 * Image labeling algorithm.
 *
 *  @param im  pointer to input image of type PIXEL
 *  @param width  width input image in pixels
 *  @param height  height input image in pixels
 *  @param connectivty  number of connectivity directions (4 or 8)
 *  @param minsize  smallest allowable blob size, they get subsumed into the parent blob
 *  @param limage pointer to label image, of same size as \p im (output)
 *  @param parent_out pointer to pointer for return of an array of region parents.  Can be NULL. (output)
 *  @param color_out pointer to pointer for return of an array of region color. Can be NULL. (output)
 *  @param edge_out pointer to pointer for return of an array of region edge points.  Can be NULL. (output)
 *  @return the number of regions found
 */
static int 
ilabel(PIXEL *im, int width, int height, int connectivity, int minsize,
    LABEL *limage,
    LABEL **parent_out, PIXEL **color_out, unsigned int **edge_out)
{
    int     *blobsize, row, col, i, j, nlabels;
    int newlabel;
    LABEL   *lmap2;
    LABEL   prevlab, curlab;
    LABEL   *parents;
    PIXEL   curpix, prevpix;
    PIXEL   *color;
    unsigned int    *edge;
    int     maxlabel = width*height;

    /* allocate label map and initialize to zero */
    lmap = (LABEL *)mxCalloc(maxlabel, sizeof(LABEL));
    /* region size */
    blobsize = (int *)mxCalloc(maxlabel, sizeof(int));

    if (parent_out)
        parents = (LABEL *)mxCalloc(maxlabel, sizeof(LABEL));
    if (color_out)
        color = (PIXEL *)mxCalloc(maxlabel, sizeof(PIXEL));
    if (edge_out)
        edge = (unsigned int *)mxCalloc(maxlabel, sizeof(unsigned int));

    

    /*
     * Blob labels are ints >= 1
     * newlabel holds the most recently assigned label value.
     * labels are unique and never recycled.
     *
     * When 2 blobs merge: A := A + B an entry is placed in the label map
     *     lmap[B] = A indicating that all pixels that were B are now A.
     * If lmap[X] = 0 then X is unmerged, X is X
     * It is possible that a later merge: C = C + A
     *     lmap[A] = C indicating that all As are now Cs
     * A pixel that was once B is mapped to A, then to C, but lmap[C] is 0 so
     * the indirection stops there.  B --> A --> C
     *
     * Resolving the indirection is the job of lresolve()
     *      lresolve(A) --> C
     *      lresolve(B) --> C
     *      lresolve(C) --> C
     */

    for (row=0; row<height; row++) {
        for (col=0; col<width; col++) {
            curpix = PIX(im,row,col);
#ifdef  DEBUG
            printf("%2d ", curpix);
#endif
        }
#ifdef  DEBUG
        printf("\n");
#endif
    }

    /*
     * first pass labelling loop.  Only does 4-way connectivity
     */
    newlabel = 0;
    for (row=0; row<height; row++) {
        prevlab = UNKNOWN;
        for (col=0; col<width; col++) {
            curpix = PIX(im,row,col);
            curlab = UNKNOWN;       // start with no known label
            if (col > 0) {
                prevpix = PIX(im,row,col-1);
                /* if no change in pixel value then inherit label from left */
                if (curpix == prevpix)
                    curlab = prevlab;
            }

            
#ifdef  DEBUG
                printf("(%d,%d) cp=%d, pp=%d, cl=%d, pl=%d\n", row, col, curpix, prevpix,
                    curlab, prevlab);
#endif
            /*
             * check whether a label merge should happen, adjacent
             * pixels with the same value but different labels
             * means that one should change.
             *
             * merge can only happen on second row onwards 
             */
            if (row > 0) {
                if (    (PIX(im,row-1,col) == curpix) &&
                    (lresolve(PIX(limage,row-1,col)) != curlab)
                ) {
                    /* we have a label assignment from N */
                    int newlabel;
                    
                    newlabel = lresolve(PIX(limage,row-1,col));
                    /*
                    newlabel = PIX(lim,row-1,col);
                    */

#ifdef  DEBUG
                    printf("mergeN(%d,%d): %d becomes %d: curpix=%d, prevpix=%d\n",
                        row, col, curlab, newlabel, curpix, PIX(im,row-1,col));
#endif
                    // newlabel dominates
                    if (curlab != UNKNOWN) {
                        lmap[curlab] = newlabel;
                        blobsize[newlabel] += blobsize[curlab];
                        //if (edge[curlab] < edge[newlabel])
                            //edge[newlabel] = edge[curlab];
                        if (parents[curlab] == 0)
                            parents[newlabel] = 0;
                    }
                    curlab = newlabel;

                } else if (
                    connectivity == 8 &&
                    (col > 0) &&
                    (PIX(im,row-1,col-1) == curpix) &&
                    (lresolve(PIX(limage,row-1,col-1)) != curlab)
                ) {
                    //  TODO: factorize these two merge cases

                    /* we have a merge to NW */
                    int newlabel;
                    
                    newlabel = lresolve(PIX(limage,row-1,col-1));
                    /*
                    newlabel = PIX(lim,row-1,col);
                    */

#ifdef  DEBUG
                    printf("mergeNW(%d,%d): %d becomes %d\n",
                        row, col, curlab, newlabel);
#endif
                    if (curlab != UNKNOWN)
                        lmap[curlab] = newlabel;
                    if (parents[curlab] == 0)
                        parents[newlabel] = 0;
                    //if (edge[curlab] < edge[newlabel])
                        //edge[newlabel] = edge[curlab];
                    blobsize[newlabel] += blobsize[curlab];
                    curlab = newlabel;

                } else if (
                    connectivity == 8 &&
                    (col < (width-1)) &&
                    (PIX(im,row-1,col+1) == curpix) &&
                    (lresolve(PIX(limage,row-1,col+1)) != curlab)
                ) {
                    /* we have a merge to NE */
                    int newlabel;
                    
                    newlabel = lresolve(PIX(limage,row-1,col+1));
                    /*
                    newlabel = PIX(lim,row-1,col);
                    */

#ifdef  DEBUG
                    printf("mergeNE(%d,%d): %d becomes %d\n",
                        row, col, curlab, newlabel);
#endif
                    if (curlab != UNKNOWN)
                        lmap[curlab] = newlabel;
                    blobsize[newlabel] += blobsize[curlab];
                    //if (edge[curlab] < edge[newlabel])
                        //edge[newlabel] = edge[curlab];
                    curlab = newlabel;

                }

            }

            if ((row > 0) && (col > 0)) {
                /*
                 * check for enclosure
                 */
                int left, above, northwest;

                left = prevlab;
                above = lresolve( PIX(limage,row-1,col) );
                northwest = lresolve( PIX(limage,row-1,col-1) );
                if (    (left == curlab) &&
                    (above == curlab) &&
                    (northwest != curlab)
                ) {
#ifdef  DEBUG
                    printf("(%d,%d): label %d encloses %d\n",
                        row, col,
						curlab, northwest);
#endif
					/* we have an enclosure */
                    if (blobsize[curlab] > THRESH) {
                        // mark the parent of this blob
                        parents[northwest] = curlab;
                        //edge[northwest] = (row-1) + height*(col-1) + 1;
                        //printf("edge is %d\n", edge[northwest]);
                    } else {
                        // it's a runt, merge it with its parent
                        lmap[curlab] = northwest;
                    }
                }
            }

            /* if label still not known, assign new */
            if (curlab == UNKNOWN) {
                curlab = NEWLABEL;
                color[curlab] = curpix;
                edge[curlab] = row + height*col + 1;
                //printf("color %d %f\n", curlab, curpix);
#ifdef  DEBUG
                printf("new label(%d,%d): %d\n", 
                    row, col, curlab);
#endif
            }
            blobsize[curlab] += 1;

            PIX(limage,row,col) = curlab;
            prevlab = curlab;
            prevpix = curpix;
        }
    }

#ifdef  DEBUG
    printf("max lim is %d\n", newlabel);
#endif

    /*
     * The label indirection map can have have quite long chains of indirection
     * as the result of region merges.
     *
     * We pass over the map, and set each entry to its final value, or 0 meaning
     * that it is not indirected.
     *

     */

     /*
      * create a new label map that maps all old labels to new consecutive labels
      */
    lmap2 = (LABEL *)mxCalloc(newlabel+1, sizeof(LABEL));

     /*
      * Create a vector of all the final label values, ie. lmap[i] == 0
      */
#ifdef  DEBUG
    printf("----------------------\nlmap:\n");
#endif
    for (i=1,nlabels=0; i<=newlabel; i++) {
#ifdef  DEBUG
        printf("(%d) = %d\n", i, lmap[i]);
#endif
        if (lmap[i] == 0) 
            lmap2[i] = ++nlabels;   /* assign new sequential label */
    }
    /*
     * now resolve each labels appear in the
     * labelled image, 
     */
    for (i=0; i<=newlabel; i++)
        if (lmap[i] != 0) {
            j = lresolve(i);
            lmap2[i] = lmap2[j];
        }
#ifdef  DEBUG
    printf("----------------------\nlmap2:\n");
    for (i=1; i<=newlabel; i++)
        printf("old(%d) -> %d\n", i, lmap2[i]);
#endif

#ifdef  DEBUG
    printf("----------------------\nparents:\n");
    for (i=1; i<=newlabel; i++)
        printf("parent[%d] = %d\n", i, parents[i]);
#endif

    /*
     * resolve the labels in the parent array and assign to double proc
     * output array
     */
    if (parent_out) {
        LABEL   *lab;

        lab = mxCalloc(nlabels, sizeof(LABEL));
        for (i=1; i<=newlabel; i++) {
            LABEL   par = parents[i], child;

            if (par) {
                child = lmap2[i];
                par = lmap2[par];
                lab[child-1] = par;
                //printf("parent [%d] = %d\n", child, par);
            }
        }
        mxFree(parents);
        *parent_out = lab;
    }

    if (color_out || edge_out) {
        PIXEL   *c;
        unsigned int    *e;

        c = (PIXEL *)mxCalloc(nlabels, sizeof(PIXEL));
        e = (unsigned int *)mxCalloc(nlabels, sizeof(unsigned int));
        for (i=1; i<=newlabel; i++) {
            LABEL     l;

            l = lmap2[i];
            c[l-1] = color[i];
            if (e[l-1] == 0)
                e[l-1] = edge[i];
            //printf("edge %d %d %d\n", i, l, edge[i]);
            //printf("color [%d] = %f\n", l, color[i]);
        }
        if (color_out) {
            mxFree(color);
            *color_out = c;
        }
        if (edge_out) {
            mxFree(edge);
            *edge_out = e;
        }
   }

    /*
     * resolve the labels in the integer labelled image and assign
     * to the double prec. output image
     */
    for (row=0; row<height; row++)
        for (col=0; col<width; col++)
            PIX(limage,row,col) = lmap2[ PIX(limage,row,col) ];

    mxFree(lmap);
    mxFree(lmap2);
    mxFree(blobsize);

    return(nlabels);
}