Esempio n. 1
0
main(int    argc,
     char **argv)
{
char        *filein;
char         buf[L_BUF_SIZE];
l_int32      size;
PIX         *pixs, *pixt1, *pixt2;
static char  mainName[] = "colormorphtest";

    if (argc != 3)
        exit(ERROR_INT(" Syntax:  colormorphtest filein size",
             mainName, 1));

    filein = argv[1];
    size = atoi(argv[2]);
    if (size % 2 == 0) size++;

    if ((pixs = pixRead(filein)) == NULL)
        exit(ERROR_INT("pixs not read", mainName, 1));

    pixt1 = pixColorMorph(pixs, L_MORPH_DILATE, size, size);
    sprintf(buf, "d%d.%d", size, size);
    pixt2 = pixColorMorphSequence(pixs, buf, 0, 0);
    pixCompare(pixt1, pixt2, "Correct for dilation", "Error on dilation");
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);

    pixt1 = pixColorMorph(pixs, L_MORPH_ERODE, size, size);
    sprintf(buf, "e%d.%d", size, size);
    pixt2 = pixColorMorphSequence(pixs, buf, 0, 0);
    pixCompare(pixt1, pixt2, "Correct for erosion", "Error on erosion");
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);

    pixt1 = pixColorMorph(pixs, L_MORPH_OPEN, size, size);
    sprintf(buf, "o%d.%d", size, size);
    pixt2 = pixColorMorphSequence(pixs, buf, 0, 0);
    pixCompare(pixt1, pixt2, "Correct for opening", "Error on opening");
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);

    pixt1 = pixColorMorph(pixs, L_MORPH_CLOSE, size, size);
    sprintf(buf, "c%d.%d", size, size);
    pixt2 = pixColorMorphSequence(pixs, buf, 0, 0);
    pixCompare(pixt1, pixt2, "Correct for closing", "Error on closing");
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);

    pixDisplayMultiple("/tmp/junk_write_display*");

    pixDestroy(&pixs);
    return 0;
}
Esempio n. 2
0
/*!
 *  pixColorMorphSequence()
 *
 *      Input:  pixs
 *              sequence (string specifying sequence)
 *              dispsep (horizontal separation in pixels between
 *                       successive displays; use zero to suppress display)
 *              dispy (if dispsep != 0, this gives the y-value of the
 *                     UL corner for display; otherwise it is ignored)
 *      Return: pixd, or null on error
 *
 *  Notes:
 *      (1) This works on 32 bpp rgb images.
 *      (2) Each component is processed separately.
 *      (3) This runs a pipeline of operations; no branching is allowed.
 *      (4) This only uses brick SELs.
 *      (5) A new image is always produced; the input image is not changed.
 *      (6) This contains an interpreter, allowing sequences to be
 *          generated and run.
 *      (7) Sel sizes (width, height) must each be odd numbers.
 *      (8) The format of the sequence string is defined below.
 *      (9) Intermediate results can optionally be displayed.
 *      (10) The sequence string is formatted as follows:
 *            - An arbitrary number of operations,  each separated
 *              by a '+' character.  White space is ignored.
 *            - Each operation begins with a case-independent character
 *              specifying the operation:
 *                 d or D  (dilation)
 *                 e or E  (erosion)
 *                 o or O  (opening)
 *                 c or C  (closing)
 *            - The args to the morphological operations are bricks of hits,
 *              and are formatted as a.b, where a and b are horizontal and
 *              vertical dimensions, rsp. (each must be an odd number)
 *           Example valid sequences are:
 *             "c5.3 + o7.5"
 *             "D9.1"
 */
