Пример #1
0
/*!
 * \brief   pixCountConnComp()
 *
 * \param[in]    pixs 1 bpp
 * \param[in]    connectivity 4 or 8
 * \param[out]   pcount
 * \return  0 if OK, 1 on error
 *
 * Notes:
 *     (1 This is the top-level call for getting the number of
 *         4- or 8-connected components in a 1 bpp image.
 *     2 It works on a copy of the input pix.  The c.c. are located
 *         in raster order and erased one at a time.
 */
l_int32
pixCountConnComp(PIX      *pixs,
                 l_int32   connectivity,
                 l_int32  *pcount)
{
    l_int32   h, iszero;
    l_int32   x, y, xstart, ystart;
    PIX      *pixt;
    L_STACK  *stack, *auxstack;

    PROCNAME("pixCountConnComp");

    if (!pcount)
        return ERROR_INT("&count not defined", procName, 1);
    *pcount = 0;  /* initialize the count to 0 */
    if (!pixs || pixGetDepth(pixs) != 1)
        return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
    if (connectivity != 4 && connectivity != 8)
        return ERROR_INT("connectivity not 4 or 8", procName, 1);

    pixt = NULL;
    stack = NULL;

    pixZero(pixs, &iszero);
    if (iszero)
        return 0;

    if ((pixt = pixCopy(NULL, pixs)) == NULL)
        return ERROR_INT("pixt not made", procName, 1);

    h = pixGetHeight(pixs);
    if ((stack = lstackCreate(h)) == NULL) {
        L_ERROR("stack not made\n", procName);
        goto cleanup;
    }
    auxstack = lstackCreate(0);
    stack->auxstack = auxstack;

    xstart = 0;
    ystart = 0;
    while (1) {
        if (!nextOnPixelInRaster(pixt, xstart, ystart, &x, &y))
            break;

        pixSeedfill(pixt, stack, x, y, connectivity);
        (*pcount)++;
        xstart = x;
        ystart = y;
    }

    /* Cleanup, freeing the fillsegs on each stack */
cleanup:
    lstackDestroy(&stack, TRUE);
    pixDestroy(&pixt);

    return 0;
}
Пример #2
0
/*!
 *  pixSubsampleBoundaryPixels()
 *
 *      Input:  pixs (1 bpp, with only boundary pixels in fg)
 *              skip (number to skip between samples as you traverse boundary)
 *      Return: pta, or null on error
 *
 *  Notes:
 *      (1) If skip = 0, we take all the fg pixels.
 *      (2) We try to traverse the boundaries in a regular way.
 *          Some pixels may be missed, and these are then subsampled
 *          randomly with a fraction determined by 'skip'.
 *      (3) The most natural approach is to use a depth first (stack-based)
 *          method to find the fg pixels.  However, the pixel runs are
 *          4-connected and there are relatively few branches.  So
 *          instead of doing a proper depth-first search, we get nearly
 *          the same result using two nested while loops: the outer
 *          one continues a raster-based search for the next fg pixel,
 *          and the inner one does a reasonable job running along
 *          each 4-connected coutour.
 */