PIX *
pixColorMorphSequence(PIX         *pixs,
                      const char  *sequence,
                      l_int32      dispsep,
                      l_int32      dispy)
{
char    *rawop, *op;
l_int32  nops, i, valid, w, h, x;
PIX     *pixt1, *pixt2;
SARRAY  *sa;

    PROCNAME("pixColorMorphSequence");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (!sequence)
        return (PIX *)ERROR_PTR("sequence not defined", procName, NULL);

        /* Split sequence into individual operations */
    sa = sarrayCreate(0);
    sarraySplitString(sa, sequence, "+");
    nops = sarrayGetCount(sa);

        /* Verify that the operation sequence is valid */
    valid = TRUE;
    for (i = 0; i < nops; i++) {
        rawop = sarrayGetString(sa, i, 0);
        op = stringRemoveChars(rawop, " \n\t");
        switch (op[0])
        {
        case 'd':
        case 'D':
        case 'e':
        case 'E':
        case 'o':
        case 'O':
        case 'c':
        case 'C':
            if (sscanf(&op[1], "%d.%d", &w, &h) != 2) {
                fprintf(stderr, "*** op: %s invalid\n", op);
                valid = FALSE;
                break;
            }
            if (w < 1 || (w & 1) == 0 || h < 1 || (h & 1) == 0 ) {
                fprintf(stderr,
                        "*** op: %s; w = %d, h = %d; must both be odd\n",
                        op, w, h);
                valid = FALSE;
                break;
            }
/*            fprintf(stderr, "op = %s; w = %d, h = %d\n", op, w, h); */
            break;
        default:
            fprintf(stderr, "*** nonexistent op = %s\n", op);
            valid = FALSE;
        }
        FREE(op);
    }
    if (!valid) {
        sarrayDestroy(&sa);
        return (PIX *)ERROR_PTR("sequence invalid", procName, NULL);
    }

        /* Parse and operate */
    pixt1 = pixCopy(NULL, pixs);
    pixt2 = NULL;
    x = 0;
    for (i = 0; i < nops; i++) {
        rawop = sarrayGetString(sa, i, 0);
        op = stringRemoveChars(rawop, " \n\t");
        switch (op[0])
        {
        case 'd':
        case 'D':
            sscanf(&op[1], "%d.%d", &w, &h);
            pixt2 = pixColorMorph(pixt1, L_MORPH_DILATE, w, h);
            pixDestroy(&pixt1);
            pixt1 = pixClone(pixt2);
            pixDestroy(&pixt2);
            if (dispsep > 0) {
                pixDisplay(pixt1, x, dispy);
                x += dispsep;
            }
            break;
        case 'e':
        case 'E':
            sscanf(&op[1], "%d.%d", &w, &h);
            pixt2 = pixColorMorph(pixt1, L_MORPH_ERODE, w, h);
            pixDestroy(&pixt1);
            pixt1 = pixClone(pixt2);
            pixDestroy(&pixt2);
            if (dispsep > 0) {
                pixDisplay(pixt1, x, dispy);
                x += dispsep;
            }
            break;
        case 'o':
        case 'O':
            sscanf(&op[1], "%d.%d", &w, &h);
            pixt2 = pixColorMorph(pixt1, L_MORPH_OPEN, w, h);
            pixDestroy(&pixt1);
            pixt1 = pixClone(pixt2);
            pixDestroy(&pixt2);
            if (dispsep > 0) {
                pixDisplay(pixt1, x, dispy);
                x += dispsep;
            }
            break;
        case 'c':
        case 'C':
            sscanf(&op[1], "%d.%d", &w, &h);
            pixt2 = pixColorMorph(pixt1, L_MORPH_CLOSE, w, h);
            pixDestroy(&pixt1);
            pixt1 = pixClone(pixt2);
            pixDestroy(&pixt2);
            if (dispsep > 0) {
                pixDisplay(pixt1, x, dispy);
                x += dispsep;
            }
            break;
        default:
            /* All invalid ops are caught in the first pass */
            break;
        }
        FREE(op);
    }

    sarrayDestroy(&sa);
    return pixt1;
}
Esempio n. 3
0
main(int    argc,
     char **argv)
{
l_int32      i, wf, hf, w, h, d, same;
l_float32    rank, time;
PIX         *pixs, *pixd, *pixt1, *pixt2, *pixt3, *pixt4;
PIXA        *pixa;
char        *filein, *fileout;
static char  mainName[] = "ranktest";

    if (argc != 6)
	exit(ERROR_INT(" Syntax:  ranktest filein wf hf rank fileout",
                       mainName, 1));

    filein = argv[1];
    wf = atoi(argv[2]);
    hf = atoi(argv[3]);
    rank = atof(argv[4]);
    fileout = argv[5];

    if ((pixs = pixRead(filein)) == NULL)
	exit(ERROR_INT("pix not made", mainName, 1));
    pixGetDimensions(pixs, &w, &h, &d);
    if (d != 8 && d != 32)
	exit(ERROR_INT("pix neither 8 nor 32 bpp", mainName, 1));

    startTimer();
    pixd = pixRankFilter(pixs, wf, hf, rank);
    time = stopTimer();
    fprintf(stderr, "Time =  %7.3f sec\n", time);
    fprintf(stderr, "MPix/sec: %7.3f\n", 0.000001 * w * h / time);
    pixDisplay(pixs, 0, 0);
    pixDisplay(pixd, 600, 0);
    pixWrite(fileout, pixd, IFF_PNG);
    pixDestroy(&pixd);

        /* Get results for different rank values */
    for (i = 0; i <= 10; i++) {
        pixd = pixRankFilter(pixs, wf, hf, 0.1 * i);
        pixDisplayWrite(pixd, 1);
        pixDestroy(&pixd);
    }

        /* Make the dimensions odd to compare with dilation & erosion */
    if (wf % 2 == 0) wf++;
    if (hf % 2 == 0) hf++;

        /* Get results for dilation and erosion */
    if (d == 8) {
        pixt1 = pixDilateGray(pixs, wf, hf);
        pixt2 = pixErodeGray(pixs, wf, hf);
    } else {
        pixt1 = pixColorMorph(pixs, L_MORPH_DILATE, wf, hf);
        pixt2 = pixColorMorph(pixs, L_MORPH_ERODE, wf, hf);
    }
    pixDisplayWrite(pixt1, 1);  /* dilation */

        /* Get results using the rank filter for rank = 0.0 and 1.0.
         * Don't use 0.0 or 1.0, because those are dispatched
         * automatically to erosion and dilation! */
    pixt3 = pixRankFilter(pixs, wf, hf, 0.0001);
    pixt4 = pixRankFilter(pixs, wf, hf, 0.9999);

        /* Compare */
    pixEqual(pixt1, pixt4, &same);
    if (same)
        fprintf(stderr, "Correct: dilation results same as rank 1.0\n");
    else
        fprintf(stderr, "Error: dilation results differ from rank 1.0\n");
    pixEqual(pixt2, pixt3, &same);
    if (same)
        fprintf(stderr, "Correct: erosion results same as rank 0.0\n");
    else
        fprintf(stderr, "Error: erosion results differ from rank 0.0\n");
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixDestroy(&pixt3);
    pixDestroy(&pixt4);

        /* Display tiled */
    pixa = pixaReadFiles("/tmp", "junk_write_display");
    pixd = pixaDisplayTiledAndScaled(pixa, d, 400, 3, 0, 25, 2);
    pixWrite("/tmp/junktiles.jpg", pixd, IFF_JFIF_JPEG);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);

    pixDestroy(&pixs);
    return 0;
}
/*!
 * \brief   pixColorMorphSequence()
 *
 * \param[in]    pixs
 * \param[in]    sequence string specifying sequence
 * \param[in]    dispsep controls debug display of each result in the sequence:
 *                       0: no output
 *                       > 0: gives horizontal separation in pixels between
 *                            successive displays
 *                       < 0: pdf output; abs(dispsep) is used for naming
 * \param[in]    dispy if dispsep > 0, this gives the y-value of the
 *                     UL corner for display; otherwise it is ignored
 * \return  pixd, or NULL on error
 *
 * <pre>
 * Notes:
 *      (1) This works on 32 bpp rgb images.
 *      (2) Each component is processed separately.
 *      (3) This runs a pipeline of operations; no branching is allowed.
 *      (4) This only uses brick SELs.
 *      (5) A new image is always produced; the input image is not changed.
 *      (6) This contains an interpreter, allowing sequences to be
 *          generated and run.
 *      (7) Sel sizes (width, height) must each be odd numbers.
 *      (8) The format of the sequence string is defined below.
 *      (9) Intermediate results can optionally be displayed.
 *      (10) The sequence string is formatted as follows:
 *            ~ An arbitrary number of operations,  each separated
 *              by a '+' character.  White space is ignored.
 *            ~ Each operation begins with a case-independent character
 *              specifying the operation:
 *                 d or D  (dilation)
 *                 e or E  (erosion)
 *                 o or O  (opening)
 *                 c or C  (closing)
 *            ~ The args to the morphological operations are bricks of hits,
 *              and are formatted as a.b, where a and b are horizontal and
 *              vertical dimensions, rsp. (each must be an odd number)
 *           Example valid sequences are:
 *             "c5.3 + o7.5"
 *             "D9.1"
 * </pre>
 */
PIX *
pixColorMorphSequence(PIX         *pixs,
                      const char  *sequence,
                      l_int32      dispsep,
                      l_int32      dispy)
{
char    *rawop, *op, *fname;
char     buf[256];
l_int32  nops, i, valid, w, h, x, pdfout;
PIX     *pixt1, *pixt2;
PIXA    *pixa;
SARRAY  *sa;

    PROCNAME("pixColorMorphSequence");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (!sequence)
        return (PIX *)ERROR_PTR("sequence not defined", procName, NULL);

        /* Split sequence into individual operations */
    sa = sarrayCreate(0);
    sarraySplitString(sa, sequence, "+");
    nops = sarrayGetCount(sa);
    pdfout = (dispsep < 0) ? 1 : 0;

        /* Verify that the operation sequence is valid */
    valid = TRUE;
    for (i = 0; i < nops; i++) {
        rawop = sarrayGetString(sa, i, L_NOCOPY);
        op = stringRemoveChars(rawop, " \n\t");
        switch (op[0])
        {
        case 'd':
        case 'D':
        case 'e':
        case 'E':
        case 'o':
        case 'O':
        case 'c':
        case 'C':
            if (sscanf(&op[1], "%d.%d", &w, &h) != 2) {
                fprintf(stderr, "*** op: %s invalid\n", op);
                valid = FALSE;
                break;
            }
            if (w < 1 || (w & 1) == 0 || h < 1 || (h & 1) == 0 ) {
                fprintf(stderr,
                        "*** op: %s; w = %d, h = %d; must both be odd\n",
                        op, w, h);
                valid = FALSE;
                break;
            }
/*            fprintf(stderr, "op = %s; w = %d, h = %d\n", op, w, h); */
            break;
        default:
            fprintf(stderr, "*** nonexistent op = %s\n", op);
            valid = FALSE;
        }
        LEPT_FREE(op);
    }
    if (!valid) {
        sarrayDestroy(&sa);
        return (PIX *)ERROR_PTR("sequence invalid", procName, NULL);
    }

        /* Parse and operate */
    pixa = NULL;
    if (pdfout) {
        pixa = pixaCreate(0);
        pixaAddPix(pixa, pixs, L_CLONE);
        snprintf(buf, sizeof(buf), "/tmp/seq_output_%d.pdf", L_ABS(dispsep));
        fname = genPathname(buf, NULL);
    }
    pixt1 = pixCopy(NULL, pixs);
    pixt2 = NULL;
    x = 0;
    for (i = 0; i < nops; i++) {
        rawop = sarrayGetString(sa, i, L_NOCOPY);
        op = stringRemoveChars(rawop, " \n\t");
        switch (op[0])
        {
        case 'd':
        case 'D':
            sscanf(&op[1], "%d.%d", &w, &h);
            pixt2 = pixColorMorph(pixt1, L_MORPH_DILATE, w, h);
            pixSwapAndDestroy(&pixt1, &pixt2);
            break;
        case 'e':
        case 'E':
            sscanf(&op[1], "%d.%d", &w, &h);
            pixt2 = pixColorMorph(pixt1, L_MORPH_ERODE, w, h);
            pixSwapAndDestroy(&pixt1, &pixt2);
            break;
        case 'o':
        case 'O':
            sscanf(&op[1], "%d.%d", &w, &h);
            pixt2 = pixColorMorph(pixt1, L_MORPH_OPEN, w, h);
            pixSwapAndDestroy(&pixt1, &pixt2);
            break;
        case 'c':
        case 'C':
            sscanf(&op[1], "%d.%d", &w, &h);
            pixt2 = pixColorMorph(pixt1, L_MORPH_CLOSE, w, h);
            pixSwapAndDestroy(&pixt1, &pixt2);
            break;
        default:
            /* All invalid ops are caught in the first pass */
            break;
        }
        LEPT_FREE(op);

            /* Debug output */
        if (dispsep > 0) {
            pixDisplay(pixt1, x, dispy);
            x += dispsep;
        }
        if (pdfout)
            pixaAddPix(pixa, pixt1, L_COPY);
    }

    if (pdfout) {
        pixaConvertToPdf(pixa, 0, 1.0, L_FLATE_ENCODE, 0, fname, fname);
        LEPT_FREE(fname);
        pixaDestroy(&pixa);
    }

    sarrayDestroy(&sa);
    return pixt1;
}