PTA *
pixSubsampleBoundaryPixels(PIX     *pixs,
                           l_int32  skip)
{
l_int32  x, y, xn, yn, xs, ys, xa, ya, count;
PIX     *pixt;
PTA     *pta;

    PROCNAME("pixSubsampleBoundaryPixels");

    if (!pixs)
        return (PTA *)ERROR_PTR("pixs not defined", procName, NULL);
    if (pixGetDepth(pixs) != 1)
        return (PTA *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
    if (skip < 0)
        return (PTA *)ERROR_PTR("skip < 0", procName, NULL);

    if (skip == 0)
        return ptaGetPixelsFromPix(pixs, NULL);

    pta = ptaCreate(0);
    pixt = pixCopy(NULL, pixs);
    xs = ys = 0;
    while (nextOnPixelInRaster(pixt, xs, ys, &xn, &yn)) {  /* new series */
        xs = xn;
        ys = yn;

            /* Add first point in this series */
        ptaAddPt(pta, xs, ys);

            /* Trace out boundary, erasing all and saving every (skip + 1)th */
        x = xs;
        y = ys;
        pixSetPixel(pixt, x, y, 0);
        count = 0;
        while (adjacentOnPixelInRaster(pixt, x, y, &xa, &ya)) {
            x = xa;
            y = ya;
            pixSetPixel(pixt, x, y, 0);
            if (count == skip) {
                ptaAddPt(pta, x, y);
                count = 0;
            }
            else {
                count++;
            }
        }
    }

    pixDestroy(&pixt);
    return pta;
}
Пример #3
0
/*!
 * \brief   pixConnCompBB()
 *
 * \param[in]    pixs 1 bpp
 * \param[in]    connectivity 4 or 8
 * \return  boxa, or NULL on error
 *
 * <pre>
 * Notes:
 *     (1) Finds bounding boxes of 4- or 8-connected components
 *         in a binary image.
 *     (2) This works on a copy of the input pix.  The c.c. are located
 *         in raster order and erased one at a time.  In the process,
 *         the b.b. is computed and saved.
 * </pre>
 */
BOXA *
pixConnCompBB(PIX     *pixs,
              l_int32  connectivity)
{
    l_int32   h, iszero;
    l_int32   x, y, xstart, ystart;
    PIX      *pixt;
    BOX      *box;
    BOXA     *boxa;
    L_STACK  *stack, *auxstack;

    PROCNAME("pixConnCompBB");

    if (!pixs || pixGetDepth(pixs) != 1)
        return (BOXA *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
    if (connectivity != 4 && connectivity != 8)
        return (BOXA *)ERROR_PTR("connectivity not 4 or 8", procName, NULL);

    boxa = NULL;
    pixt = NULL;
    stack = NULL;

    pixZero(pixs, &iszero);
    if (iszero)
        return boxaCreate(1);  /* return empty boxa */

    if ((pixt = pixCopy(NULL, pixs)) == NULL)
        return (BOXA *)ERROR_PTR("pixt not made", procName, NULL);

    h = pixGetHeight(pixs);
    if ((stack = lstackCreate(h)) == NULL) {
        L_ERROR("stack not made\n", procName);
        goto cleanup;
    }
    auxstack = lstackCreate(0);
    stack->auxstack = auxstack;
    boxa = boxaCreate(0);

    xstart = 0;
    ystart = 0;
    while (1) {
        if (!nextOnPixelInRaster(pixt, xstart, ystart, &x, &y))
            break;

        if ((box = pixSeedfillBB(pixt, stack, x, y, connectivity)) == NULL) {
            L_ERROR("box not made\n", procName);
            boxaDestroy(&boxa);
            goto cleanup;
        }
        boxaAddBox(boxa, box, L_INSERT);

        xstart = x;
        ystart = y;
    }

#if  DEBUG
    pixCountPixels(pixt, &iszero, NULL);
    fprintf(stderr, "Number of remaining pixels = %d\n", iszero);
    pixWrite("junkremain", pixt1, IFF_PNG);
#endif  /* DEBUG */

    /* Cleanup, freeing the fillsegs on each stack */
cleanup:
    lstackDestroy(&stack, TRUE);
    pixDestroy(&pixt);
    return boxa;
}
Пример #4
0
/*!
 * \brief   pixConnCompPixa()
 *
 * \param[in]    pixs 1 bpp
 * \param[out]   ppixa pixa of each c.c.
 * \param[in]    connectivity 4 or 8
 * \return  boxa, or NULL on error
 *
 * <pre>
 * Notes:
 *      (1) This finds bounding boxes of 4- or 8-connected components
 *          in a binary image, and saves images of each c.c
 *          in a pixa array.
 *      (2) It sets up 2 temporary pix, and for each c.c. that is
 *          located in raster order, it erases the c.c. from one pix,
 *          then uses the b.b. to extract the c.c. from the two pix using
 *          an XOR, and finally erases the c.c. from the second pix.
 *      (3) A clone of the returned boxa (where all boxes in the array
 *          are clones) is inserted into the pixa.
 *      (4) If the input is valid, this always returns a boxa and a pixa.
 *          If pixs is empty, the boxa and pixa will be empty.
 * </pre>
 */
BOXA *
pixConnCompPixa(PIX     *pixs,
                PIXA   **ppixa,
                l_int32  connectivity)
{
    l_int32   h, iszero;
    l_int32   x, y, xstart, ystart;
    PIX      *pix1, *pix2, *pix3, *pix4;
    PIXA     *pixa;
    BOX      *box;
    BOXA     *boxa;
    L_STACK  *stack, *auxstack;

    PROCNAME("pixConnCompPixa");

    if (!ppixa)
        return (BOXA *)ERROR_PTR("&pixa not defined", procName, NULL);
    *ppixa = NULL;
    if (!pixs || pixGetDepth(pixs) != 1)
        return (BOXA *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
    if (connectivity != 4 && connectivity != 8)
        return (BOXA *)ERROR_PTR("connectivity not 4 or 8", procName, NULL);

    boxa = NULL;
    pix1 = pix2 = pix3 = pix4 = NULL;
    stack = NULL;

    pixZero(pixs, &iszero);
    if (iszero)
        return boxaCreate(1);  /* return empty boxa */

    pix1 = pixCopy(NULL, pixs);
    pix2 = pixCopy(NULL, pixs);
    if (!pix1 || !pix2) {
        L_ERROR("pix1 or pix2 not made\n", procName);
        goto cleanup;
    }

    h = pixGetHeight(pixs);
    if ((stack = lstackCreate(h)) == NULL) {
        L_ERROR("stack not made\n", procName);
        goto cleanup;
    }
    auxstack = lstackCreate(0);
    stack->auxstack = auxstack;
    pixa = pixaCreate(0);
    boxa = boxaCreate(0);

    xstart = 0;
    ystart = 0;
    while (1) {
        if (!nextOnPixelInRaster(pix1, xstart, ystart, &x, &y))
            break;

        if ((box = pixSeedfillBB(pix1, stack, x, y, connectivity)) == NULL) {
            L_ERROR("box not made\n", procName);
            pixaDestroy(&pixa);
            boxaDestroy(&boxa);
            goto cleanup;
        }
        boxaAddBox(boxa, box, L_INSERT);

        /* Save the c.c. and remove from pix2 as well */
        pix3 = pixClipRectangle(pix1, box, NULL);
        pix4 = pixClipRectangle(pix2, box, NULL);
        pixXor(pix3, pix3, pix4);
        pixRasterop(pix2, box->x, box->y, box->w, box->h, PIX_SRC ^ PIX_DST,
                    pix3, 0, 0);
        pixaAddPix(pixa, pix3, L_INSERT);
        pixDestroy(&pix4);

        xstart = x;
        ystart = y;
    }

#if  DEBUG
    pixCountPixels(pix1, &iszero, NULL);
    fprintf(stderr, "Number of remaining pixels = %d\n", iszero);
    pixWrite("junkremain", pix1, IFF_PNG);
#endif  /* DEBUG */

    /* Remove old boxa of pixa and replace with a clone copy */
    boxaDestroy(&pixa->boxa);
    pixa->boxa = boxaCopy(boxa, L_CLONE);
    *ppixa = pixa;

    /* Cleanup, freeing the fillsegs on each stack */
cleanup:
    lstackDestroy(&stack, TRUE);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    return boxa;
}