Exemple #1
0
void
RotateTest(PIX *pixs,
           l_float32 scale,
           L_REGPARAMS *rp) {
    l_int32 w, h, d, outformat;
    PIX *pixt1, *pixt2, *pixt3, *pixd;
    PIXA *pixa;

    pixGetDimensions(pixs, &w, &h, &d);
    outformat = (d == 8 || d == 32) ? IFF_JFIF_JPEG : IFF_PNG;

    pixa = pixaCreate(0);
    pixt1 = pixRotate(pixs, ANGLE1, L_ROTATE_SHEAR, L_BRING_IN_WHITE, w, h);
    pixSaveTiled(pixt1, pixa, scale, 1, 20, 32);
    pixt2 = pixRotate(pixs, ANGLE1, L_ROTATE_SHEAR, L_BRING_IN_BLACK, w, h);
    pixSaveTiled(pixt2, pixa, scale, 0, 20, 0);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixt1 = pixRotate(pixs, ANGLE1, L_ROTATE_SHEAR, L_BRING_IN_WHITE, 0, 0);
    pixSaveTiled(pixt1, pixa, scale, 1, 20, 0);
    pixt2 = pixRotate(pixs, ANGLE1, L_ROTATE_SHEAR, L_BRING_IN_BLACK, 0, 0);
    pixSaveTiled(pixt2, pixa, scale, 0, 20, 0);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixt1 = pixRotate(pixs, ANGLE2, L_ROTATE_SHEAR, L_BRING_IN_WHITE, w, h);
    pixSaveTiled(pixt1, pixa, scale, 1, 20, 0);
    pixt2 = pixRotate(pixs, ANGLE2, L_ROTATE_SHEAR, L_BRING_IN_BLACK, w, h);
    pixSaveTiled(pixt2, pixa, scale, 0, 20, 0);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixt1 = pixRotate(pixs, ANGLE2, L_ROTATE_SHEAR, L_BRING_IN_WHITE, 0, 0);
    pixSaveTiled(pixt1, pixa, scale, 1, 20, 0);
    pixt2 = pixRotate(pixs, ANGLE2, L_ROTATE_SHEAR, L_BRING_IN_BLACK, 0, 0);
    pixSaveTiled(pixt2, pixa, scale, 0, 20, 0);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixd = pixaDisplay(pixa, 0, 0);
    regTestWritePixAndCheck(rp, pixd, outformat);
    pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);

    pixa = pixaCreate(0);
    pixt1 = pixRotate(pixs, ANGLE2, L_ROTATE_SAMPLING, L_BRING_IN_WHITE, w, h);
    pixSaveTiled(pixt1, pixa, scale, 1, 20, 32);
    pixt2 = pixRotate(pixs, ANGLE2, L_ROTATE_SAMPLING, L_BRING_IN_BLACK, w, h);
    pixSaveTiled(pixt2, pixa, scale, 0, 20, 0);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixt1 = pixRotate(pixs, ANGLE2, L_ROTATE_SAMPLING, L_BRING_IN_WHITE, 0, 0);
    pixSaveTiled(pixt1, pixa, scale, 1, 20, 0);
    pixt2 = pixRotate(pixs, ANGLE2, L_ROTATE_SAMPLING, L_BRING_IN_BLACK, 0, 0);
    pixSaveTiled(pixt2, pixa, scale, 0, 20, 0);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);

    if (pixGetDepth(pixs) == 1)
        pixt1 = pixScaleToGray2(pixs);
    else
        pixt1 = pixClone(pixs);
    pixt2 = pixRotate(pixt1, ANGLE2, L_ROTATE_AREA_MAP, L_BRING_IN_WHITE, w, h);
    pixSaveTiled(pixt2, pixa, scale, 1, 20, 0);
    pixt3 = pixRotate(pixt1, ANGLE2, L_ROTATE_AREA_MAP, L_BRING_IN_BLACK, w, h);
    pixSaveTiled(pixt3, pixa, scale, 0, 20, 0);
    pixDestroy(&pixt2);
    pixDestroy(&pixt3);
    pixt2 = pixRotate(pixt1, ANGLE2, L_ROTATE_AREA_MAP, L_BRING_IN_WHITE, 0, 0);
    pixSaveTiled(pixt2, pixa, scale, 1, 20, 0);
    pixt3 = pixRotate(pixt1, ANGLE2, L_ROTATE_AREA_MAP, L_BRING_IN_BLACK, 0, 0);
    pixSaveTiled(pixt3, pixa, scale, 0, 20, 0);
    pixDestroy(&pixt2);
    pixDestroy(&pixt3);
    pixDestroy(&pixt1);
    pixd = pixaDisplay(pixa, 0, 0);
    regTestWritePixAndCheck(rp, pixd, outformat);
    pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);

    return;
}
Exemple #2
0
l_int32 main(int    argc,
             char **argv)
{
l_int32     size, i, rval, gval, bval, yval, uval, vval;
l_float32  *a[3], b[3];
L_BMF      *bmf;
PIX        *pixd;
PIXA       *pixa;

        /* Explore the range of rgb --> yuv transforms.  All rgb
         * values transform to a valid value of yuv, so when transforming
         * back we get the same rgb values that we started with. */
    pixa = pixaCreate(0);
    bmf = bmfCreate("fonts", 6);
    for (gval = 0; gval <= 255; gval += 20)
        AddTransformsRGB(pixa, bmf, gval);

    pixd = pixaDisplayTiledAndScaled(pixa, 32, 755, 1, 0, 20, 2);
    pixDisplay(pixd, 100, 0);
    pixWrite("/tmp/yuv1.png", pixd, IFF_PNG);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);

        /* Now start with all "valid" yuv values, not all of which are
         * related to a valid rgb value.  Our yuv --> rgb transform
         * clips the rgb components to [0 ... 255], so when transforming
         * back we get different values whenever the initial yuv
         * value is out of the rgb gamut. */
    pixa = pixaCreate(0);
    for (yval = 16; yval <= 235; yval += 16)
        AddTransformsYUV(pixa, bmf, yval);

    pixd = pixaDisplayTiledAndScaled(pixa, 32, 755, 1, 0, 20, 2);
    pixDisplay(pixd, 600, 0);
    pixWrite("/tmp/yuv2.png", pixd, IFF_PNG);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);
    bmfDestroy(&bmf);


    /* --------- Try out a special case by hand, and show that --------- *
     * ------- the transform matrices we are using are inverses ---------*/

        /* First, use our functions for the transform */
    fprintf(stderr, "Start with: yval = 143, uval = 79, vval = 103\n");
    convertYUVToRGB(143, 79, 103, &rval, &gval, &bval);
    fprintf(stderr, " ==> rval = %d, gval = %d, bval = %d\n", rval, gval, bval);
    convertRGBToYUV(rval, gval, bval, &yval, &uval, &vval);
    fprintf(stderr, " ==> yval = %d, uval = %d, vval = %d\n", yval, uval, vval);

        /* Next, convert yuv --> rbg by solving for rgb --> yuv transform.
         *      [ a00   a01   a02 ]    r   =   b0           (y - 16)
         *      [ a10   a11   a12 ] *  g   =   b1           (u - 128)
         *      [ a20   a21   a22 ]    b   =   b2           (v - 128)
         */
    b[0] = 143.0 - 16.0;    /* y - 16 */
    b[1] = 79.0 - 128.0;   /* u - 128 */
    b[2] = 103.0 - 128.0;    /* v - 128 */
    for (i = 0; i < 3; i++)
        a[i] = (l_float32 *)lept_calloc(3, sizeof(l_float32));
    a[0][0] = 65.738 / 256.0;
    a[0][1] = 129.057 / 256.0;
    a[0][2] = 25.064 / 256.0;
    a[1][0] = -37.945 / 256.0;
    a[1][1] = -74.494 / 256.0;
    a[1][2] = 112.439 / 256.0;
    a[2][0] = 112.439 / 256.0;
    a[2][1] = -94.154 / 256.0;
    a[2][2] = -18.285 / 256.0;
    fprintf(stderr, "Here's the original matrix: yuv --> rgb:\n");
    for (i = 0; i < 3; i++)
        fprintf(stderr, "    %7.3f  %7.3f  %7.3f\n", 256.0 * a[i][0],
                256.0 * a[i][1], 256.0 * a[i][2]);
    gaussjordan(a, b, 3);
    fprintf(stderr, "\nInput (yuv) = (143,79,103); solve for rgb:\n"
            "rval = %7.3f, gval = %7.3f, bval = %7.3f\n",
            b[0], b[1], b[2]);
    fprintf(stderr, "Here's the inverse matrix: rgb --> yuv:\n");
    for (i = 0; i < 3; i++)
        fprintf(stderr, "    %7.3f  %7.3f  %7.3f\n", 256.0 * a[i][0],
                256.0 * a[i][1], 256.0 * a[i][2]);

        /* Now, convert back: rgb --> yuv;
         * Do this by solving for yuv --> rgb transform.
         * Use the b[] found previously (the rgb values), and
         * the a[][] which now holds the rgb --> yuv transform.  */
    gaussjordan(a, b, 3);
    fprintf(stderr, "\nInput rgb; solve for yuv:\n"
            "yval = %7.3f, uval = %7.3f, vval = %7.3f\n",
            b[0] + 16.0, b[1] + 128.0, b[2] + 128.0);
    fprintf(stderr, "Inverting the matrix again: yuv --> rgb:\n");
    for (i = 0; i < 3; i++)
        fprintf(stderr, "    %7.3f  %7.3f  %7.3f\n", 256.0 * a[i][0],
                256.0 * a[i][1], 256.0 * a[i][2]);

    for (i = 0; i < 3; i++) lept_free(a[i]);
    return 0;
}
/**
 * Auto page segmentation. Divide the page image into blocks of uniform
 * text linespacing and images.
 *
 * Width, height and resolution are derived from the input image.
 *
 * If the pix is non-NULL, then it is assumed to be the input, and it is
 * copied to the image, otherwise the image is used directly.
 *
 * The output goes in the blocks list with corresponding TO_BLOCKs in the
 * to_blocks list.
 *
 * If single_column is true, then no attempt is made to divide the image
 * into columns, but multiple blocks are still made if the text is of
 * non-uniform linespacing.
 */
int Tesseract::AutoPageSeg(int width, int height, int resolution,
                           bool single_column, IMAGE* image,
                           BLOCK_LIST* blocks, TO_BLOCK_LIST* to_blocks) {
    int vertical_x = 0;
    int vertical_y = 1;
    TabVector_LIST v_lines;
    TabVector_LIST h_lines;
    ICOORD bleft(0, 0);
    Boxa* boxa = NULL;
    Pixa* pixa = NULL;
    // The blocks made by the ColumnFinder. Moved to blocks before return.
    BLOCK_LIST found_blocks;

#ifdef HAVE_LIBLEPT
    if (pix_binary_ != NULL) {
        if (textord_debug_images) {
            Pix* grey_pix = pixCreate(width, height, 8);
            // Printable images are light grey on white, but for screen display
            // they are black on dark grey so the other colors show up well.
            if (textord_debug_printable) {
                pixSetAll(grey_pix);
                pixSetMasked(grey_pix, pix_binary_, 192);
            } else {
                pixSetAllArbitrary(grey_pix, 64);
                pixSetMasked(grey_pix, pix_binary_, 0);
            }
            AlignedBlob::IncrementDebugPix();
            pixWrite(AlignedBlob::textord_debug_pix().string(), grey_pix, IFF_PNG);
            pixDestroy(&grey_pix);
        }
        if (tessedit_dump_pageseg_images)
            pixWrite("tessinput.png", pix_binary_, IFF_PNG);
        // Leptonica is used to find the lines and image regions in the input.
        LineFinder::FindVerticalLines(resolution, pix_binary_,
                                      &vertical_x, &vertical_y, &v_lines);
        LineFinder::FindHorizontalLines(resolution, pix_binary_, &h_lines);
        if (tessedit_dump_pageseg_images)
            pixWrite("tessnolines.png", pix_binary_, IFF_PNG);
        ImageFinder::FindImages(pix_binary_, &boxa, &pixa);
        if (tessedit_dump_pageseg_images)
            pixWrite("tessnoimages.png", pix_binary_, IFF_PNG);
        // Copy the Pix to the IMAGE.
        image->FromPix(pix_binary_);
        if (single_column)
            v_lines.clear();
    }
#endif
    TO_BLOCK_LIST land_blocks, port_blocks;
    TBOX page_box;
    // The rest of the algorithm uses the usual connected components.
    find_components(blocks, &land_blocks, &port_blocks, &page_box);

    TO_BLOCK_IT to_block_it(&port_blocks);
    ASSERT_HOST(!to_block_it.empty());
    for (to_block_it.mark_cycle_pt(); !to_block_it.cycled_list();
            to_block_it.forward()) {
        TO_BLOCK* to_block = to_block_it.data();
        TBOX blkbox = to_block->block->bounding_box();
        if (to_block->line_size >= 2) {
            // Note: if there are multiple blocks, then v_lines, boxa, and pixa
            // are empty on the next iteration, but in this case, we assume
            // that there aren't any interesting line separators or images, since
            // it means that we have a pre-defined unlv zone file.
            ColumnFinder finder(static_cast<int>(to_block->line_size),
                                blkbox.botleft(), blkbox.topright(),
                                &v_lines, &h_lines, vertical_x, vertical_y);
            if (finder.FindBlocks(height, resolution, single_column,
                                  to_block, boxa, pixa, &found_blocks, to_blocks) < 0)
                return -1;
            finder.ComputeDeskewVectors(&deskew_, &reskew_);
            boxa = NULL;
            pixa = NULL;
        }
    }
#ifdef HAVE_LIBLEPT
    boxaDestroy(&boxa);
    pixaDestroy(&pixa);
#endif
    blocks->clear();
    BLOCK_IT block_it(blocks);
    // Move the found blocks to the input/output blocks.
    block_it.add_list_after(&found_blocks);

    if (textord_debug_images) {
        // The debug image is no longer needed so delete it.
        unlink(AlignedBlob::textord_debug_pix().string());
    }
    return 0;
}
int main(int    argc,
         char **argv)
{
l_int32      i, n, binsize, binstart, nbins;
l_float32    pi, val, angle, xval, yval, x0, y0, rank, startval, fbinsize;
l_float32    minval, maxval, meanval, median, variance, rankval;
GPLOT       *gplot;
NUMA        *na, *nahisto, *nax, *nay, *nap, *nasx, *nasy;
NUMA        *nadx, *nady, *nafx, *nafy, *na1, *na2, *na3, *na4;
PIX         *pixs, *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7, *pixd;
PIXA        *pixa;
static char  mainName[] = "numa1_reg";

    if (argc != 1)
        return ERROR_INT(" Syntax:  numa1_reg", mainName, 1);

    lept_mkdir("lept/numa1");

    /* -------------------------------------------------------------------*
     *                            Histograms                              *
     * -------------------------------------------------------------------*/
#if  DO_ALL
    pi = 3.1415926535;
    na = numaCreate(5000);
    for (i = 0; i < 500000; i++) {
        angle = 0.02293 * i * pi;
        val = (l_float32)(999. * sin(angle));
        numaAddNumber(na, val);
    }

    nahisto = numaMakeHistogramClipped(na, 6, 2000);
    nbins = numaGetCount(nahisto);
    nax = numaMakeSequence(0, 1, nbins);
    gplot = gplotCreate("/tmp/lept/numa1/histo1", GPLOT_PNG, "example histo 1",
                        "i", "histo[i]");
    gplotAddPlot(gplot, nax, nahisto, GPLOT_LINES, "sine");
    gplotMakeOutput(gplot);
    gplotDestroy(&gplot);
    numaDestroy(&nax);
    numaDestroy(&nahisto);

    nahisto = numaMakeHistogram(na, 1000, &binsize, &binstart);
    nbins = numaGetCount(nahisto);
    nax = numaMakeSequence(binstart, binsize, nbins);
    fprintf(stderr, " binsize = %d, binstart = %d\n", binsize, binstart);
    gplot = gplotCreate("/tmp/lept/numa1/histo2", GPLOT_PNG, "example histo 2",
                        "i", "histo[i]");
    gplotAddPlot(gplot, nax, nahisto, GPLOT_LINES, "sine");
    gplotMakeOutput(gplot);
    gplotDestroy(&gplot);
    numaDestroy(&nax);
    numaDestroy(&nahisto);

    nahisto = numaMakeHistogram(na, 1000, &binsize, NULL);
    nbins = numaGetCount(nahisto);
    nax = numaMakeSequence(0, binsize, nbins);
    fprintf(stderr, " binsize = %d, binstart = %d\n", binsize, 0);
    gplot = gplotCreate("/tmp/lept/numa1/histo3", GPLOT_PNG, "example histo 3",
                        "i", "histo[i]");
    gplotAddPlot(gplot, nax, nahisto, GPLOT_LINES, "sine");
    gplotMakeOutput(gplot);
    gplotDestroy(&gplot);
    numaDestroy(&nax);
    numaDestroy(&nahisto);

    nahisto = numaMakeHistogramAuto(na, 1000);
    nbins = numaGetCount(nahisto);
    numaGetParameters(nahisto, &startval, &fbinsize);
    nax = numaMakeSequence(startval, fbinsize, nbins);
    fprintf(stderr, " binsize = %7.4f, binstart = %8.3f\n",
            fbinsize, startval);
    gplot = gplotCreate("/tmp/lept/numa1/histo4", GPLOT_PNG, "example histo 4",
                        "i", "histo[i]");
    gplotAddPlot(gplot, nax, nahisto, GPLOT_LINES, "sine");
    gplotMakeOutput(gplot);
    gplotDestroy(&gplot);
    pixa = pixaCreate(4);
    pix1 = pixRead("/tmp/lept/numa1/histo1.png");
    pix2 = pixRead("/tmp/lept/numa1/histo2.png");
    pix3 = pixRead("/tmp/lept/numa1/histo3.png");
    pix4 = pixRead("/tmp/lept/numa1/histo4.png");
    pixaAddPix(pixa, pix1, L_INSERT);
    pixaAddPix(pixa, pix2, L_INSERT);
    pixaAddPix(pixa, pix3, L_INSERT);
    pixaAddPix(pixa, pix4, L_INSERT);
    pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2);
    pixDisplay(pixd, 600, 0);
    pixWrite("/tmp/lept/numa1/histo.png", pixd, IFF_PNG);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);
    numaDestroy(&nax);
    numaDestroy(&nahisto);

    numaGetStatsUsingHistogram(na, 2000, &minval, &maxval, &meanval,
                               &variance, &median, 0.80, &rankval, &nahisto);
    fprintf(stderr, "Sin histogram: \n"
                    "  min val  = %7.2f    -- should be -999.00\n"
                    "  max val  = %7.2f    -- should be  999.00\n"
                    "  mean val = %7.2f    -- should be    0.06\n"
                    "  median   = %7.2f    -- should be    0.30\n"
                    "  rmsdev   = %7.2f    -- should be  706.41\n"
                    "  rank val = %7.2f    -- should be  808.15\n",
            minval, maxval, meanval, median, sqrt((l_float64)variance),
            rankval);
    numaHistogramGetRankFromVal(nahisto, 808.15, &rank);
    fprintf(stderr, "  rank     = %7.3f    -- should be  0.800\n", rank);
    numaDestroy(&nahisto);
    numaDestroy(&na);
#endif

    /* -------------------------------------------------------------------*
     *                            Interpolation                           *
     * -------------------------------------------------------------------*/
#if  DO_ALL
        /* Test numaInterpolateEqxInterval() */
    pixs = pixRead("test8.jpg");
    na = pixGetGrayHistogramMasked(pixs, NULL, 0, 0, 1);
/*    numaWriteStream(stderr, na); */
    nasy = numaGetPartialSums(na);
    gplotSimple1(nasy, GPLOT_PNG, "/tmp/lept/numa1/int1", "partial sums");
    gplotSimple1(na, GPLOT_PNG, "/tmp/lept/numa1/int2", "simple test");
    numaInterpolateEqxInterval(0.0, 1.0, na, L_LINEAR_INTERP,
                               0.0, 255.0, 15, &nax, &nay);
    gplot = gplotCreate("/tmp/lept/numa1/int3", GPLOT_PNG, "test interpolation",
                        "pix val", "num pix");
    gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "plot 1");
    gplotMakeOutput(gplot);
    gplotDestroy(&gplot);
    numaDestroy(&na);
    numaDestroy(&nasy);
    numaDestroy(&nax);
    numaDestroy(&nay);
    pixDestroy(&pixs);
#endif

#if  DO_ALL
        /* Test numaInterpolateArbxInterval() */
    pixs = pixRead("test8.jpg");
    na = pixGetGrayHistogramMasked(pixs, NULL, 0, 0, 1);
    nasy = numaGetPartialSums(na);
    numaInsertNumber(nasy, 0, 0.0);
    nasx = numaMakeSequence(0.0, 1.0, 257);
/*    gplotSimple1(nasy, GPLOT_PNG, "/tmp/numa/nasy", "partial sums"); */
    numaInterpolateArbxInterval(nasx, nasy, L_LINEAR_INTERP,
                                10.0, 250.0, 23, &nax, &nay);
    gplot = gplotCreate("/tmp/lept/numa1/int4", GPLOT_PNG, "arbx interpolation",
                        "pix val", "cum num pix");
    gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "plot 1");
    gplotMakeOutput(gplot);
    gplotDestroy(&gplot);
    numaDestroy(&na);
    numaDestroy(&nasx);
    numaDestroy(&nasy);
    numaDestroy(&nax);
    numaDestroy(&nay);
    pixDestroy(&pixs);
#endif

#if  DO_ALL
        /* Test numaInterpolateArbxVal() */
    pixs = pixRead("test8.jpg");
    na = pixGetGrayHistogramMasked(pixs, NULL, 0, 0, 1);
    nasy = numaGetPartialSums(na);
    numaInsertNumber(nasy, 0, 0.0);
    nasx = numaMakeSequence(0.0, 1.0, 257);
/*    gplotSimple1(nasy, GPLOT_PNG, "/tmp/numa/nasy", "partial sums"); */
    nax = numaMakeSequence(15.0, (250.0 - 15.0) / 23.0, 24);
    n = numaGetCount(nax);
    nay = numaCreate(n);
    for (i = 0; i < n; i++) {
        numaGetFValue(nax, i, &xval);
        numaInterpolateArbxVal(nasx, nasy, L_QUADRATIC_INTERP, xval, &yval);
        numaAddNumber(nay, yval);
    }
    gplot = gplotCreate("/tmp/lept/numa1/int5", GPLOT_PNG, "arbx interpolation",
                        "pix val", "cum num pix");
    gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "plot 1");
    gplotMakeOutput(gplot);
    gplotDestroy(&gplot);
    numaDestroy(&na);
    numaDestroy(&nasx);
    numaDestroy(&nasy);
    numaDestroy(&nax);
    numaDestroy(&nay);
    pixDestroy(&pixs);
#endif

#if  DO_ALL
        /* Test interpolation */
    nasx = numaRead("testangle.na");
    nasy = numaRead("testscore.na");
    gplot = gplotCreate("/tmp/lept/numa1/int6", GPLOT_PNG, "arbx interpolation",
                        "angle", "score");
    numaInterpolateArbxInterval(nasx, nasy, L_LINEAR_INTERP,
                                -2.00, 0.0, 50, &nax, &nay);
    gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "linear");
    numaDestroy(&nax);
    numaDestroy(&nay);
    numaInterpolateArbxInterval(nasx, nasy, L_QUADRATIC_INTERP,
                                -2.00, 0.0, 50, &nax, &nay);
    gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "quadratic");
    numaDestroy(&nax);
    numaDestroy(&nay);
    gplotMakeOutput(gplot);
    gplotDestroy(&gplot);
    gplot = gplotCreate("/tmp/lept/numa1/int7", GPLOT_PNG, "arbx interpolation",
                        "angle", "score");
    numaInterpolateArbxInterval(nasx, nasy, L_LINEAR_INTERP,
                                -1.2, -0.8, 50, &nax, &nay);
    gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "quadratic");
    gplotMakeOutput(gplot);
    gplotDestroy(&gplot);
    numaFitMax(nay, &yval, nax, &xval);
    fprintf(stderr, "max = %f at loc = %f\n", yval, xval);
    pixa = pixaCreate(7);
    pix1 = pixRead("/tmp/lept/numa1/int1.png");
    pix2 = pixRead("/tmp/lept/numa1/int2.png");
    pix3 = pixRead("/tmp/lept/numa1/int3.png");
    pix4 = pixRead("/tmp/lept/numa1/int4.png");
    pix5 = pixRead("/tmp/lept/numa1/int5.png");
    pix6 = pixRead("/tmp/lept/numa1/int6.png");
    pix7 = pixRead("/tmp/lept/numa1/int7.png");
    pixaAddPix(pixa, pix1, L_INSERT);
    pixaAddPix(pixa, pix2, L_INSERT);
    pixaAddPix(pixa, pix3, L_INSERT);
    pixaAddPix(pixa, pix4, L_INSERT);
    pixaAddPix(pixa, pix5, L_INSERT);
    pixaAddPix(pixa, pix6, L_INSERT);
    pixaAddPix(pixa, pix7, L_INSERT);
    pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2);
    pixDisplay(pixd, 100, 900);
    pixWrite("/tmp/lept/numa1/int.png", pixd, IFF_PNG);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);
    numaDestroy(&nasx);
    numaDestroy(&nasy);
    numaDestroy(&nax);
    numaDestroy(&nay);
#endif

    /* -------------------------------------------------------------------*
     *                   Integration and differentiation                  *
     * -------------------------------------------------------------------*/
#if  DO_ALL
        /* Test integration and differentiation */
    nasx = numaRead("testangle.na");
    nasy = numaRead("testscore.na");
        /* ---------- Plot the derivative ---------- */
    numaDifferentiateInterval(nasx, nasy, -2.0, 0.0, 50, &nadx, &nady);
    gplot = gplotCreate("/tmp/lept/numa1/diff1", GPLOT_PNG, "derivative",
                        "angle", "slope");
    gplotAddPlot(gplot, nadx, nady, GPLOT_LINES, "derivative");
    gplotMakeOutput(gplot);
    gplotDestroy(&gplot);
        /*  ---------- Plot the original function ----------- */
        /*  and the integral of the derivative; the two       */
        /*  should be approximately the same.                 */
    gplot = gplotCreate("/tmp/lept/numa1/diff2", GPLOT_PNG, "integ-diff",
                        "angle", "val");
    numaInterpolateArbxInterval(nasx, nasy, L_LINEAR_INTERP,
                                -2.00, 0.0, 50, &nafx, &nafy);
    gplotAddPlot(gplot, nafx, nafy, GPLOT_LINES, "function");
    n = numaGetCount(nadx);
    numaGetFValue(nafx, 0, &x0);
    numaGetFValue(nafy, 0, &y0);
    nay = numaCreate(n);
        /* (Note: this tests robustness of the integrator: we go from
         * i = 0, and choose to have only 1 point in the interpolation
         * there, which is too small and causes the function to bomb out.) */
    fprintf(stderr, "We must get a 'npts < 2' error here:\n");
    for (i = 0; i < n; i++) {
        numaGetFValue(nadx, i, &xval);
        numaIntegrateInterval(nadx, nady, x0, xval, 2 * i + 1, &yval);
        numaAddNumber(nay, y0 + yval);
    }
    gplotAddPlot(gplot, nafx, nay, GPLOT_LINES, "anti-derivative");
    gplotMakeOutput(gplot);
    gplotDestroy(&gplot);
    pixa = pixaCreate(2);
    pix1 = pixRead("/tmp/lept/numa1/diff1.png");
    pix2 = pixRead("/tmp/lept/numa1/diff2.png");
    pixaAddPix(pixa, pix1, L_INSERT);
    pixaAddPix(pixa, pix2, L_INSERT);
    pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2);
    pixDisplay(pixd, 100, 450);
    pixWrite("/tmp/lept/numa1/diff.png", pixd, IFF_PNG);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);
    numaDestroy(&nasx);
    numaDestroy(&nasy);
    numaDestroy(&nafx);
    numaDestroy(&nafy);
    numaDestroy(&nadx);
    numaDestroy(&nady);
    numaDestroy(&nay);
#endif

    /* -------------------------------------------------------------------*
     *                             Rank extraction                        *
     * -------------------------------------------------------------------*/
#if  DO_ALL
        /* Rank extraction with interpolation */
    pixs = pixRead("test8.jpg");
    nasy= pixGetGrayHistogramMasked(pixs, NULL, 0, 0, 1);
    numaMakeRankFromHistogram(0.0, 1.0, nasy, 350, &nax, &nay);
    gplot = gplotCreate("/tmp/lept/numa1/rank1", GPLOT_PNG,
                        "test rank extractor", "pix val", "rank val");
    gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "plot 1");
    gplotMakeOutput(gplot);
    gplotDestroy(&gplot);
    numaDestroy(&nasy);
    numaDestroy(&nax);
    numaDestroy(&nay);
    pixDestroy(&pixs);
#endif

#if  DO_ALL
        /* Rank extraction, point by point */
    pixs = pixRead("test8.jpg");
    nap = numaCreate(200);
    pixGetRankValueMasked(pixs, NULL, 0, 0, 2, 0.0, &val, &na);
    for (i = 0; i < 101; i++) {
      rank = 0.01 * i;
      numaHistogramGetValFromRank(na, rank, &val);
      numaAddNumber(nap, val);
    }
    gplotSimple1(nap, GPLOT_PNG, "/tmp/lept/numa1/rank2", "rank value");
    pixa = pixaCreate(2);
    pix1 = pixRead("/tmp/lept/numa1/rank1.png");
    pix2 = pixRead("/tmp/lept/numa1/rank2.png");
    pixaAddPix(pixa, pix1, L_INSERT);
    pixaAddPix(pixa, pix2, L_INSERT);
    pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2);
    pixDisplay(pixd, 100, 0);
    pixWrite("/tmp/lept/numa1/rank.png", pixd, IFF_PNG);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);
    numaDestroy(&na);
    numaDestroy(&nap);
    pixDestroy(&pixs);
#endif

    /* -------------------------------------------------------------------*
     *                           Numa-morphology                          *
     * -------------------------------------------------------------------*/
#if  DO_ALL
    na = numaRead("lyra.5.na");
    gplotSimple1(na, GPLOT_PNG, "/tmp/lept/numa1/lyra1", "Original");
    na1 = numaErode(na, 21);
    gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/numa1/lyra2", "Erosion");
    na2 = numaDilate(na, 21);
    gplotSimple1(na2, GPLOT_PNG, "/tmp/lept/numa1/lyra3", "Dilation");
    na3 = numaOpen(na, 21);
    gplotSimple1(na3, GPLOT_PNG, "/tmp/lept/numa1/lyra4", "Opening");
    na4 = numaClose(na, 21);
    gplotSimple1(na4, GPLOT_PNG, "/tmp/lept/numa1/lyra5", "Closing");
    pixa = pixaCreate(2);
    pix1 = pixRead("/tmp/lept/numa1/lyra1.png");
    pix2 = pixRead("/tmp/lept/numa1/lyra2.png");
    pix3 = pixRead("/tmp/lept/numa1/lyra3.png");
    pix4 = pixRead("/tmp/lept/numa1/lyra4.png");
    pix5 = pixRead("/tmp/lept/numa1/lyra5.png");
    pixaAddPix(pixa, pix1, L_INSERT);
    pixaAddPix(pixa, pix2, L_INSERT);
    pixaAddPix(pixa, pix3, L_INSERT);
    pixaAddPix(pixa, pix4, L_INSERT);
    pixaAddPix(pixa, pix5, L_INSERT);
    pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2);
    pixDisplay(pixd, 600, 450);
    pixWrite("/tmp/lept/numa1/morph.png", pixd, IFF_PNG);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);
    numaDestroy(&na);
    numaDestroy(&na1);
    numaDestroy(&na2);
    numaDestroy(&na3);
    numaDestroy(&na4);
    pixaDestroy(&pixa);
#endif

    return 0;
}
Exemple #5
0
/*!
 *  pixGetWordsInTextlines()
 *
 *      Input:  pixs (1 bpp, typ. 300 ppi)
 *              reduction (1 for input res; 2 for 2x reduction of input res)
 *              minwidth, minheight (of saved components; smaller are discarded)
 *              maxwidth, maxheight (of saved components; larger are discarded)
 *              &boxad (<return> word boxes sorted in textline line order)
 *              &pixad (<return> word images sorted in textline line order)
 *              &naindex (<return> index of textline for each word)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) The input should be at a resolution of about 300 ppi.
 *          The word masks and word images can be computed at either
 *          150 ppi or 300 ppi.  For the former, set reduction = 2.
 *      (2) The four size constraints on saved components are all
 *          scaled by @reduction.
 *      (3) The result are word images (and their b.b.), extracted in
 *          textline order, at either full res or 2x reduction,
 *          and with a numa giving the textline index for each word.
 *      (4) The pixa and boxa interfaces should make this type of
 *          application simple to put together.  The steps are:
 *           - optionally reduce by 2x
 *           - generate first estimate of word masks
 *           - get b.b. of these, and remove the small and big ones
 *           - extract pixa of the word images, using the b.b.
 *           - sort actual word images in textline order (2d)
 *           - flatten them to a pixa (1d), saving the textline index
 *             for each pix
 *      (5) In an actual application, it may be desirable to pre-filter
 *          the input image to remove large components, to extract
 *          single columns of text, and to deskew them.  For example,
 *          to remove both large components and small noisy components
 *          that can interfere with the statistics used to estimate
 *          parameters for segmenting by words, but still retain text lines,
 *          the following image preprocessing can be done:
 *                Pix *pixt = pixMorphSequence(pixs, "c40.1", 0);
 *                Pix *pixf = pixSelectBySize(pixt, 0, 60, 8,
 *                                     L_SELECT_HEIGHT, L_SELECT_IF_LT, NULL);
 *                pixAnd(pixf, pixf, pixs);  // the filtered image
 *          The closing turns text lines into long blobs, but does not
 *          significantly increase their height.  But if there are many
 *          small connected components in a dense texture, this is likely
 *          to generate tall components that will be eliminated in pixf.
 */
l_int32
pixGetWordsInTextlines(PIX     *pixs,
                       l_int32  reduction,
                       l_int32  minwidth,
                       l_int32  minheight,
                       l_int32  maxwidth,
                       l_int32  maxheight,
                       BOXA   **pboxad,
                       PIXA   **ppixad,
                       NUMA   **pnai)
{
l_int32  maxdil;
BOXA    *boxa1, *boxad;
BOXAA   *baa;
NUMA    *nai;
NUMAA   *naa;
PIXA    *pixa1, *pixad;
PIX     *pix1;
PIXAA   *paa;

    PROCNAME("pixGetWordsInTextlines");

    if (!pboxad || !ppixad || !pnai)
        return ERROR_INT("&boxad, &pixad, &nai not all defined", procName, 1);
    *pboxad = NULL;
    *ppixad = NULL;
    *pnai = NULL;
    if (!pixs)
        return ERROR_INT("pixs not defined", procName, 1);
    if (reduction != 1 && reduction != 2)
        return ERROR_INT("reduction not in {1,2}", procName, 1);

    if (reduction == 1) {
        pix1 = pixClone(pixs);
        maxdil = 18;
    } else {  /* reduction == 2 */
        pix1 = pixReduceRankBinaryCascade(pixs, 1, 0, 0, 0);
        maxdil = 9;
    }

        /* Get the bounding boxes of the words from the word mask. */
    pixWordBoxesByDilation(pix1, maxdil, minwidth, minheight,
                           maxwidth, maxheight, &boxa1, NULL);

        /* Generate a pixa of the word images */
    pixa1 = pixaCreateFromBoxa(pix1, boxa1, NULL);  /* mask over each word */

        /* Sort the bounding boxes of these words by line.  We use the
         * index mapping to allow identical sorting of the pixa. */
    baa = boxaSort2d(boxa1, &naa, -1, -1, 4);
    paa = pixaSort2dByIndex(pixa1, naa, L_CLONE);

        /* Flatten the word paa */
    pixad = pixaaFlattenToPixa(paa, &nai, L_CLONE);
    boxad = pixaGetBoxa(pixad, L_COPY);

    *pnai = nai;
    *pboxad = boxad;
    *ppixad = pixad;

    pixDestroy(&pix1);
    pixaDestroy(&pixa1);
    boxaDestroy(&boxa1);
    boxaaDestroy(&baa);
    pixaaDestroy(&paa);
    numaaDestroy(&naa);
    return 0;
}
Exemple #6
0
/*!
 *  pixaDisplayTiledAndScaled()
 *
 *      Input:  pixa
 *              outdepth (output depth: 1, 8 or 32 bpp)
 *              tilewidth (each pix is scaled to this width)
 *              ncols (number of tiles in each row)
 *              background (0 for white, 1 for black; this is the color
 *                 of the spacing between the images)
 *              spacing  (between images, and on outside)
 *              border (width of additional black border on each image;
 *                      use 0 for no border)
 *      Return: pix of tiled images, or null on error
 *
 *  Notes:
 *      (1) This can be used to tile a number of renderings of
 *          an image that are at different scales and depths.
 *      (2) Each image, after scaling and optionally adding the
 *          black border, has width 'tilewidth'.  Thus, the border does
 *          not affect the spacing between the image tiles.  The
 *          maximum allowed border width is tilewidth / 5.
 */
PIX *
pixaDisplayTiledAndScaled(PIXA    *pixa,
                          l_int32  outdepth,
                          l_int32  tilewidth,
                          l_int32  ncols,
                          l_int32  background,
                          l_int32  spacing,
                          l_int32  border)
{
l_int32    x, y, w, h, wd, hd, d;
l_int32    i, n, nrows, maxht, ninrow, irow, bordval;
l_int32   *rowht;
l_float32  scalefact;
PIX       *pix, *pixn, *pixt, *pixb, *pixd;
PIXA      *pixan;

    PROCNAME("pixaDisplayTiledAndScaled");

    if (!pixa)
        return (PIX *)ERROR_PTR("pixa not defined", procName, NULL);
    if (outdepth != 1 && outdepth != 8 && outdepth != 32)
        return (PIX *)ERROR_PTR("outdepth not in {1, 8, 32}", procName, NULL);
    if (border < 0 || border > tilewidth / 5)
        border = 0;
    
    if ((n = pixaGetCount(pixa)) == 0)
        return (PIX *)ERROR_PTR("no components", procName, NULL);

        /* Normalize scale and depth for each pix; optionally add border */
    pixan = pixaCreate(n);
    bordval = (outdepth == 1) ? 1 : 0;
    for (i = 0; i < n; i++) {
        if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL)
            continue;

        pixGetDimensions(pix, &w, &h, &d);
        scalefact = (l_float32)(tilewidth - 2 * border) / (l_float32)w;
        if (d == 1 && outdepth > 1 && scalefact < 1.0)
            pixt = pixScaleToGray(pix, scalefact);
        else
            pixt = pixScale(pix, scalefact, scalefact);

        if (outdepth == 1)
            pixn = pixConvertTo1(pixt, 128);
        else if (outdepth == 8)
            pixn = pixConvertTo8(pixt, FALSE);
        else  /* outdepth == 32 */
            pixn = pixConvertTo32(pixt);
        pixDestroy(&pixt);

        if (border)
            pixb = pixAddBorder(pixn, border, bordval);
        else
            pixb = pixClone(pixn);

        pixaAddPix(pixan, pixb, L_INSERT);
        pixDestroy(&pix);
        pixDestroy(&pixn);
    }
    if ((n = pixaGetCount(pixan)) == 0) { /* should not have changed! */
        pixaDestroy(&pixan);
        return (PIX *)ERROR_PTR("no components", procName, NULL);
    }

        /* Determine the size of each row and of pixd */
    wd = tilewidth * ncols + spacing * (ncols + 1);
    nrows = (n + ncols - 1) / ncols;
    if ((rowht = (l_int32 *)CALLOC(nrows, sizeof(l_int32))) == NULL)
        return (PIX *)ERROR_PTR("rowht array not made", procName, NULL);
    maxht = 0;
    ninrow = 0;
    irow = 0;
    for (i = 0; i < n; i++) {
        pix = pixaGetPix(pixan, i, L_CLONE);
        ninrow++;
        pixGetDimensions(pix, &w, &h, NULL);
        maxht = L_MAX(h, maxht);
        if (ninrow == ncols) {
            rowht[irow] = maxht;
            maxht = ninrow = 0;  /* reset */
            irow++;
        }
        pixDestroy(&pix);
    }
    if (ninrow > 0) {   /* last fencepost */
        rowht[irow] = maxht;
        irow++;  /* total number of rows */
    }
    nrows = irow;
    hd = spacing * (nrows + 1);
    for (i = 0; i < nrows; i++)
        hd += rowht[i];

    pixd = pixCreate(wd, hd, outdepth);
    if ((background == 1 && outdepth == 1) ||
        (background == 0 && outdepth != 1))
        pixSetAll(pixd);

        /* Now blit images to pixd */
    x = y = spacing;
    irow = 0;
    for (i = 0; i < n; i++) {
        pix = pixaGetPix(pixan, i, L_CLONE);
        pixGetDimensions(pix, &w, &h, NULL);
        if (i && ((i % ncols) == 0)) {  /* start new row */
            x = spacing;
            y += spacing + rowht[irow];
            irow++;
        }
        pixRasterop(pixd, x, y, w, h, PIX_SRC, pix, 0, 0);
        x += tilewidth + spacing;
        pixDestroy(&pix);
    }

    pixaDestroy(&pixan);
    FREE(rowht);
    return pixd;
}
Exemple #7
0
/*!
 *  pixaaDisplayByPixa()
 *
 *      Input:  pixaa
 *              xspace between pix in pixa
 *              yspace between pixa
 *              max width of output pix
 *      Return: pix, or null on error
 *
 *  Notes:
 *      (1) Displays each pixa on a line (or set of lines),
 *          in order from top to bottom.  Within each pixa,
 *          the pix are displayed in order from left to right.
 *      (2) The size of each pix in each pixa is assumed to be
 *          approximately equal to the size of the first pix in
 *          the pixa.  If this assumption is not correct, this
 *          function will not work properly.
 *      (3) This ignores the boxa of the pixaa.
 */
PIX *
pixaaDisplayByPixa(PIXAA   *pixaa,
                   l_int32  xspace,
                   l_int32  yspace,
                   l_int32  maxw)
{
l_int32  i, j, npixa, npix;
l_int32  width, height, depth, nlines, lwidth;
l_int32  x, y, w, h, w0, h0;
PIX     *pixt, *pixd;
PIXA    *pixa;

    PROCNAME("pixaaDisplayByPixa");

    if (!pixaa)
        return (PIX *)ERROR_PTR("pixaa not defined", procName, NULL);
    
    if ((npixa = pixaaGetCount(pixaa)) == 0)
        return (PIX *)ERROR_PTR("no components", procName, NULL);

        /* Get size of output pix.  The width is the minimum of the
         * maxw and the largest pixa line width.  The height is whatever
         * it needs to be to accommodate all pixa. */
    height = 2 * yspace;
    width = 0;
    for (i = 0; i < npixa; i++) {
        pixa = pixaaGetPixa(pixaa, i, L_CLONE);
        npix = pixaGetCount(pixa);
        pixt = pixaGetPix(pixa, 0, L_CLONE);
        if (i == 0)
            depth = pixGetDepth(pixt);
        w = pixGetWidth(pixt);
        lwidth = npix * (w + xspace);
        nlines = (lwidth + maxw - 1) / maxw;
        if (nlines > 1)
            width = maxw;
        else
            width = L_MAX(lwidth, width);
        height += nlines * (pixGetHeight(pixt) + yspace);
        pixDestroy(&pixt);
        pixaDestroy(&pixa);
    }

    if ((pixd = pixCreate(width, height, depth)) == NULL)
        return (PIX *)ERROR_PTR("pixd not made", procName, NULL);

        /* Now layout the pix by pixa */
    y = yspace;
    for (i = 0; i < npixa; i++) {
        x = 0;
        pixa = pixaaGetPixa(pixaa, i, L_CLONE);
        npix = pixaGetCount(pixa);
        for (j = 0; j < npix; j++) {
            pixt = pixaGetPix(pixa, j, L_CLONE);
            if (j == 0) {
                w0 = pixGetWidth(pixt);
                h0 = pixGetHeight(pixt);
            }
            w = pixGetWidth(pixt);
            if (width == maxw && x + w >= maxw) {
                x = 0;
                y += h0 + yspace;
            }
            h = pixGetHeight(pixt);
            pixRasterop(pixd, x, y, w, h, PIX_PAINT, pixt, 0, 0);
            pixDestroy(&pixt);
            x += w0 + xspace;
        }
        y += h0 + yspace;
        pixaDestroy(&pixa);
    }

    return pixd;
}
Exemple #8
0
int main(int    argc,
         char **argv)
{
l_uint8     *data1, *data2;
l_int32      i, same, w, h, width, success, nba;
size_t       size1, size2;
l_float32    diffarea, diffxor, scalefact;
BOX         *box;
BOXA        *boxa1, *boxa2, *boxa3;
BOXAA       *baa1, *baa2, *baa3;
PIX         *pix1, *pix2, *pix3, *pixdb;
PIXA        *pixa1, *pixa2;
L_REGPARAMS  *rp;

    if (regTestSetup(argc, argv, &rp))
        return 1;

    lept_mkdir("lept/boxa");

        /* Make a boxa and display its contents */
    boxa1 = boxaCreate(6);
    box = boxCreate(60, 60, 40, 20);
    boxaAddBox(boxa1, box, L_INSERT);
    box = boxCreate(120, 50, 20, 50);
    boxaAddBox(boxa1, box, L_INSERT);
    box = boxCreate(50, 140, 46, 60);
    boxaAddBox(boxa1, box, L_INSERT);
    box = boxCreate(166, 130, 64, 28);
    boxaAddBox(boxa1, box, L_INSERT);
    box = boxCreate(64, 224, 44, 34);
    boxaAddBox(boxa1, box, L_INSERT);
    box = boxCreate(117, 206, 26, 74);
    boxaAddBox(boxa1, box, L_INSERT);
    pix1 = DisplayBoxa(boxa1);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 0 */
    pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display);
    pixDestroy(&pix1);

    boxaCompareRegions(boxa1, boxa1, 100, &same, &diffarea, &diffxor, NULL);
    regTestCompareValues(rp, 1, same, 0.0);  /* 1 */
    regTestCompareValues(rp, 0.0, diffarea, 0.0);  /* 2 */
    regTestCompareValues(rp, 0.0, diffxor, 0.0);  /* 3 */

    boxa2 = boxaTransform(boxa1, -13, -13, 1.0, 1.0);
    boxaCompareRegions(boxa1, boxa2, 10, &same, &diffarea, &diffxor, NULL);
    regTestCompareValues(rp, 1, same, 0.0);  /* 4 */
    regTestCompareValues(rp, 0.0, diffarea, 0.0);  /* 5 */
    regTestCompareValues(rp, 0.0, diffxor, 0.0);  /* 6 */
    boxaDestroy(&boxa2);

    boxa2 = boxaReconcileEvenOddHeight(boxa1, L_ADJUST_TOP_AND_BOT, 6,
                                       L_ADJUST_CHOOSE_MIN, 1.0, 0);
    pix1 = DisplayBoxa(boxa2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 7 */
    pixDisplayWithTitle(pix1, 200, 0, NULL, rp->display);
    pixDestroy(&pix1);

    boxaCompareRegions(boxa1, boxa2, 10, &same, &diffarea, &diffxor, &pixdb);
    regTestCompareValues(rp, 1, same, 0.0);  /* 8 */
    regTestCompareValues(rp, 0.053, diffarea, 0.002);  /* 9 */
    regTestCompareValues(rp, 0.240, diffxor, 0.002);  /* 10 */
    regTestWritePixAndCheck(rp, pixdb, IFF_PNG);  /* 11 */
    pixDisplayWithTitle(pixdb, 400, 0, NULL, rp->display);
    pixDestroy(&pixdb);
    boxaDestroy(&boxa1);
    boxaDestroy(&boxa2);

        /* Input is a fairly clean boxa */
    boxa1 = boxaRead("boxa1.ba");
    boxa2 = boxaReconcileEvenOddHeight(boxa1, L_ADJUST_TOP, 80,
                                       L_ADJUST_CHOOSE_MIN, 1.05, 1);
    width = 100;
    boxaGetExtent(boxa2, &w, &h, NULL);
    scalefact = (l_float32)width / (l_float32)w;
    boxa3 = boxaTransform(boxa2, 0, 0, scalefact, scalefact);
    pix1 = boxaDisplayTiled(boxa3, NULL, 1500, 2, 1.0, 0, 3, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 12 */
    pixDisplayWithTitle(pix1, 600, 0, NULL, rp->display);
    pixDestroy(&pix1);
    boxaDestroy(&boxa1);
    boxaDestroy(&boxa2);
    boxaDestroy(&boxa3);

        /* Input is an unsmoothed and noisy boxa */
    boxa1 = boxaRead("boxa2.ba");
    boxa2 = boxaReconcileEvenOddHeight(boxa1, L_ADJUST_TOP, 80,
                                       L_ADJUST_CHOOSE_MIN, 1.05, 1);
    width = 100;
    boxaGetExtent(boxa2, &w, &h, NULL);
    scalefact = (l_float32)width / (l_float32)w;
    boxa3 = boxaTransform(boxa2, 0, 0, scalefact, scalefact);
    pix1 = boxaDisplayTiled(boxa3, NULL, 1500, 2, 1.0, 0, 3, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 13 */
    pixDisplayWithTitle(pix1, 800, 0, NULL, rp->display);
    pixDestroy(&pix1);
    boxaDestroy(&boxa1);
    boxaDestroy(&boxa2);
    boxaDestroy(&boxa3);

        /* Input is an unsmoothed and noisy boxa */
    boxa1 = boxaRead("boxa2.ba");
    boxa2 = boxaSmoothSequenceMedian(boxa1, 10, L_SUB_ON_LOC_DIFF, 80, 20, 1);
    boxa3 = boxaSmoothSequenceMedian(boxa1, 10, L_SUB_ON_SIZE_DIFF, 80, 20, 1);
    boxaPlotSides(boxa1, "initial", NULL, NULL, NULL, NULL, &pix1);
    boxaPlotSides(boxa2, "side_smoothing", NULL, NULL, NULL, NULL, &pix2);
    boxaPlotSides(boxa3, "size_smoothing", NULL, NULL, NULL, NULL, &pix3);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 14 */
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 15 */
    regTestWritePixAndCheck(rp, pix3, IFF_PNG);  /* 16 */
    pixDisplayWithTitle(pix1, 1300, 0, NULL, rp->display);
    pixDisplayWithTitle(pix2, 1300, 500, NULL, rp->display);
    pixDisplayWithTitle(pix3, 1300, 1000, NULL, rp->display);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix3);
    boxaDestroy(&boxa1);
    boxaDestroy(&boxa2);
    boxaDestroy(&boxa3);

        /* Input is a boxa smoothed with a median window filter */
    boxa1 = boxaRead("boxa3.ba");
    boxa2 = boxaReconcileEvenOddHeight(boxa1, L_ADJUST_TOP, 80,
                                       L_ADJUST_CHOOSE_MIN, 1.05, 1);
    width = 100;
    boxaGetExtent(boxa2, &w, &h, NULL);
    scalefact = (l_float32)width / (l_float32)w;
    boxa3 = boxaTransform(boxa2, 0, 0, scalefact, scalefact);
    pix1 = boxaDisplayTiled(boxa3, NULL, 1500, 2, 1.0, 0, 3, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 17 */
    pixDisplayWithTitle(pix1, 1000, 0, NULL, rp->display);
    pixDestroy(&pix1);
    boxaDestroy(&boxa1);
    boxaDestroy(&boxa2);
    boxaDestroy(&boxa3);

        /* Test serialized boxa I/O to and from memory */
    data1 = l_binaryRead("boxa2.ba", &size1);
    boxa1 = boxaReadMem(data1, size1);
    boxaWriteMem(&data2, &size2, boxa1);
    boxa2 = boxaReadMem(data2, size2);
    boxaWrite("/tmp/lept/boxa/boxa1.ba", boxa1);
    boxaWrite("/tmp/lept/boxa/boxa2.ba", boxa2);
    filesAreIdentical("/tmp/lept/boxa/boxa1.ba", "/tmp/lept/boxa/boxa2.ba",
                      &same); 
    regTestCompareValues(rp, 1, same, 0.0);  /* 18 */
    boxaDestroy(&boxa1);
    boxaDestroy(&boxa2);
    lept_free(data1);
    lept_free(data2);

        /* ----------- Test pixaDisplayBoxaa() ------------ */
    pixa1 = pixaReadBoth("showboxes.pac");
    baa1 = boxaaRead("showboxes1.baa");
    baa2 = boxaaTranspose(baa1);
    baa3 = boxaaTranspose(baa2);
    nba = boxaaGetCount(baa1);
    success = TRUE;
    for (i = 0; i < nba; i++) {
        boxa1 = boxaaGetBoxa(baa1, i, L_CLONE);
        boxa2 = boxaaGetBoxa(baa3, i, L_CLONE);
        boxaEqual(boxa1, boxa2, 0, NULL, &same);
        boxaDestroy(&boxa1);
        boxaDestroy(&boxa2);
        if (!same) success = FALSE;
    }
        /* Check that the transpose is reversible */
    regTestCompareValues(rp, 1, success, 0.0);  /* 19 */
    pixa2 = pixaDisplayBoxaa(pixa1, baa2, L_DRAW_RGB, 2);
    pix1 = pixaDisplayTiledInRows(pixa2, 32, 1400, 1.0, 0, 10, 0);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 20 */
    pixDisplayWithTitle(pix1, 0, 600, NULL, rp->display);
    fprintf(stderr, "Writing to: /tmp/lept/boxa/show.pdf\n");
    l_pdfSetDateAndVersion(FALSE);
    pixaConvertToPdf(pixa2, 75, 1.0, 0, 0, NULL, "/tmp/lept/boxa/show.pdf");
    regTestCheckFile(rp, "/tmp/lept/boxa/show.pdf");  /* 21 */
    pixDestroy(&pix1);
    pixaDestroy(&pixa1);
    pixaDestroy(&pixa2);
    boxaaDestroy(&baa1);
    boxaaDestroy(&baa2);
    boxaaDestroy(&baa3);

    return regTestCleanup(rp);
}
Exemple #9
0
l_int32 main(int    argc,
             char **argv)
{
char      *boxatxt;
l_int32    i;
BOXA      *boxa1, *boxa2, *boxa3;
BOXAA     *baa, *baa1;
NUMAA     *naa1;
PIX       *pixdb, *pix1, *pix2, *pix3, *pix4;
PIXA      *pixa1, *pixa2, *pixa3, *pixat;
L_RECOG   *recog;
L_RECOGA  *recoga;
SARRAY    *sa1;

    /* ----- Example identifying samples using training data ----- */
#if 1
        /* Read the training data */
    pixat = pixaRead("recog/sets/train06.pa");
    recog = recogCreateFromPixa(pixat, 0, 0, L_USE_ALL, 128, 1, "fonts");
    recoga = recogaCreateFromRecog(recog);
    pixaDestroy(&pixat);

        /* Read the data from all samples */
    pix1 = pixRead("recog/sets/samples06.png");
    boxatxt = pixGetText(pix1);
    boxa1 = boxaReadMem((l_uint8 *)boxatxt, strlen(boxatxt));
    pixa1 = pixaCreateFromBoxa(pix1, boxa1, NULL);
    pixDestroy(&pix1);  /* destroys boxa1 */

        /* Identify components in the sample data */
    pixa2 = pixaCreate(0);
    pixa3 = pixaCreate(0);
    for (i = 0; i < 9; i++) {
/*        if (i != 4) continue; */  /* dots form separate boxa */
/*        if (i != 8) continue; */  /* broken 2 in '24' */
        pix1 = pixaGetPix(pixa1, i, L_CLONE);

            /* Show the 2d box data in the sample */
        boxa2 = pixConnComp(pix1, NULL, 8);
        baa = boxaSort2d(boxa2, NULL, 6, 6, 5);
        pix2 = boxaaDisplay(baa, 3, 1, 0xff000000, 0x00ff0000, 0, 0);
        pixaAddPix(pixa3, pix2, L_INSERT);
        boxaaDestroy(&baa);
        boxaDestroy(&boxa2);

            /* Get the numbers in the sample */
        recogaIdentifyMultiple(recoga, pix1, 0, 5, 3, &boxa3, NULL, &pixdb, 0);
        sa1 = recogaExtractNumbers(recoga, boxa3, 0.7, -1, &baa1, &naa1);
        sarrayWriteStream(stderr, sa1);
        boxaaWriteStream(stderr, baa1);
        numaaWriteStream(stderr, naa1);
        pixaAddPix(pixa2, pixdb, L_INSERT);
/*        pixaWrite("/tmp/pixa.pa", pixa2); */
        pixDestroy(&pix1);
        boxaDestroy(&boxa3);
        boxaaDestroy(&baa1);
        numaaDestroy(&naa1);
        sarrayDestroy(&sa1);
    }

    pix3 = pixaDisplayLinearly(pixa2, L_VERT, 1.0, 0, 20, 1, NULL);
    pixWrite("/tmp/pix3.png", pix3, IFF_PNG);
    pix4 = pixaDisplayTiledInRows(pixa3, 32, 1500, 1.0, 0, 20, 2);
    pixDisplay(pix4, 500, 0);
    pixWrite("/tmp/pix4.png", pix4, IFF_PNG);
    pixaDestroy(&pixa2);
    pixaDestroy(&pixa3);
    pixDestroy(&pix1);
    pixDestroy(&pix3);
    pixDestroy(&pix4);
    pixaDestroy(&pixa1);
    boxaDestroy(&boxa1);
    recogaDestroy(&recoga);
#endif

    return 0;
}
Exemple #10
0
int main(int argc,
         char **argv) {
    char textstr[256];
    l_int32 i, thresh, fgval, bgval;
    l_float32 scorefract;
    L_BMF *bmf;
    PIX *pixs, *pixb, *pixb2, *pixb3, *pixg, *pixp, *pixt1, *pixt2;
    PIXA *pixa;

    pixs = pixRead("1555-7.jpg");
    pixg = pixConvertTo8(pixs, 0);
    bmf = bmfCreate("fonts", 8);
    for (i = 0; i < 3; i++) {
        pixa = pixaCreate(3);
        scorefract = 0.1 * i;
        pixOtsuAdaptiveThreshold(pixg, 2000, 2000, 0, 0, scorefract,
                                 NULL, &pixb);
        pixSaveTiledOutline(pixb, pixa, 0.5, 1, 20, 2, 32);
        pixSplitDistributionFgBg(pixg, scorefract, 1, &thresh, &fgval, &bgval, 1);
        fprintf(stderr, "thresh = %d, fgval = %d, bgval = %d\n", thresh, fgval,
                bgval);

        /* Give gnuplot time to write out the plot */
#ifndef  _WIN32
        sleep(1);
#else
        Sleep(1000);
#endif  /* _WIN32 */

        pixp = pixRead("/tmp/histplot.png");
        pixSaveTiled(pixp, pixa, 1.0, 0, 20, 1);
        pixt1 = pixaDisplay(pixa, 0, 0);
        snprintf(textstr, sizeof(textstr),
                 "Scorefract = %3.1f ........... Thresh = %d", scorefract, thresh);
        pixt2 = pixAddSingleTextblock(pixt1, bmf, textstr, 0x00ff0000,
                                      L_ADD_BELOW, NULL);
        pixDisplay(pixt2, 100, 100);
        snprintf(textstr, sizeof(textstr), "/tmp/otsu.%d.png", i);
        pixWrite(textstr, pixt2, IFF_PNG);
        pixDestroy(&pixb);
        pixDestroy(&pixp);
        pixDestroy(&pixt1);
        pixDestroy(&pixt2);
        pixaDestroy(&pixa);
    }

    pixa = pixaCreate(2);
    for (i = 0; i < 2; i++) {
        scorefract = 0.1 * i;
        pixOtsuAdaptiveThreshold(pixg, 300, 300, 0, 0, scorefract,
                                 NULL, &pixb);
        pixb2 = pixAddBlackOrWhiteBorder(pixb, 2, 2, 2, 2, L_GET_BLACK_VAL);
        snprintf(textstr, sizeof(textstr),
                 "Scorefract = %3.1f", scorefract);
        pixb3 = pixAddSingleTextblock(pixb2, bmf, textstr, 1,
                                      L_ADD_BELOW, NULL);
        pixSaveTiled(pixb3, pixa, 2, (i + 1) % 1, 20, 32);
        pixDestroy(&pixb);
        pixDestroy(&pixb2);
    }
    pixb = pixaDisplay(pixa, 0, 0);
    pixWrite("/tmp/otsu-tiled.jpg", pixb, IFF_PNG);
    pixDestroy(&pixb);
    pixaDestroy(&pixa);

    bmfDestroy(&bmf);
    pixDestroy(&pixs);
    pixDestroy(&pixg);
    return 0;
}
Exemple #11
0
static PIX *
shearTest(PIX     *pixs,
          l_int32  reduction)
{
l_int32   w, h, d;
PIX      *pixt1, *pixt2, *pixd;
PIXA     *pixa;

    PROCNAME("shearTest");

    pixa = pixaCreate(0);
    pixGetDimensions(pixs, &w, &h, &d);

    pixt1 = pixHShear(NULL, pixs, 0, ANGLE1, L_BRING_IN_WHITE);
    pixSaveTiled(pixt1, pixa, reduction, 1, 20, 32);
    pixt2 = pixHShear(NULL, pixs, h / 2, ANGLE1, L_BRING_IN_WHITE);
    pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixt1 = pixHShear(NULL, pixs, 0, ANGLE1, L_BRING_IN_BLACK);
    pixSaveTiled(pixt1, pixa, reduction, 0, 20, 0);
    pixt2 = pixHShear(NULL, pixs, h / 2, ANGLE1, L_BRING_IN_BLACK);
    pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);

    if (!pixGetColormap(pixs)) {
        pixt1 = pixCopy(NULL, pixs);
        pixHShearIP(pixt1, 0, ANGLE1, L_BRING_IN_WHITE);
        pixSaveTiled(pixt1, pixa, reduction, 1, 20, 0);
        pixt2 = pixCopy(NULL, pixs);
        pixHShearIP(pixt2, h / 2, ANGLE1, L_BRING_IN_WHITE);
        pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0);
        pixDestroy(&pixt1);
        pixDestroy(&pixt2);
        pixt1 = pixCopy(NULL, pixs);
        pixHShearIP(pixt1, 0, ANGLE1, L_BRING_IN_BLACK);
        pixSaveTiled(pixt1, pixa, reduction, 0, 20, 0);
        pixt2 = pixCopy(NULL, pixs);
        pixHShearIP(pixt2, h / 2, ANGLE1, L_BRING_IN_BLACK);
        pixSaveTiled(pixt2, pixa, reduction, 0, 20, 32);
        pixDestroy(&pixt1);
        pixDestroy(&pixt2);
    }

    if (d == 8 || d == 32 || pixGetColormap(pixs)) {
        pixt1 = pixHShearLI(pixs, 0, ANGLE1, L_BRING_IN_WHITE);
        pixSaveTiled(pixt1, pixa, reduction, 1, 20, 0);
        pixt2 = pixHShearLI(pixs, w / 2, ANGLE1, L_BRING_IN_WHITE);
        pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0);
        pixDestroy(&pixt1);
        pixDestroy(&pixt2);
        pixt1 = pixHShearLI(pixs, 0, ANGLE1, L_BRING_IN_BLACK);
        pixSaveTiled(pixt1, pixa, reduction, 0, 20, 0);
        pixt2 = pixHShearLI(pixs, w / 2, ANGLE1, L_BRING_IN_BLACK);
        pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0);
        pixDestroy(&pixt1);
        pixDestroy(&pixt2);
    }

    pixt1 = pixVShear(NULL, pixs, 0, ANGLE1, L_BRING_IN_WHITE);
    pixSaveTiled(pixt1, pixa, reduction, 1, 20, 0);
    pixt2 = pixVShear(NULL, pixs, w / 2, ANGLE1, L_BRING_IN_WHITE);
    pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixt1 = pixVShear(NULL, pixs, 0, ANGLE1, L_BRING_IN_BLACK);
    pixSaveTiled(pixt1, pixa, reduction, 0, 20, 0);
    pixt2 = pixVShear(NULL, pixs, w / 2, ANGLE1, L_BRING_IN_BLACK);
    pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);

    if (!pixGetColormap(pixs)) {
        pixt1 = pixCopy(NULL, pixs);
        pixVShearIP(pixt1, 0, ANGLE1, L_BRING_IN_WHITE);
        pixSaveTiled(pixt1, pixa, reduction, 1, 20, 0);
        pixt2 = pixCopy(NULL, pixs);
        pixVShearIP(pixt2, w / 2, ANGLE1, L_BRING_IN_WHITE);
        pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0);
        pixDestroy(&pixt1);
        pixDestroy(&pixt2);
        pixt1 = pixCopy(NULL, pixs);
        pixVShearIP(pixt1, 0, ANGLE1, L_BRING_IN_BLACK);
        pixSaveTiled(pixt1, pixa, reduction, 0, 20, 0);
        pixt2 = pixCopy(NULL, pixs);
        pixVShearIP(pixt2, w / 2, ANGLE1, L_BRING_IN_BLACK);
        pixSaveTiled(pixt2, pixa, reduction, 0, 20, 32);
        pixDestroy(&pixt1);
        pixDestroy(&pixt2);
    }

    if (d == 8 || d == 32 || pixGetColormap(pixs)) {
        pixt1 = pixVShearLI(pixs, 0, ANGLE1, L_BRING_IN_WHITE);
        pixSaveTiled(pixt1, pixa, reduction, 1, 20, 0);
        pixt2 = pixVShearLI(pixs, w / 2, ANGLE1, L_BRING_IN_WHITE);
        pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0);
        pixDestroy(&pixt1);
        pixDestroy(&pixt2);
        pixt1 = pixVShearLI(pixs, 0, ANGLE1, L_BRING_IN_BLACK);
        pixSaveTiled(pixt1, pixa, reduction, 0, 20, 0);
        pixt2 = pixVShearLI(pixs, w / 2, ANGLE1, L_BRING_IN_BLACK);
        pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0);
        pixDestroy(&pixt1);
        pixDestroy(&pixt2);
    }

    pixd = pixaDisplay(pixa, 0, 0);
    pixaDestroy(&pixa);
    return pixd;
}
Exemple #12
0
int main(int argc,
         char **argv) {
    const char *name;
    l_int32 i, n;
    BOX *box;
    PIX *pix0, *pix1, *pixd;
    PIXA *pixa;
    SARRAY *sa1, *sa2, *sa3, *sa4;
    L_REGPARAMS *rp;

    if (regTestSetup(argc, argv, &rp))
        return 1;

    /* ----------------  Find all the jpg and tif images --------------- */
    sa1 = getSortedPathnamesInDirectory(".", ".jpg", 0, 0);
    sa2 = getSortedPathnamesInDirectory(".", ".tif", 0, 0);
    sa3 = sarraySelectByRange(sa1, 0, 9);
    sa4 = sarraySelectByRange(sa2, 0, 9);
    sarrayConcatenate(sa3, sa4);
    n = sarrayGetCount(sa3);
    sarrayDestroy(&sa1);
    sarrayDestroy(&sa2);
    sarrayDestroy(&sa4);

    /* ---------------- Use replace to fill up a pixa -------------------*/
    pixa = pixaCreate(1);
    pixaExtendArrayToSize(pixa, n);
    if ((pix0 = pixRead("marge.jpg")) == NULL)
        rp->success = FALSE;
    pix1 = pixScaleToSize(pix0, 144, 108);  /* scale 0.25 */
    pixDestroy(&pix0);
    pixaInitFull(pixa, pix1, NULL);  /* fill it up */
    pixd = pixaDisplayTiledInRows(pixa, 32, 1000, 1.0, 0, 25, 2);
    pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display);
    pixWrite("/tmp/regout/pix1.jpg", pixd, IFF_JFIF_JPEG);
    pixDestroy(&pix1);
    pixDestroy(&pixd);

    /* ---------------- And again with jpgs and tifs -------------------*/
    for (i = 0; i < n; i++) {
        name = sarrayGetString(sa3, i, L_NOCOPY);
        if ((pix0 = pixRead(name)) == NULL)
            rp->success = FALSE;
        pix1 = pixScaleToSize(pix0, 144, 108);
        pixaReplacePix(pixa, i, pix1, NULL);
        pixDestroy(&pix0);
    }
    pixd = pixaDisplayTiledInRows(pixa, 32, 1000, 1.0, 0, 25, 2);
    pixDisplayWithTitle(pixd, 400, 100, NULL, rp->display);
    pixWrite("/tmp/regout/pix2.jpg", pixd, IFF_JFIF_JPEG);
    pixDestroy(&pixd);

    /* ---------------- And again, reversing the order ------------------*/
    box = boxCreate(0, 0, 0, 0);
    pixaInitFull(pixa, NULL, box);
    boxDestroy(&box);
    for (i = 0; i < n; i++) {
        name = sarrayGetString(sa3, i, L_NOCOPY);
        if ((pix0 = pixRead(name)) == NULL)
            rp->success = FALSE;
        pix1 = pixScaleToSize(pix0, 144, 108);
        pixaReplacePix(pixa, n - 1 - i, pix1, NULL);
        pixDestroy(&pix0);
    }
    pixd = pixaDisplayTiledInRows(pixa, 32, 1000, 1.0, 0, 25, 2);
    pixDisplayWithTitle(pixd, 700, 100, NULL, rp->display);
    pixWrite("/tmp/regout/pix3.jpg", pixd, IFF_JFIF_JPEG);
    pixDestroy(&pixd);
    sarrayDestroy(&sa3);

    pixaDestroy(&pixa);
    return regTestCleanup(rp);
}
int main(int    argc,
         char **argv)
{
l_int32      w, h, ystart, yend, y, ymax, ymid, i, window, sum1, sum2, rankx;
l_uint32     uval;
l_float32    ave, rankval, maxvar, variance, norm, conf, angle, radangle;
NUMA        *na1;
PIX         *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7;
PIXA        *pixa;
static char  mainName[] = "findbinding";

    if (argc != 1)
        return ERROR_INT(" Syntax:  findbinding", mainName, 1);

    lept_mkdir("lept/binding");
    pixa = pixaCreate(0);

    pix1 = pixRead("binding-example.45.jpg");
    pix2 = pixConvertTo8(pix1, 0);

        /* Find the skew angle */
    pix3 = pixConvertTo1(pix2, 150);
    pixFindSkewSweepAndSearch(pix3, &angle, &conf, 2, 2, 7.0, 1.0, 0.01);
    fprintf(stderr, "angle = %f, conf = %f\n", angle, conf);

        /* Deskew, bringing in black pixels at the edges */
    if (L_ABS(angle) < 0.1 || conf < 1.5) {
        pix4 = pixClone(pix2);
    } else {
        radangle = 3.1416 * angle / 180.0;
        pix4 = pixRotate(pix2, radangle, L_ROTATE_AREA_MAP,
                         L_BRING_IN_BLACK, 0, 0);
    }

        /* Rotate 90 degrees to make binding horizontal */
    pix5 = pixRotateOrth(pix4, 1);

        /* Sort pixels in each row by their gray value.
         * Dark pixels on the left, light ones on the right. */
    pix6 = pixRankRowTransform(pix5);
    pixDisplay(pix5, 0, 0);
    pixDisplay(pix6, 550, 0);
    pixaAddPix(pixa, pix4, L_COPY);
    pixaAddPix(pixa, pix5, L_COPY);
    pixaAddPix(pixa, pix6, L_COPY);

        /* Make an a priori estimate of the y-interval within which the
         * binding will be found.  The search will be done in this interval. */
    pixGetDimensions(pix6, &w, &h, NULL);
    ystart = 0.25 * h;
    yend = 0.75 * h;

        /* Choose a very light rank value; close to white, which
         * corresponds to a column in pix6 near the right side. */
    rankval = 0.98;
    rankx = (l_int32)(w * rankval);

        /* Investigate variance in a small window (vertical, size = 5)
         * of the pixels in that column.  These are the %rankval
         * pixels in each raster of pix6.  Find the y-location of
         * maximum variance. */
    window = 5;
    norm = 1.0 / window;
    maxvar = 0.0;
    na1 = numaCreate(0);
    numaSetParameters(na1, ystart, 1);
    for (y = ystart; y <= yend; y++) {
        sum1 = sum2 = 0;
        for (i = 0; i < window; i++) {
            pixGetPixel(pix6, rankx, y + i, &uval);
            sum1 += uval;
            sum2 += uval * uval;
        }
        ave = norm * sum1;
        variance = norm * sum2 - ave * ave;
        numaAddNumber(na1, variance);
        ymid = y + window / 2;
        if (variance > maxvar) {
            maxvar = variance;
            ymax = ymid;
        }
    }

        /* Plot the windowed variance as a function of the y-value
         * of the window location */
    fprintf(stderr, "maxvar = %f, ymax = %d\n", maxvar, ymax);
    gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/binding/root", NULL);
    pix7 = pixRead("/tmp/lept/binding/root.png");
    pixDisplay(pix7, 0, 800);
    pixaAddPix(pixa, pix7, L_COPY);

        /* Superimpose the variance plot over the image.
         * The variance peak is at the binding. */
    pixRenderPlotFromNumaGen(&pix5, na1, L_VERTICAL_LINE, 3, w - 120, 100, 1,
                                                           0x0000ff00);
    pixDisplay(pix5, 1050, 0);
    pixaAddPix(pixa, pix5, L_COPY);

        /* Bundle the results up in a pdf */
    fprintf(stderr, "Writing pdf output file: /tmp/lept/binding/binding.pdf\n");
    pixaConvertToPdf(pixa, 45, 1.0, 0, 0, "Binding locator",
                     "/tmp/lept/binding/binding.pdf");

    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix3);
    pixDestroy(&pix4);
    pixDestroy(&pix5);
    pixDestroy(&pix6);
    pixDestroy(&pix7);
    pixaDestroy(&pixa);
    numaDestroy(&na1);
    return 0;
}
Exemple #14
0
main(int    argc,
     char **argv)
{
char        *selname;
l_int32      i, j, nsels, sx, sy;
l_float32    fact, time;
GPLOT       *gplot;
NUMA        *na1, *na2, *na3, *na4, *nac1, *nac2, *nac3, *nac4, *nax;
PIX         *pixs, *pixt;
PIXA        *pixa;
SEL         *sel;
SELA        *selalinear;
static char  mainName[] = "dwamorph2_reg";

    if (argc != 1)
	exit(ERROR_INT(" Syntax: dwamorph2_reg", mainName, 1));

    if ((pixs = pixRead("feyn-fract.tif")) == NULL)
	exit(ERROR_INT("pix not made", mainName, 1));
    pixt = pixCreateTemplate(pixs);

    selalinear = selaAddDwaLinear(NULL);
    nsels = selaGetCount(selalinear);

    fact = 1000. / (l_float32)NTIMES;  /* converts to time in msec */
    na1 = numaCreate(64);
    na2 = numaCreate(64);
    na3 = numaCreate(64);
    na4 = numaCreate(64);

        /*  ---------  dilation  ----------*/

    for (i = 0; i < nsels / 2; i++)
    {
        sel = selaGetSel(selalinear, i);
        selGetParameters(sel, &sy, &sx, NULL, NULL);
        selname = selGetName(sel);
	fprintf(stderr, " %d .", i);

        startTimer();
        for (j = 0; j < NTIMES; j++)
            pixDilate(pixt, pixs, sel);
        time = fact * stopTimer();
        numaAddNumber(na1, time);

        startTimer();
        for (j = 0; j < NTIMES; j++)
            pixDilateCompBrick(pixt, pixs, sx, sy);
        time = fact * stopTimer();
        numaAddNumber(na2, time);

        startTimer();
        for (j = 0; j < NTIMES; j++)
            pixMorphDwa_3(pixt, pixs, L_MORPH_DILATE, selname);
        time = fact * stopTimer();
        numaAddNumber(na3, time);

        startTimer();
        for (j = 0; j < NTIMES; j++)
            pixDilateCompBrickDwa(pixt, pixs, sx, sy);
        time = fact * stopTimer();
        numaAddNumber(na4, time);
    }

    nax = numaMakeSequence(2, 1, nsels / 2);
    nac1 = numaWindowedMean(na1, HALFWIDTH);
    nac2 = numaWindowedMean(na2, HALFWIDTH);
    nac3 = numaWindowedMean(na3, HALFWIDTH);
    nac4 = numaWindowedMean(na4, HALFWIDTH);
    gplot = gplotCreate("/tmp/junkdilate", GPLOT_PNG,
                        "Dilation time vs sel size", "size", "time (ms)");
    gplotAddPlot(gplot, nax, nac1, GPLOT_LINES, "linear rasterop");
    gplotAddPlot(gplot, nax, nac2, GPLOT_LINES, "composite rasterop");
    gplotAddPlot(gplot, nax, nac3, GPLOT_LINES, "linear dwa");
    gplotAddPlot(gplot, nax, nac4, GPLOT_LINES, "composite dwa");
    gplotMakeOutput(gplot);
    gplotDestroy(&gplot);
    numaDestroy(&nac1);
    numaDestroy(&nac2);
    numaDestroy(&nac3);
    numaDestroy(&nac4);

        /*  ---------  erosion  ----------*/

    numaEmpty(na1);
    numaEmpty(na2);
    numaEmpty(na3);
    numaEmpty(na4);
    for (i = 0; i < nsels / 2; i++)
    {
        sel = selaGetSel(selalinear, i);
        selGetParameters(sel, &sy, &sx, NULL, NULL);
        selname = selGetName(sel);
	fprintf(stderr, " %d .", i);

        startTimer();
        for (j = 0; j < NTIMES; j++)
            pixErode(pixt, pixs, sel);
        time = fact * stopTimer();
        numaAddNumber(na1, time);

        startTimer();
        for (j = 0; j < NTIMES; j++)
            pixErodeCompBrick(pixt, pixs, sx, sy);
        time = fact * stopTimer();
        numaAddNumber(na2, time);

        startTimer();
        for (j = 0; j < NTIMES; j++)
            pixMorphDwa_3(pixt, pixs, L_MORPH_ERODE, selname);
        time = fact * stopTimer();
        numaAddNumber(na3, time);

        startTimer();
        for (j = 0; j < NTIMES; j++)
            pixErodeCompBrickDwa(pixt, pixs, sx, sy);
        time = fact * stopTimer();
        numaAddNumber(na4, time);
    }

    nac1 = numaWindowedMean(na1, HALFWIDTH);
    nac2 = numaWindowedMean(na2, HALFWIDTH);
    nac3 = numaWindowedMean(na3, HALFWIDTH);
    nac4 = numaWindowedMean(na4, HALFWIDTH);
    gplot = gplotCreate("/tmp/junkerode", GPLOT_PNG,
                        "Erosion time vs sel size", "size", "time (ms)");
    gplotAddPlot(gplot, nax, nac1, GPLOT_LINES, "linear rasterop");
    gplotAddPlot(gplot, nax, nac2, GPLOT_LINES, "composite rasterop");
    gplotAddPlot(gplot, nax, nac3, GPLOT_LINES, "linear dwa");
    gplotAddPlot(gplot, nax, nac4, GPLOT_LINES, "composite dwa");
    gplotMakeOutput(gplot);
    gplotDestroy(&gplot);
    numaDestroy(&nac1);
    numaDestroy(&nac2);
    numaDestroy(&nac3);
    numaDestroy(&nac4);

        /*  ---------  opening  ----------*/

    numaEmpty(na1);
    numaEmpty(na2);
    numaEmpty(na3);
    numaEmpty(na4);
    for (i = 0; i < nsels / 2; i++)
    {
        sel = selaGetSel(selalinear, i);
        selGetParameters(sel, &sy, &sx, NULL, NULL);
        selname = selGetName(sel);
	fprintf(stderr, " %d .", i);

        startTimer();
        for (j = 0; j < NTIMES; j++)
            pixOpen(pixt, pixs, sel);
        time = fact * stopTimer();
        numaAddNumber(na1, time);

        startTimer();
        for (j = 0; j < NTIMES; j++)
            pixOpenCompBrick(pixt, pixs, sx, sy);
        time = fact * stopTimer();
        numaAddNumber(na2, time);

        startTimer();
        for (j = 0; j < NTIMES; j++)
            pixMorphDwa_3(pixt, pixs, L_MORPH_OPEN, selname);
        time = fact * stopTimer();
        numaAddNumber(na3, time);

        startTimer();
        for (j = 0; j < NTIMES; j++)
            pixOpenCompBrickDwa(pixt, pixs, sx, sy);
        time = fact * stopTimer();
        numaAddNumber(na4, time);
    }

    nac1 = numaWindowedMean(na1, HALFWIDTH);
    nac2 = numaWindowedMean(na2, HALFWIDTH);
    nac3 = numaWindowedMean(na3, HALFWIDTH);
    nac4 = numaWindowedMean(na4, HALFWIDTH);
    gplot = gplotCreate("/tmp/junkopen", GPLOT_PNG,
                        "Opening time vs sel size", "size", "time (ms)");
    gplotAddPlot(gplot, nax, nac1, GPLOT_LINES, "linear rasterop");
    gplotAddPlot(gplot, nax, nac2, GPLOT_LINES, "composite rasterop");
    gplotAddPlot(gplot, nax, nac3, GPLOT_LINES, "linear dwa");
    gplotAddPlot(gplot, nax, nac4, GPLOT_LINES, "composite dwa");
    gplotMakeOutput(gplot);
    gplotDestroy(&gplot);
    numaDestroy(&nac1);
    numaDestroy(&nac2);
    numaDestroy(&nac3);
    numaDestroy(&nac4);

        /*  ---------  closing  ----------*/

    numaEmpty(na1);
    numaEmpty(na2);
    numaEmpty(na3);
    numaEmpty(na4);
    for (i = 0; i < nsels / 2; i++)
    {
        sel = selaGetSel(selalinear, i);
        selGetParameters(sel, &sy, &sx, NULL, NULL);
        selname = selGetName(sel);
	fprintf(stderr, " %d .", i);

        startTimer();
        for (j = 0; j < NTIMES; j++)
            pixClose(pixt, pixs, sel);
        time = fact * stopTimer();
        numaAddNumber(na1, time);

        startTimer();
        for (j = 0; j < NTIMES; j++)
            pixCloseCompBrick(pixt, pixs, sx, sy);
        time = fact * stopTimer();
        numaAddNumber(na2, time);

        startTimer();
        for (j = 0; j < NTIMES; j++)
            pixMorphDwa_3(pixt, pixs, L_MORPH_CLOSE, selname);
        time = fact * stopTimer();
        numaAddNumber(na3, time);

        startTimer();
        for (j = 0; j < NTIMES; j++)
            pixCloseCompBrickDwa(pixt, pixs, sx, sy);
        time = fact * stopTimer();
        numaAddNumber(na4, time);
    }

    nac1 = numaWindowedMean(na1, HALFWIDTH);
    nac2 = numaWindowedMean(na2, HALFWIDTH);
    nac3 = numaWindowedMean(na3, HALFWIDTH);
    nac4 = numaWindowedMean(na4, HALFWIDTH);
    gplot = gplotCreate("/tmp/junkclose", GPLOT_PNG,
                        "Closing time vs sel size", "size", "time (ms)");
    gplotAddPlot(gplot, nax, nac1, GPLOT_LINES, "linear rasterop");
    gplotAddPlot(gplot, nax, nac2, GPLOT_LINES, "composite rasterop");
    gplotAddPlot(gplot, nax, nac3, GPLOT_LINES, "linear dwa");
    gplotAddPlot(gplot, nax, nac4, GPLOT_LINES, "composite dwa");
    gplotMakeOutput(gplot);
    gplotDestroy(&gplot);
    numaDestroy(&nac1);
    numaDestroy(&nac2);
    numaDestroy(&nac3);
    numaDestroy(&nac4);


    numaDestroy(&na1);
    numaDestroy(&na2);
    numaDestroy(&na3);
    numaDestroy(&na4);
    numaDestroy(&nax);
    selaDestroy(&selalinear);
    pixDestroy(&pixt);
    pixDestroy(&pixs);

        /* Display the results together */
    pixa = pixaCreate(0);
    pixs = pixRead("/tmp/junkdilate.png");
    pixaAddPix(pixa, pixs, L_INSERT);
    pixs = pixRead("/tmp/junkerode.png");
    pixaAddPix(pixa, pixs, L_INSERT);
    pixs = pixRead("/tmp/junkopen.png");
    pixaAddPix(pixa, pixs, L_INSERT);
    pixs = pixRead("/tmp/junkclose.png");
    pixaAddPix(pixa, pixs, L_INSERT);
    pixt = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 40, 3);
    pixWrite("/tmp/junktimings.png", pixt, IFF_PNG);
    pixDisplay(pixt, 100, 100);
    pixDestroy(&pixt);
    pixaDestroy(&pixa);
    return 0;
}
Exemple #15
0
/*!
 *  pixaDisplayTiled()
 *
 *      Input:  pixa
 *              maxwidth (of output image)
 *              background (0 for white, 1 for black)
 *              spacing
 *      Return: pix of tiled images, or null on error
 *
 *  Notes:
 *      (1) This saves a pixa to a single image file of width not to
 *          exceed maxwidth, with background color either white or black,
 *          and with each subimage spaced on a regular lattice.
 *      (2) The lattice size is determined from the largest width and height,
 *          separately, of all pix in the pixa.
 *      (3) All pix in the pixa must be of equal depth.
 *      (4) If any pix has a colormap, all pix are rendered in rgb.
 *      (5) Careful: because no components are omitted, this is
 *          dangerous if there are thousands of small components and
 *          one or more very large one, because the size of the
 *          resulting pix can be huge!
 */
PIX *
pixaDisplayTiled(PIXA    *pixa,
                 l_int32  maxwidth,
                 l_int32  background,
                 l_int32  spacing)
{
l_int32  w, h, wmax, hmax, wd, hd, d, hascmap;
l_int32  i, j, n, ni, ncols, nrows;
l_int32  ystart, xstart, wt, ht;
PIX     *pix, *pixt, *pixd;
PIXA    *pixat;

    PROCNAME("pixaDisplayTiled");

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

        /* If any pix have colormaps, generate rgb */
    if ((n = pixaGetCount(pixa)) == 0)
        return (PIX *)ERROR_PTR("no components", procName, NULL);
    pixaAnyColormaps(pixa, &hascmap);
    if (hascmap) {
        pixat = pixaCreate(n);
        for (i = 0; i < n; i++) {
            pixt = pixaGetPix(pixa, i, L_CLONE);
            pix = pixConvertTo32(pixt);
            pixaAddPix(pixat, pix, L_INSERT);
            pixDestroy(&pixt);
        }
    }
    else
        pixat = pixaCopy(pixa, L_CLONE);

        /* Find the largest width and height of the subimages */
    wmax = hmax = 0;
    for (i = 0; i < n; i++) {
        pix = pixaGetPix(pixat, i, L_CLONE);
        pixGetDimensions(pix, &w, &h, NULL);
        if (i == 0)
            d = pixGetDepth(pix);
        else if (d != pixGetDepth(pix)) {
            pixDestroy(&pix);
            pixaDestroy(&pixat);
            return (PIX *)ERROR_PTR("depths not equal", procName, NULL);
        }
        if (w > wmax)
            wmax = w;
        if (h > hmax)
            hmax = h;
        pixDestroy(&pix);
    }

        /* Get the number of rows and columns and the output image size */
    spacing = L_MAX(spacing, 0);
    ncols = (l_int32)((l_float32)(maxwidth - spacing) /
                      (l_float32)(wmax + spacing));
    nrows = (n + ncols - 1) / ncols;
    wd = wmax * ncols + spacing * (ncols + 1);
    hd = hmax * nrows + spacing * (nrows + 1);
    if ((pixd = pixCreate(wd, hd, d)) == NULL) {
        pixaDestroy(&pixat);
	return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    }

#if 0
    fprintf(stderr, " nrows = %d, ncols = %d, wmax = %d, hmax = %d\n",
            nrows, ncols, wmax, hmax);
    fprintf(stderr, " space = %d, wd = %d, hd = %d, n = %d\n",
            space, wd, hd, n);
#endif

        /* Reset the background color if necessary */
    if ((background == 1 && d == 1) || (background == 0 && d != 1))
        pixSetAll(pixd);

        /* Blit the images to the dest */
    for (i = 0, ni = 0; i < nrows; i++) {
        ystart = spacing + i * (hmax + spacing);
        for (j = 0; j < ncols && ni < n; j++, ni++) {
            xstart = spacing + j * (wmax + spacing);
            pix = pixaGetPix(pixat, ni, L_CLONE);
            wt = pixGetWidth(pix);
            ht = pixGetHeight(pix);
            pixRasterop(pixd, xstart, ystart, wt, ht, PIX_SRC, pix, 0, 0);
            pixDestroy(&pix);
        }
    }

    pixaDestroy(&pixat);
    return pixd;
}
Exemple #16
0
main(int    argc,
     char **argv)
{
char         *str;
l_int32       i, j, same, ok;
l_float32     sum, avediff, rmsdiff;
L_KERNEL     *kel1, *kel2, *kel3, *kel4, *kelx, *kely;
BOX          *box;
PIX          *pix, *pixs, *pixb, *pixg, *pixr, *pixd, *pixp, *pixt;
PIX          *pixt1, *pixt2, *pixt3;
PIXA         *pixa;
SARRAY       *sa;
L_REGPARAMS  *rp;

    if (regTestSetup(argc, argv, &rp))
        return 1;

    pixa = pixaCreate(0);

        /* Test creating from a string */
    kel1 = kernelCreateFromString(5, 5, 2, 2, kdatastr);
    pixd = kernelDisplayInPix(kel1, 41, 2);
    pixWrite("/tmp/pixkern.png", pixd, IFF_PNG);
    regTestCheckFile(rp, "/tmp/pixkern.png");  /* 0 */
    pixSaveTiled(pixd, pixa, 1, 1, 20, 8);
    pixDestroy(&pixd);
    kernelDestroy(&kel1);

        /* Test read/write for kernel.  Note that both get
         * compared to the same golden file, which is
         * overwritten with a copy of /tmp/kern2.kel */
    kel1 = kernelCreateFromString(5, 5, 2, 2, kdatastr);
    kernelWrite("/tmp/kern1.kel", kel1);
    regTestCheckFile(rp, "/tmp/kern1.kel");  /* 1 */
    kel2 = kernelRead("/tmp/kern1.kel");
    kernelWrite("/tmp/kern2.kel", kel2);
    regTestCheckFile(rp, "/tmp/kern2.kel");  /* 2 */
    regTestCompareFiles(rp, 1, 2);  /* 3 */
    kernelDestroy(&kel1);
    kernelDestroy(&kel2);

        /* Test creating from a file */
    sa = sarrayCreate(0);
    sarrayAddString(sa, (char *)"# small 3x3 kernel", L_COPY);
    sarrayAddString(sa, (char *)"3 5", L_COPY);
    sarrayAddString(sa, (char *)"1 2", L_COPY);
    sarrayAddString(sa, (char *)"20.5   50   80    50   20", L_COPY);
    sarrayAddString(sa, (char *)"82.    120  180   120  80", L_COPY);
    sarrayAddString(sa, (char *)"22.1   50   80    50   20", L_COPY);
    str = sarrayToString(sa, 1);
    l_binaryWrite("/tmp/kernfile.kel", "w", str, strlen(str));
    kel2 = kernelCreateFromFile("/tmp/kernfile.kel");
    pixd = kernelDisplayInPix(kel2, 41, 2);
    pixSaveTiled(pixd, pixa, 1, 1, 20, 0);
    pixWrite("/tmp/ker1.png", pixd, IFF_PNG);
    regTestCheckFile(rp, "/tmp/ker1.png");  /* 4 */
    pixDestroy(&pixd);
    sarrayDestroy(&sa);
    lept_free(str);
    kernelDestroy(&kel2);

        /* Test creating from a pix */
    pixt = pixCreate(5, 3, 8);
    pixSetPixel(pixt, 0, 0, 20);
    pixSetPixel(pixt, 1, 0, 50);
    pixSetPixel(pixt, 2, 0, 80);
    pixSetPixel(pixt, 3, 0, 50);
    pixSetPixel(pixt, 4, 0, 20);
    pixSetPixel(pixt, 0, 1, 80);
    pixSetPixel(pixt, 1, 1, 120);
    pixSetPixel(pixt, 2, 1, 180);
    pixSetPixel(pixt, 3, 1, 120);
    pixSetPixel(pixt, 4, 1, 80);
    pixSetPixel(pixt, 0, 0, 20);
    pixSetPixel(pixt, 1, 2, 50);
    pixSetPixel(pixt, 2, 2, 80);
    pixSetPixel(pixt, 3, 2, 50);
    pixSetPixel(pixt, 4, 2, 20);
    kel3 = kernelCreateFromPix(pixt, 1, 2);
    pixd = kernelDisplayInPix(kel3, 41, 2);
    pixSaveTiled(pixd, pixa, 1, 0, 20, 0);
    pixWrite("/tmp/ker2.png", pixd, IFF_PNG);
    regTestCheckFile(rp, "/tmp/ker2.png");  /* 5 */
    pixDestroy(&pixd);
    pixDestroy(&pixt);
    kernelDestroy(&kel3);

        /* Test convolution with kel1 */
    pixs = pixRead("test24.jpg");
    pixg = pixScaleRGBToGrayFast(pixs, 3, COLOR_GREEN);
    pixSaveTiled(pixg, pixa, 1, 1, 20, 0);
    kel1 = kernelCreateFromString(5, 5, 2, 2, kdatastr);
    pixd = pixConvolve(pixg, kel1, 8, 1);
    pixSaveTiled(pixd, pixa, 1, 0, 20, 0);
    pixWrite("/tmp/ker3.png", pixd, IFF_PNG);
    regTestCheckFile(rp, "/tmp/ker3.png");  /* 6 */
    pixDestroy(&pixs);
    pixDestroy(&pixg);
    pixDestroy(&pixd);
    kernelDestroy(&kel1);

        /* Test convolution with flat rectangular kel; also test
         * block convolution with tiling. */
    pixs = pixRead("test24.jpg");
    pixg = pixScaleRGBToGrayFast(pixs, 3, COLOR_GREEN);
    kel2 = makeFlatKernel(11, 11, 5, 5);
    pixd = pixConvolve(pixg, kel2, 8, 1);
    pixSaveTiled(pixd, pixa, 1, 1, 20, 0);
    pixWrite("/tmp/ker4.png", pixd, IFF_PNG);
    regTestCheckFile(rp, "/tmp/ker4.png");  /* 7 */
    pixt = pixBlockconv(pixg, 5, 5);
    pixSaveTiled(pixt, pixa, 1, 0, 20, 0);
    pixWrite("/tmp/ker5.png", pixt, IFF_PNG);
    regTestCheckFile(rp, "/tmp/ker5.png");  /* 8 */
    if (rp->display)
        pixCompareGray(pixd, pixt, L_COMPARE_ABS_DIFF, GPLOT_X11, NULL,
                       NULL, NULL, NULL);
    pixt2 = pixBlockconvTiled(pixg, 5, 5, 3, 6);
    pixSaveTiled(pixt2, pixa, 1, 0, 20, 0);
    pixWrite("/tmp/ker5a.png", pixt2, IFF_PNG);
    regTestCheckFile(rp, "/tmp/ker5a.png");  /* 9 */
    pixDestroy(&pixt2);

    ok = TRUE;
    for (i = 1; i <= 7; i++) {
        for (j = 1; j <= 7; j++) {
            if (i == 1 && j == 1) continue;
            pixt2 = pixBlockconvTiled(pixg, 5, 5, j, i);
            pixEqual(pixt2, pixd, &same);
            if (!same) {
                fprintf(stderr," Error for nx = %d, ny = %d\n", j, i);
                ok = FALSE;
            }
            pixDestroy(&pixt2);
        }
    }
    if (ok)
        fprintf(stderr, "OK: Tiled results identical to pixConvolve()\n");
    else
        fprintf(stderr, "ERROR: Tiled results not identical to pixConvolve()\n");
          
    pixDestroy(&pixs);
    pixDestroy(&pixg);
    pixDestroy(&pixd);
    pixDestroy(&pixt);
    kernelDestroy(&kel2);

        /* Do another flat rectangular test; this time with white at edge.
         * About 1% of the pixels near the image edge differ by 1 between
         * the pixConvolve() and pixBlockconv().  For what it's worth,
         * pixConvolve() gives the more accurate result; namely, 255 for
         * pixels at the edge. */
    pix = pixRead("pageseg1.tif");
    box = boxCreate(100, 100, 2260, 3160);
    pixb = pixClipRectangle(pix, box, NULL);
    pixs = pixScaleToGray4(pixb);

    kel3 = makeFlatKernel(7, 7, 3, 3);
    startTimer();
    pixt = pixConvolve(pixs, kel3, 8, 1);
    fprintf(stderr, "Generic convolution time: %5.3f sec\n", stopTimer());
    pixSaveTiled(pixt, pixa, 1, 1, 20, 0);
    pixWrite("/tmp/conv1.png", pixt, IFF_PNG);
    regTestCheckFile(rp, "/tmp/conv1.png");  /* 10 */

    startTimer();
    pixt2 = pixBlockconv(pixs, 3, 3);
    fprintf(stderr, "Flat block convolution time: %5.3f sec\n", stopTimer());
    pixSaveTiled(pixt2, pixa, 1, 0, 20, 0);
    pixWrite("/tmp/conv2.png", pixt2, IFF_PNG);  /* ditto */
    regTestCheckFile(rp, "/tmp/conv2.png");  /* 11 */

    pixCompareGray(pixt, pixt2, L_COMPARE_ABS_DIFF, GPLOT_PNG, NULL,
                   &avediff, &rmsdiff, NULL);
#ifndef  _WIN32
    sleep(1);  /* give gnuplot time to write out the file */
#else
    Sleep(1000);
#endif  /* _WIN32 */
    pixp = pixRead("/tmp/grayroot.png");
    pixSaveTiled(pixp, pixa, 1, 0, 20, 0);
    pixWrite("/tmp/conv3.png", pixp, IFF_PNG);
    regTestCheckFile(rp, "/tmp/conv3.png");  /* 12 */
    fprintf(stderr, "Ave diff = %6.4f, RMS diff = %6.4f\n", avediff, rmsdiff);
    if (avediff <= 0.01)
        fprintf(stderr, "OK: avediff = %6.4f <= 0.01\n", avediff);
    else
        fprintf(stderr, "Bad?: avediff = %6.4f > 0.01\n", avediff);

    pixDestroy(&pixt);
    pixDestroy(&pixt2);
    pixDestroy(&pixs);
    pixDestroy(&pixp);
    pixDestroy(&pix);
    pixDestroy(&pixb);
    boxDestroy(&box);
    kernelDestroy(&kel3);

        /* Do yet another set of flat rectangular tests, this time
         * on an RGB image */
    pixs = pixRead("test24.jpg");
    kel4 = makeFlatKernel(7, 7, 3, 3);
    startTimer();
    pixt1 = pixConvolveRGB(pixs, kel4);
    fprintf(stderr, "Time 7x7 non-separable: %7.3f sec\n", stopTimer());
    pixWrite("/tmp/conv4.jpg", pixt1, IFF_JFIF_JPEG);
    regTestCheckFile(rp, "/tmp/conv4.jpg");  /* 13 */

    kelx = makeFlatKernel(1, 7, 0, 3);
    kely = makeFlatKernel(7, 1, 3, 0);
    startTimer();
    pixt2 = pixConvolveRGBSep(pixs, kelx, kely);
    fprintf(stderr, "Time 7x1,1x7 separable: %7.3f sec\n", stopTimer());
    pixWrite("/tmp/conv5.jpg", pixt2, IFF_JFIF_JPEG);
    regTestCheckFile(rp, "/tmp/conv5.jpg");  /* 14 */

    startTimer();
    pixt3 = pixBlockconv(pixs, 3, 3);
    fprintf(stderr, "Time 7x7 blockconv: %7.3f sec\n", stopTimer());
    pixWrite("/tmp/conv6.jpg", pixt3, IFF_JFIF_JPEG);
    regTestCheckFile(rp, "/tmp/conv6.jpg");  /* 15 */
    regTestComparePix(rp, pixt1, pixt2);  /* 16 */
    regTestCompareSimilarPix(rp, pixt2, pixt3, 15, 0.0005, 0);  /* 17 */

    pixDestroy(&pixs);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixDestroy(&pixt3);
    kernelDestroy(&kel4);
    kernelDestroy(&kelx);
    kernelDestroy(&kely);

        /* Test generation and convolution with gaussian kernel */
    pixs = pixRead("test8.jpg");
    pixSaveTiled(pixs, pixa, 1, 1, 20, 0);
    kel1 = makeGaussianKernel(5, 5, 3.0, 5.0);
    kernelGetSum(kel1, &sum);
    fprintf(stderr, "Sum for gaussian kernel = %f\n", sum);
    kernelWrite("/tmp/gauss.kel", kel1);
    pixt = pixConvolve(pixs, kel1, 8, 1);
    pixt2 = pixConvolve(pixs, kel1, 16, 0);
    pixSaveTiled(pixt, pixa, 1, 0, 20, 0);
    pixSaveTiled(pixt2, pixa, 1, 0, 20, 0);
    pixWrite("/tmp/ker6.png", pixt, IFF_PNG);
    regTestCheckFile(rp, "/tmp/ker6.png");  /* 18 */
    pixDestroy(&pixt);
    pixDestroy(&pixt2);

    pixt = kernelDisplayInPix(kel1, 25, 2);
    pixSaveTiled(pixt, pixa, 1, 0, 20, 0);
    pixDestroy(&pixt);
    kernelDestroy(&kel1);
    pixDestroy(&pixs);

        /* Test generation and convolution with separable gaussian kernel */
    pixs = pixRead("test8.jpg");
    pixSaveTiled(pixs, pixa, 1, 1, 20, 0);
    makeGaussianKernelSep(5, 5, 3.0, 5.0, &kelx, &kely);
    kernelGetSum(kelx, &sum);
    fprintf(stderr, "Sum for x gaussian kernel = %f\n", sum);
    kernelGetSum(kely, &sum);
    fprintf(stderr, "Sum for y gaussian kernel = %f\n", sum);
    kernelWrite("/tmp/gauss.kelx", kelx);
    kernelWrite("/tmp/gauss.kely", kely);

    pixt = pixConvolveSep(pixs, kelx, kely, 8, 1);
    pixt2 = pixConvolveSep(pixs, kelx, kely, 16, 0);
    pixSaveTiled(pixt, pixa, 1, 0, 20, 0);
    pixSaveTiled(pixt2, pixa, 1, 0, 20, 0);
    pixWrite("/tmp/ker7.png", pixt, IFF_PNG);
    regTestCheckFile(rp, "/tmp/ker7.png");  /* 19 */
    pixDestroy(&pixt);
    pixDestroy(&pixt2);

    pixt = kernelDisplayInPix(kelx, 25, 2);
    pixSaveTiled(pixt, pixa, 1, 0, 20, 0);
    pixDestroy(&pixt);
    pixt = kernelDisplayInPix(kely, 25, 2);
    pixSaveTiled(pixt, pixa, 1, 0, 20, 0);
    pixDestroy(&pixt);
    kernelDestroy(&kelx);
    kernelDestroy(&kely);
    pixDestroy(&pixs);

        /* Test generation and convolution with diff of gaussians kernel */
/*    pixt = pixRead("marge.jpg");
    pixs = pixConvertRGBToLuminance(pixt);
    pixDestroy(&pixt); */
    pixs = pixRead("test8.jpg");
    pixSaveTiled(pixs, pixa, 1, 1, 20, 0);
    kel1 = makeDoGKernel(7, 7, 1.5, 2.7);
    kernelGetSum(kel1, &sum);
    fprintf(stderr, "Sum for DoG kernel = %f\n", sum);
    kernelWrite("/tmp/dog.kel", kel1);
    pixt = pixConvolve(pixs, kel1, 8, 0);
/*    pixInvert(pixt, pixt); */
    pixSaveTiled(pixt, pixa, 1, 0, 20, 0);
    pixWrite("/tmp/ker8.png", pixt, IFF_PNG);
    regTestCheckFile(rp, "/tmp/ker8.png");  /* 20 */
    pixDestroy(&pixt);

    pixt = kernelDisplayInPix(kel1, 20, 2);
    pixSaveTiled(pixt, pixa, 1, 0, 20, 0);
    pixDestroy(&pixt);
    kernelDestroy(&kel1);
    pixDestroy(&pixs);

    pixd = pixaDisplay(pixa, 0, 0);
    pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display);
    pixWrite("/tmp/kernel.jpg", pixd, IFF_JFIF_JPEG);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);

    return regTestCleanup(rp);
}
Exemple #17
0
/*!
 *  pixaDisplayTiledInRows()
 *
 *      Input:  pixa
 *              outdepth (output depth: 1, 8 or 32 bpp)
 *              maxwidth (of output image)
 *              scalefactor (applied to every pix; use 1.0 for no scaling)
 *              background (0 for white, 1 for black; this is the color
 *                 of the spacing between the images)
 *              spacing  (between images, and on outside)
 *              border (width of black border added to each image;
 *                      use 0 for no border)
 *      Return: pixd (of tiled images), or null on error
 *
 *  Notes:
 *      (1) This saves a pixa to a single image file of width not to
 *          exceed maxwidth, with background color either white or black,
 *          and with each row tiled such that the top of each pix is
 *          aligned and separated by 'spacing' from the next one.
 *          A black border can be added to each pix.
 *      (2) All pix are converted to outdepth; existing colormaps are removed.
 *      (3) This does a reasonably spacewise-efficient job of laying
 *          out the individual pix images into a tiled composite.
 */
PIX *
pixaDisplayTiledInRows(PIXA      *pixa,
                       l_int32    outdepth,
                       l_int32    maxwidth,
                       l_float32  scalefactor,
                       l_int32    background,
                       l_int32    spacing,
                       l_int32    border)
{
l_int32  h;  /* cumulative height over all the rows */
l_int32  w;  /* cumulative height in the current row */
l_int32  bordval, wtry, wt, ht;
l_int32  irow;  /* index of current pix in current row */
l_int32  wmaxrow;  /* width of the largest row */
l_int32  maxh;  /* max height in row */
l_int32  i, j, index, n, x, y, nrows, ninrow;
NUMA    *nainrow;  /* number of pix in the row */
NUMA    *namaxh;  /* height of max pix in the row */
PIX     *pix, *pixn, *pixt, *pixd;
PIXA    *pixan;

    PROCNAME("pixaDisplayTiledInRows");

    if (!pixa)
        return (PIX *)ERROR_PTR("pixa not defined", procName, NULL);
    if (outdepth != 1 && outdepth != 8 && outdepth != 32)
        return (PIX *)ERROR_PTR("outdepth not in {1, 8, 32}", procName, NULL);
    if (border < 0)
        border = 0;
    if (scalefactor <= 0.0) scalefactor = 1.0;
    
    if ((n = pixaGetCount(pixa)) == 0)
        return (PIX *)ERROR_PTR("no components", procName, NULL);

        /* Normalize depths, scale, remove colormaps; optionally add border */
    pixan = pixaCreate(n);
    bordval = (outdepth == 1) ? 1 : 0;
    for (i = 0; i < n; i++) {
        if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL)
            continue;

        if (outdepth == 1)
            pixn = pixConvertTo1(pix, 128);
        else if (outdepth == 8)
            pixn = pixConvertTo8(pix, FALSE);
        else  /* outdepth == 32 */
            pixn = pixConvertTo32(pix);
        pixDestroy(&pix);

        if (scalefactor != 1.0)
            pixt = pixScale(pixn, scalefactor, scalefactor);
        else
            pixt = pixClone(pixn);
        if (border)
            pixd = pixAddBorder(pixt, border, bordval);
        else
            pixd = pixClone(pixt);
        pixDestroy(&pixn);
        pixDestroy(&pixt);

        pixaAddPix(pixan, pixd, L_INSERT);
    }
    if (pixaGetCount(pixan) != n) {
        n = pixaGetCount(pixan);
        L_WARNING_INT("only got %d components", procName, n);
        if (n == 0) {
            pixaDestroy(&pixan);
            return (PIX *)ERROR_PTR("no components", procName, NULL);
        }
    }

        /* Compute parameters for layout */
    nainrow = numaCreate(0);
    namaxh = numaCreate(0);
    wmaxrow = 0;
    w = h = spacing;
    maxh = 0;  /* max height in row */
    for (i = 0, irow = 0; i < n; i++, irow++) {
        pixaGetPixDimensions(pixan, i, &wt, &ht, NULL);
        wtry = w + wt + spacing;
        if (wtry > maxwidth) {  /* end the current row and start next one */
            numaAddNumber(nainrow, irow); 
            numaAddNumber(namaxh, maxh); 
            wmaxrow = L_MAX(wmaxrow, w);
            h += maxh + spacing;
            irow = 0;
            w = wt + 2 * spacing;
            maxh = ht;
        } else {
            w = wtry;
            maxh = L_MAX(maxh, ht);
        }
    }

        /* Enter the parameters for the last row */
    numaAddNumber(nainrow, irow); 
    numaAddNumber(namaxh, maxh); 
    wmaxrow = L_MAX(wmaxrow, w);
    h += maxh + spacing;
            
    if ((pixd = pixCreate(wmaxrow, h, outdepth)) == NULL) {
        numaDestroy(&nainrow);
        numaDestroy(&namaxh);
        pixaDestroy(&pixan);
	return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    }

        /* Reset the background color if necessary */
    if ((background == 1 && outdepth == 1) ||
        (background == 0 && outdepth != 1))
        pixSetAll(pixd);

        /* Blit the images to the dest */
    nrows = numaGetCount(nainrow);
    y = spacing;
    for (i = 0, index = 0; i < nrows; i++) {  /* over rows */
        numaGetIValue(nainrow, i, &ninrow);
        numaGetIValue(namaxh, i, &maxh);
        x = spacing;
        for (j = 0; j < ninrow; j++, index++) {   /* over pix in row */
            pix = pixaGetPix(pixan, index, L_CLONE);
            pixGetDimensions(pix, &wt, &ht, NULL);
            pixRasterop(pixd, x, y, wt, ht, PIX_SRC, pix, 0, 0);
            pixDestroy(&pix);
            x += wt + spacing;
        }
        y += maxh + spacing;
    }

    numaDestroy(&nainrow);
    numaDestroy(&namaxh);
    pixaDestroy(&pixan);
    return pixd;
}
Exemple #18
0
main(int    argc,
char **argv)
{
l_float32     sum, sumx, sumy, diff;
FPIX         *fpixs, *fpixs2, *fpixs3, *fpixt1, *fpixt2, *fpixg, *fpixd;
L_KERNEL     *kel, *kelx, *kely;
PIX          *pixs, *pixs2, *pixs3, *pixt, *pixd, *pixg;
PIX          *pixt1, *pixt2, *pixt3, *pixt4, *pixt5, *pixt6;
PIXA         *pixa;
L_REGPARAMS  *rp;

    if (regTestSetup(argc, argv, &rp))
        return 1;

    pixa = pixaCreate(0);

        /* Gaussian kernel */
    kel = makeGaussianKernel(5, 5, 3.0, 4.0);
    kernelGetSum(kel, &sum);
    if (rp->display) fprintf(stderr, "Sum for 2d gaussian kernel = %f\n", sum);
    pixt = kernelDisplayInPix(kel, 41, 2);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 0 */
    pixSaveTiled(pixt, pixa, 1, 1, 20, 8);
    pixDestroy(&pixt);

        /* Separable gaussian kernel */
    makeGaussianKernelSep(5, 5, 3.0, 4.0, &kelx, &kely);
    kernelGetSum(kelx, &sumx);
    if (rp->display) fprintf(stderr, "Sum for x gaussian kernel = %f\n", sumx);
    kernelGetSum(kely, &sumy);
    if (rp->display) fprintf(stderr, "Sum for y gaussian kernel = %f\n", sumy);
    if (rp->display) fprintf(stderr, "Sum for x * y gaussian kernel = %f\n",
                         sumx * sumy);
    pixt = kernelDisplayInPix(kelx, 41, 2);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 1 */
    pixSaveTiled(pixt, pixa, 1, 0, 20, 8);
    pixDestroy(&pixt);
    pixt = kernelDisplayInPix(kely, 41, 2);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 2 */
    pixSaveTiled(pixt, pixa, 1, 0, 20, 8);
    pixDestroy(&pixt);

        /* Use pixRasterop() to generate source image */
    pixs = pixRead("test8.jpg");
    pixs2 = pixRead("karen8.jpg");
    pixRasterop(pixs, 150, 125, 150, 100, PIX_SRC, pixs2, 75, 100);
    regTestWritePixAndCheck(rp, pixs, IFF_JFIF_JPEG);  /* 3 */

        /* Convolution directly with pix */
    pixt1 = pixConvolve(pixs, kel, 8, 1);
    regTestWritePixAndCheck(rp, pixt1, IFF_JFIF_JPEG);  /* 4 */
    pixSaveTiled(pixt1, pixa, 1, 1, 20, 8);
    pixt2 = pixConvolveSep(pixs, kelx, kely, 8, 1);
    regTestWritePixAndCheck(rp, pixt2, IFF_JFIF_JPEG);  /* 5 */
    pixSaveTiled(pixt2, pixa, 1, 0, 20, 8);

        /* Convolution indirectly with fpix, using fpixRasterop()
         * to generate the source image. */
    fpixs = pixConvertToFPix(pixs, 3);
    fpixs2 = pixConvertToFPix(pixs2, 3);
    fpixRasterop(fpixs, 150, 125, 150, 100, fpixs2, 75, 100);
    fpixt1 = fpixConvolve(fpixs, kel, 1);
    pixt3 = fpixConvertToPix(fpixt1, 8, L_CLIP_TO_ZERO, 1);
    regTestWritePixAndCheck(rp, pixt3, IFF_JFIF_JPEG);  /* 6 */
    pixSaveTiled(pixt3, pixa, 1, 1, 20, 8);
    fpixt2 = fpixConvolveSep(fpixs, kelx, kely, 1);
    pixt4 = fpixConvertToPix(fpixt2, 8, L_CLIP_TO_ZERO, 1);
    regTestWritePixAndCheck(rp, pixt4, IFF_JFIF_JPEG);  /* 7 */
    pixSaveTiled(pixt4, pixa, 1, 0, 20, 8);
    pixDestroy(&pixs2);
    fpixDestroy(&fpixs2);
    fpixDestroy(&fpixt1);
    fpixDestroy(&fpixt2);

        /* Comparison of results */
    pixCompareGray(pixt1, pixt2, L_COMPARE_ABS_DIFF, 0, NULL,
                   &diff, NULL, NULL);
    if (rp->display)
        fprintf(stderr, "Ave diff of pixConvolve and pixConvolveSep: %f\n",
                diff);
    pixCompareGray(pixt3, pixt4, L_COMPARE_ABS_DIFF, 0, NULL,
                   &diff, NULL, NULL);
    if (rp->display)
        fprintf(stderr, "Ave diff of fpixConvolve and fpixConvolveSep: %f\n",
                diff);
    pixCompareGray(pixt1, pixt3, L_COMPARE_ABS_DIFF, 0, NULL,
                   &diff, NULL, NULL);
    if (rp->display)
        fprintf(stderr, "Ave diff of pixConvolve and fpixConvolve: %f\n", diff);
    pixCompareGray(pixt2, pixt4, L_COMPARE_ABS_DIFF, GPLOT_PNG, NULL,
                   &diff, NULL, NULL);
    if (rp->display)
        fprintf(stderr, "Ave diff of pixConvolveSep and fpixConvolveSep: %f\n",
                diff);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixDestroy(&pixt3);
    pixDestroy(&pixt4);

        /* Test arithmetic operations; add in a fraction rotated by 180 */
    pixs3 = pixRotate180(NULL, pixs);
    regTestWritePixAndCheck(rp, pixs3, IFF_JFIF_JPEG);  /* 8 */
    pixSaveTiled(pixs3, pixa, 1, 1, 20, 8);
    fpixs3 = pixConvertToFPix(pixs3, 3);
    fpixd = fpixLinearCombination(NULL, fpixs, fpixs3, 20.0, 5.0);
    fpixAddMultConstant(fpixd, 0.0, 23.174);   /* multiply up in magnitude */
    pixd = fpixDisplayMaxDynamicRange(fpixd);  /* bring back to 8 bpp */
    regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG);  /* 9 */
    pixSaveTiled(pixd, pixa, 1, 0, 20, 8);
    pixDestroy(&pixs3);
    fpixDestroy(&fpixs3);
    fpixDestroy(&fpixd);
    pixDestroy(&pixd);
    pixDestroy(&pixs);
    fpixDestroy(&fpixs);

        /* Save the comparison graph; gnuplot should have made it by now! */
#ifndef _WIN32
    sleep(2);
#else
    Sleep(2000);
#endif  /* _WIN32 */
    pixt5 = pixRead("/tmp/grayroot.png");
    regTestWritePixAndCheck(rp, pixt5, IFF_PNG);  /* 10 */
    pixSaveTiled(pixt5, pixa, 1, 1, 20, 8);
    pixDestroy(&pixt5);

        /* Display results */
    pixd = pixaDisplay(pixa, 0, 0);
    regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG);  /* 11 */
    pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);

        /* Test some more convolutions, with sampled output. First on pix */
    pixa = pixaCreate(0);
    pixs = pixRead("1555-7.jpg");
    pixg = pixConvertTo8(pixs, 0);
    l_setConvolveSampling(5, 5);
    pixt1 = pixConvolve(pixg, kel, 8, 1);
    regTestWritePixAndCheck(rp, pixt1, IFF_JFIF_JPEG);  /* 12 */
    pixSaveTiled(pixt1, pixa, 1, 1, 20, 32);
    pixt2 = pixConvolveSep(pixg, kelx, kely, 8, 1);
    regTestWritePixAndCheck(rp, pixt2, IFF_JFIF_JPEG);  /* 13 */
    pixSaveTiled(pixt2, pixa, 1, 0, 20, 32);
    pixt3 = pixConvolveRGB(pixs, kel);
    regTestWritePixAndCheck(rp, pixt3, IFF_JFIF_JPEG);  /* 14 */
    pixSaveTiled(pixt3, pixa, 1, 0, 20, 32);
    pixt4 = pixConvolveRGBSep(pixs, kelx, kely);
    regTestWritePixAndCheck(rp, pixt4, IFF_JFIF_JPEG);  /* 15 */
    pixSaveTiled(pixt4, pixa, 1, 0, 20, 32);

        /* Then on fpix */
    fpixg = pixConvertToFPix(pixg, 1);
    fpixt1 = fpixConvolve(fpixg, kel, 1);
    pixt5 = fpixConvertToPix(fpixt1, 8, L_CLIP_TO_ZERO, 0);
    regTestWritePixAndCheck(rp, pixt5, IFF_JFIF_JPEG);  /* 16 */
    pixSaveTiled(pixt5, pixa, 1, 1, 20, 32);
    fpixt2 = fpixConvolveSep(fpixg, kelx, kely, 1);
    pixt6 = fpixConvertToPix(fpixt2, 8, L_CLIP_TO_ZERO, 0);
    regTestWritePixAndCheck(rp, pixt6, IFF_JFIF_JPEG);  /* 17 */
    pixSaveTiled(pixt2, pixa, 1, 0, 20, 32);
    regTestCompareSimilarPix(rp, pixt1, pixt5, 2, 0.00, 0);  /* 18 */
    regTestCompareSimilarPix(rp, pixt2, pixt6, 2, 0.00, 0);  /* 19 */
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixDestroy(&pixt3);
    pixDestroy(&pixt4);
    pixDestroy(&pixt5);
    pixDestroy(&pixt6);
    fpixDestroy(&fpixg);
    fpixDestroy(&fpixt1);
    fpixDestroy(&fpixt2);

    pixd = pixaDisplay(pixa, 0, 0);
    regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG);  /* 20 */
    pixDisplayWithTitle(pixd, 600, 100, NULL, rp->display);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);

    regTestCleanup(rp);
    pixDestroy(&pixs);
    pixDestroy(&pixg);
    kernelDestroy(&kel);
    kernelDestroy(&kelx);
    kernelDestroy(&kely);
    return 0;
}
Exemple #19
0
/*!
 *  pixaaDisplay()
 *
 *      Input:  pixaa
 *              w, h (if set to 0, determines the size from the
 *                    b.b. of the components in pixaa)
 *      Return: pix, or null on error
 *
 *  Notes:
 *      (1) Each pix of the pixaa is displayed at the location given by
 *          its box, translated by the box of the containing pixa
 *          if it exists.
 */
PIX *
pixaaDisplay(PIXAA   *pixaa,
             l_int32  w,
             l_int32  h)
{
l_int32  i, j, n, nbox, na, d, wmax, hmax, x, y, xb, yb, wb, hb;
BOXA    *boxa1;  /* top-level boxa */
BOXA    *boxa;
PIX     *pixt, *pixd;
PIXA    *pixa;

    PROCNAME("pixaaDisplay");

    if (!pixaa)
        return (PIX *)ERROR_PTR("pixaa not defined", procName, NULL);
    
    n = pixaaGetCount(pixaa);
    if (n == 0)
        return (PIX *)ERROR_PTR("no components", procName, NULL);

        /* If w and h not input, determine the minimum size required
         * to contain the origin and all c.c. */
    boxa1 = pixaaGetBoxa(pixaa, L_CLONE);
    nbox = boxaGetCount(boxa1);
    if (w == 0 || h == 0) {
        if (nbox == n)
            boxaGetExtent(boxa1, &w, &h, NULL);
        else {  /* have to use the lower-level boxa for each pixa */
            wmax = hmax = 0;
            for (i = 0; i < n; i++) {
                pixa = pixaaGetPixa(pixaa, i, L_CLONE);
                boxa = pixaGetBoxa(pixa, L_CLONE);
                boxaGetExtent(boxa, &w, &h, NULL);
                wmax = L_MAX(wmax, w);
                hmax = L_MAX(hmax, h);
                pixaDestroy(&pixa);
                boxaDestroy(&boxa);
            }
            w = wmax;
            h = hmax;
        }
    }

        /* Get depth from first pix */
    pixa = pixaaGetPixa(pixaa, 0, L_CLONE);
    pixt = pixaGetPix(pixa, 0, L_CLONE);
    d = pixGetDepth(pixt);
    pixaDestroy(&pixa);
    pixDestroy(&pixt);

    if ((pixd = pixCreate(w, h, d)) == NULL)
        return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    
    x = y = 0;
    for (i = 0; i < n; i++) {
        pixa = pixaaGetPixa(pixaa, i, L_CLONE);
        if (nbox == n)
            boxaGetBoxGeometry(boxa1, i, &x, &y, NULL, NULL);
        na = pixaGetCount(pixa);
        for (j = 0; j < na; j++) {
            pixaGetBoxGeometry(pixa, j, &xb, &yb, &wb, &hb);
            pixt = pixaGetPix(pixa, j, L_CLONE);
            pixRasterop(pixd, x + xb, y + yb, wb, hb, PIX_PAINT, pixt, 0, 0);
            pixDestroy(&pixt);
        }
        pixaDestroy(&pixa);
    }
    boxaDestroy(&boxa1);

    return pixd;
}
Exemple #20
0
int main(int    argc,
         char **argv)
{
l_int32       index;
l_uint32      val32;
BOX          *box, *box1, *box2, *box3, *box4, *box5;
BOXA         *boxa;
L_KERNEL     *kel;
PIX          *pixs, *pixg, *pixb, *pixd, *pixt, *pix1, *pix2, *pix3, *pix4;
PIXA         *pixa;
PIXCMAP      *cmap;
L_REGPARAMS  *rp;

    if (regTestSetup(argc, argv, &rp))
        return 1;

    pixa = pixaCreate(0);

        /* Color non-white pixels on RGB */
    pixs = pixRead("lucasta-frag.jpg");
    pixt = pixConvert8To32(pixs);
    box = boxCreate(120, 30, 200, 200);
    pixColorGray(pixt, box, L_PAINT_DARK, 220, 0, 0, 255);
    regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG);  /* 0 */
    pixaAddPix(pixa, pixt, L_COPY);
    pixColorGray(pixt, NULL, L_PAINT_DARK, 220, 255, 100, 100);
    regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG);  /* 1 */
    pixaAddPix(pixa, pixt, L_INSERT);
    boxDestroy(&box);

        /* Color non-white pixels on colormap */
    pixt = pixThresholdTo4bpp(pixs, 6, 1);
    box = boxCreate(120, 30, 200, 200);
    pixColorGray(pixt, box, L_PAINT_DARK, 220, 0, 0, 255);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 2 */
    pixaAddPix(pixa, pixt, L_COPY);
    pixColorGray(pixt, NULL, L_PAINT_DARK, 220, 255, 100, 100);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 3 */
    pixaAddPix(pixa, pixt, L_INSERT);
    boxDestroy(&box);

        /* Color non-black pixels on RGB */
    pixt = pixConvert8To32(pixs);
    box = boxCreate(120, 30, 200, 200);
    pixColorGray(pixt, box, L_PAINT_LIGHT, 20, 0, 0, 255);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 4 */
    pixaAddPix(pixa, pixt, L_COPY);
    pixColorGray(pixt, NULL, L_PAINT_LIGHT, 80, 255, 100, 100);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 5 */
    pixaAddPix(pixa, pixt, L_INSERT);
    boxDestroy(&box);

        /* Color non-black pixels on colormap */
    pixt = pixThresholdTo4bpp(pixs, 6, 1);
    box = boxCreate(120, 30, 200, 200);
    pixColorGray(pixt, box, L_PAINT_LIGHT, 20, 0, 0, 255);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 6 */
    pixaAddPix(pixa, pixt, L_COPY);
    pixColorGray(pixt, NULL, L_PAINT_LIGHT, 20, 255, 100, 100);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 7 */
    pixaAddPix(pixa, pixt, L_INSERT);
    boxDestroy(&box);

        /* Add highlight color to RGB */
    pixt = pixConvert8To32(pixs);
    box = boxCreate(507, 5, 385, 45);
    pixg = pixClipRectangle(pixs, box, NULL);
    pixb = pixThresholdToBinary(pixg, 180);
    pixInvert(pixb, pixb);
    pixDisplayWrite(pixb, 1);
    composeRGBPixel(50, 0, 250, &val32);
    pixPaintThroughMask(pixt, pixb, box->x, box->y, val32);
    boxDestroy(&box);
    pixDestroy(&pixg);
    pixDestroy(&pixb);
    box = boxCreate(236, 107, 262, 40);
    pixg = pixClipRectangle(pixs, box, NULL);
    pixb = pixThresholdToBinary(pixg, 180);
    pixInvert(pixb, pixb);
    composeRGBPixel(250, 0, 50, &val32);
    pixPaintThroughMask(pixt, pixb, box->x, box->y, val32);
    boxDestroy(&box);
    pixDestroy(&pixg);
    pixDestroy(&pixb);
    box = boxCreate(222, 208, 247, 43);
    pixg = pixClipRectangle(pixs, box, NULL);
    pixb = pixThresholdToBinary(pixg, 180);
    pixInvert(pixb, pixb);
    composeRGBPixel(60, 250, 60, &val32);
    pixPaintThroughMask(pixt, pixb, box->x, box->y, val32);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 8 */
    pixaAddPix(pixa, pixt, L_INSERT);
    boxDestroy(&box);
    pixDestroy(&pixg);
    pixDestroy(&pixb);

        /* Add highlight color to colormap */
    pixt = pixThresholdTo4bpp(pixs, 5, 1);
    cmap = pixGetColormap(pixt);
    pixcmapGetIndex(cmap, 255, 255, 255, &index);
    box = boxCreate(507, 5, 385, 45);
    pixSetSelectCmap(pixt, box, index, 50, 0, 250);
    boxDestroy(&box);
    box = boxCreate(236, 107, 262, 40);
    pixSetSelectCmap(pixt, box, index, 250, 0, 50);
    boxDestroy(&box);
    box = boxCreate(222, 208, 247, 43);
    pixSetSelectCmap(pixt, box, index, 60, 250, 60);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 9 */
    pixaAddPix(pixa, pixt, L_INSERT);
    boxDestroy(&box);

        /* Paint lines on RGB */
    pixt = pixConvert8To32(pixs);
    pixRenderLineArb(pixt, 450, 20, 850, 320, 5, 200, 50, 125);
    pixRenderLineArb(pixt, 30, 40, 440, 40, 5, 100, 200, 25);
    box = boxCreate(70, 80, 300, 245);
    pixRenderBoxArb(pixt, box, 3, 200, 200, 25);
    regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG);  /* 10 */
    pixaAddPix(pixa, pixt, L_INSERT);
    boxDestroy(&box);

        /* Paint lines on colormap */
    pixt = pixThresholdTo4bpp(pixs, 5, 1);
    pixRenderLineArb(pixt, 450, 20, 850, 320, 5, 200, 50, 125);
    pixRenderLineArb(pixt, 30, 40, 440, 40, 5, 100, 200, 25);
    box = boxCreate(70, 80, 300, 245);
    pixRenderBoxArb(pixt, box, 3, 200, 200, 25);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 11 */
    pixaAddPix(pixa, pixt, L_INSERT);
    boxDestroy(&box);

        /* Blend lines on RGB */
    pixt = pixConvert8To32(pixs);
    pixRenderLineBlend(pixt, 450, 20, 850, 320, 5, 200, 50, 125, 0.35);
    pixRenderLineBlend(pixt, 30, 40, 440, 40, 5, 100, 200, 25, 0.35);
    box = boxCreate(70, 80, 300, 245);
    pixRenderBoxBlend(pixt, box, 3, 200, 200, 25, 0.6);
    regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG);  /* 12 */
    pixaAddPix(pixa, pixt, L_INSERT);
    boxDestroy(&box);

        /* Colorize gray on cmapped image. */
    pix1 = pixRead("lucasta.150.jpg");
    pix2 = pixThresholdTo4bpp(pix1, 7, 1);
    box1 = boxCreate(73, 206, 140, 27);
    pixColorGrayCmap(pix2, box1, L_PAINT_LIGHT, 130, 207, 43);
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 13 */
    pixaAddPix(pixa, pix2, L_COPY);
    if (rp->display)
        pixPrintStreamInfo(stderr, pix2, "One box added");

    box2 = boxCreate(255, 404, 197, 25);
    pixColorGrayCmap(pix2, box2, L_PAINT_LIGHT, 230, 67, 119);
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 14 */
    pixaAddPix(pixa, pix2, L_COPY);
    if (rp->display)
        pixPrintStreamInfo(stderr, pix2, "Two boxes added");

    box3 = boxCreate(122, 756, 224, 22);
    pixColorGrayCmap(pix2, box3, L_PAINT_DARK, 230, 67, 119);
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 15 */
    pixaAddPix(pixa, pix2, L_COPY);
    if (rp->display)
        pixPrintStreamInfo(stderr, pix2, "Three boxes added");

    box4 = boxCreate(11, 780, 147, 22);
    pixColorGrayCmap(pix2, box4, L_PAINT_LIGHT, 70, 137, 229);
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 16 */
    pixaAddPix(pixa, pix2, L_COPY);
    if (rp->display)
        pixPrintStreamInfo(stderr, pix2, "Four boxes added");

    box5 = boxCreate(163, 605, 78, 22);
    pixColorGrayCmap(pix2, box5, L_PAINT_LIGHT, 70, 137, 229);
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 17 */
    pixaAddPix(pixa, pix2, L_INSERT);
    if (rp->display)
        pixPrintStreamInfo(stderr, pix2, "Five boxes added");
    pixDestroy(&pix1);
    boxDestroy(&box1);
    boxDestroy(&box2);
    boxDestroy(&box3);
    boxDestroy(&box4);
    boxDestroy(&box5);
    pixDestroy(&pixs);

        /* Make a gray image and identify the fg pixels (val > 230) */
    pixs = pixRead("feyn-fract.tif");
    pix1 = pixConvertTo8(pixs, 0);
    kel = makeGaussianKernel(2, 2, 1.5, 1.0);
    pix2 = pixConvolve(pix1, kel, 8, 1);
    pix3 = pixThresholdToBinary(pix2, 230);
    boxa = pixConnComp(pix3, NULL, 8);
    pixDestroy(&pixs);
    pixDestroy(&pix1);
    pixDestroy(&pix3);
    kernelDestroy(&kel);

        /* Color the individual components in the gray image */
    pix4 = pixColorGrayRegions(pix2, boxa, L_PAINT_DARK, 230, 255, 0, 0);
    regTestWritePixAndCheck(rp, pix4, IFF_PNG);  /* 18 */
    pixaAddPix(pixa, pix4, L_INSERT);
    pixDisplayWithTitle(pix4, 0, 0, NULL, rp->display);

        /* Threshold to 10 levels of gray */
    pix3 = pixThresholdOn8bpp(pix2, 10, 1);
    regTestWritePixAndCheck(rp, pix3, IFF_PNG);  /* 19 */
    pixaAddPix(pixa, pix3, L_COPY);

        /* Color the individual components in the cmapped image */
    pix4 = pixColorGrayRegions(pix3, boxa, L_PAINT_DARK, 230, 255, 0, 0);
    regTestWritePixAndCheck(rp, pix4, IFF_PNG);  /* 20 */
    pixaAddPix(pixa, pix4, L_INSERT);
    pixDisplayWithTitle(pix4, 0, 100, NULL, rp->display);
    boxaDestroy(&boxa);

        /* Color the entire gray image (not component-wise) */
    pixColorGray(pix2, NULL, L_PAINT_DARK, 230, 255, 0, 0);
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 21 */
    pixaAddPix(pixa, pix2, L_INSERT);

        /* Color the entire cmapped image (not component-wise) */
    pixColorGray(pix3, NULL, L_PAINT_DARK, 230, 255, 0, 0);
    regTestWritePixAndCheck(rp, pix3, IFF_PNG);  /* 22 */
    pixaAddPix(pixa, pix3, L_INSERT);

        /* Reconstruct cmapped images */
    pixd = ReconstructByValue(rp, "weasel2.4c.png");
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 23 */
    pixaAddPix(pixa, pixd, L_INSERT);
    pixd = ReconstructByValue(rp, "weasel4.11c.png");
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 24 */
    pixaAddPix(pixa, pixd, L_INSERT);
    pixd = ReconstructByValue(rp, "weasel8.240c.png");
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 25 */
    pixaAddPix(pixa, pixd, L_INSERT);

        /* Fake reconstruct cmapped images, with one color into a band */
    pixd = FakeReconstructByBand(rp, "weasel2.4c.png");
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 26 */
    pixaAddPix(pixa, pixd, L_INSERT);
    pixd = FakeReconstructByBand(rp, "weasel4.11c.png");
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 27 */
    pixaAddPix(pixa, pixd, L_INSERT);
    pixd = FakeReconstructByBand(rp, "weasel8.240c.png");
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 28 */
    pixaAddPix(pixa, pixd, L_INSERT);

        /* If in testing mode, make a pdf */
    if (rp->display) {
        pixaConvertToPdf(pixa, 100, 1.0, L_FLATE_ENCODE, 0,
                         "Colorize and paint", "/tmp/paint.pdf");
    }

    pixaDestroy(&pixa);
    return regTestCleanup(rp);
}
Exemple #21
0
/*!
 *  pixThinGeneral()
 *
 *      Input:  pixs (1 bpp)
 *              type (L_THIN_FG, L_THIN_BG)
 *              sela (of Sels for parallel composite HMTs)
 *              maxiters (max number of iters allowed; use 0 to iterate
 *                        until completion)
 *      Return: pixd, or null on error
 *
 *  Notes:
 *      (1) See notes in pixThin().  That function chooses among
 *          the best of the Sels for thinning.
 *      (2) This is a general function that takes a Sela of HMTs
 *          that are used in parallel for thinning from each
 *          of four directions.  One iteration consists of four
 *          such parallel thins.
 */
PIX *
pixThinGeneral(PIX     *pixs,
               l_int32  type,
               SELA    *sela,
               l_int32  maxiters)
{
l_int32  i, j, r, nsels, same;
PIXA    *pixahmt;
PIX    **pixhmt;  /* array owned by pixahmt; do not destroy! */
PIX     *pixd, *pixt;
SEL     *sel, *selr;

    PROCNAME("pixThinGeneral");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (pixGetDepth(pixs) != 1)
        return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
    if (type != L_THIN_FG && type != L_THIN_BG)
        return (PIX *)ERROR_PTR("invalid fg/bg type", procName, NULL);
    if (!sela)
        return (PIX *)ERROR_PTR("sela not defined", procName, NULL);
    if (maxiters == 0) maxiters = 10000;

        /* Set up array of temp pix to hold hmts */
    nsels = selaGetCount(sela);
    pixahmt = pixaCreate(nsels);
    for (i = 0; i < nsels; i++) {
        pixt = pixCreateTemplate(pixs);
        pixaAddPix(pixahmt, pixt, L_INSERT);
    }
    pixhmt = pixaGetPixArray(pixahmt);
    if (!pixhmt)
        return (PIX *)ERROR_PTR("pixhmt array not made", procName, NULL);

#if  DEBUG_SELS
    pixt = selaDisplayInPix(sela, 35, 3, 15, 4);
    pixDisplayWithTitle(pixt, 100, 100, "allsels", 1);
    pixDestroy(&pixt);
#endif  /* DEBUG_SELS */

        /* Set up initial image for fg thinning */
    if (type == L_THIN_FG)
        pixd = pixCopy(NULL, pixs);
    else  /* bg thinning */
        pixd = pixInvert(NULL, pixs);

        /* Thin the fg, with up to maxiters iterations */
    for (i = 0; i < maxiters; i++) {
        pixt = pixCopy(NULL, pixd);  /* test for completion */
        for (r = 0; r < 4; r++) {  /* over 90 degree rotations of Sels */
            for (j = 0; j < nsels; j++) {  /* over individual sels in sela */
                sel = selaGetSel(sela, j);  /* not a copy */
                selr = selRotateOrth(sel, r);
                pixHMT(pixhmt[j], pixd, selr);
                selDestroy(&selr);
                if (j > 0)
                    pixOr(pixhmt[0], pixhmt[0], pixhmt[j]);  /* accum result */
            }
            pixSubtract(pixd, pixd, pixhmt[0]);  /* remove result */
        }
        pixEqual(pixd, pixt, &same);
        pixDestroy(&pixt);
        if (same) {
            L_INFO("%d iterations to completion\n", procName, i);
            break;
        }
    }

    if (type == L_THIN_BG)
        pixInvert(pixd, pixd);

    pixaDestroy(&pixahmt);
    return pixd;
}
Exemple #22
0
int main(int    argc,
         char **argv)
{
l_int32      i, j, n;
l_int32      w, h, bw, bh, wpls, rval, gval, bval, same;
l_uint32     pixel;
l_uint32    *lines, *datas;
l_float32    sum1, sum2, sum3, ave1, ave2, ave3, ave4, diff1, diff2;
l_float32    var1, var2, var3;
BOX         *box1, *box2;
NUMA        *na, *na1, *na2, *na3, *na4;
PIX         *pix, *pixs, *pix1, *pix2, *pix3, *pix4, *pix5, *pixg, *pixd;
PIXA        *pixa;
PTA         *pta;
static char  mainName[] = "numa2_reg";

    if (argc != 1)
        return ERROR_INT(" Syntax:  numa2_reg", mainName, 1);

    /* -------------------------------------------------------------------*
     *                         Numa-windowed stats                        *
     * -------------------------------------------------------------------*/
#if  DO_ALL
    na = numaRead("lyra-5.numa");
    numaWindowedStats(na, 5, &na1, &na2, &na3, &na4);
    gplotSimple1(na, GPLOT_PNG, "/tmp/lyraroot6", "Original");
    gplotSimple1(na1, GPLOT_PNG, "/tmp/lyraroot7", "Mean");
    gplotSimple1(na2, GPLOT_PNG, "/tmp/lyraroot8", "Mean Square");
    gplotSimple1(na3, GPLOT_PNG, "/tmp/lyraroot9", "Variance");
    gplotSimple1(na4, GPLOT_PNG, "/tmp/lyraroot10", "RMS Difference");
#ifndef  _WIN32
    sleep(1);
#else
    Sleep(1000);
#endif  /* _WIN32 */
    pixa = pixaCreate(5);
    pix1 = pixRead("/tmp/lyraroot6.png");
    pix2 = pixRead("/tmp/lyraroot7.png");
    pix3 = pixRead("/tmp/lyraroot8.png");
    pix4 = pixRead("/tmp/lyraroot9.png");
    pix5 = pixRead("/tmp/lyraroot10.png");
    pixSaveTiled(pix1, pixa, 1.0, 1, 25, 32);
    pixSaveTiled(pix2, pixa, 1.0, 1, 25, 32);
    pixSaveTiled(pix3, pixa, 1.0, 0, 25, 32);
    pixSaveTiled(pix4, pixa, 1.0, 1, 25, 32);
    pixSaveTiled(pix5, pixa, 1.0, 0, 25, 32);
    pixd = pixaDisplay(pixa, 0, 0);
    pixDisplay(pixd, 100, 100);
    pixWrite("/tmp/numawindow.png", pixd, IFF_PNG);
    numaDestroy(&na);
    numaDestroy(&na1);
    numaDestroy(&na2);
    numaDestroy(&na3);
    numaDestroy(&na4);
    pixaDestroy(&pixa);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix3);
    pixDestroy(&pix4);
    pixDestroy(&pix5);
    pixDestroy(&pixd);
#endif

    /* -------------------------------------------------------------------*
     *                        Extraction on a line                        *
     * -------------------------------------------------------------------*/
#if  DO_ALL
        /* First, make a pretty image */
    w = h = 200;
    pixs = pixCreate(w, h, 32);
    wpls = pixGetWpl(pixs);
    datas = pixGetData(pixs);
    for (i = 0; i < 200; i++) {
        lines = datas + i * wpls;
        for (j = 0; j < 200; j++) {
            rval = (l_int32)((255. * j) / w + (255. * i) / h);
            gval = (l_int32)((255. * 2 * j) / w + (255. * 2 * i) / h) % 255;
            bval = (l_int32)((255. * 4 * j) / w + (255. * 4 * i) / h) % 255;
            composeRGBPixel(rval, gval, bval, &pixel);
            lines[j] = pixel;
        }
    }
    pixg = pixConvertTo8(pixs, 0);  /* and a grayscale version */
    pixWrite("/tmp/junkpixg", pixg, IFF_PNG);
    pixDisplay(pixg, 450, 100);

    na1 = pixExtractOnLine(pixg, 20, 20, 180, 20, 1);
    na2 = pixExtractOnLine(pixg, 40, 30, 40, 170, 1);
    na3 = pixExtractOnLine(pixg, 20, 170, 180, 30, 1);
    na4 = pixExtractOnLine(pixg, 20, 190, 180, 10, 1);
    gplotSimple1(na1, GPLOT_PNG, "/tmp/extroot1", "Horizontal");
    gplotSimple1(na2, GPLOT_PNG, "/tmp/extroot2", "Vertical");
    gplotSimple1(na3, GPLOT_PNG, "/tmp/extroot3",
                "Slightly more horizontal than vertical");
    gplotSimple1(na4, GPLOT_PNG, "/tmp/extroot4",
                "Slightly more vertical than horizontal");
#ifndef  _WIN32
    sleep(1);
#else
    Sleep(1000);
#endif  /* _WIN32 */
    pixa = pixaCreate(4);
    pix1 = pixRead("/tmp/extroot1.png");
    pix2 = pixRead("/tmp/extroot2.png");
    pix3 = pixRead("/tmp/extroot3.png");
    pix4 = pixRead("/tmp/extroot4.png");
    pixSaveTiled(pix1, pixa, 1.0, 1, 25, 32);
    pixSaveTiled(pix2, pixa, 1.0, 0, 25, 32);
    pixSaveTiled(pix3, pixa, 1.0, 1, 25, 32);
    pixSaveTiled(pix4, pixa, 1.0, 0, 25, 32);
    pixd = pixaDisplay(pixa, 0, 0);
    pixDisplay(pixd, 100, 500);
    pixWrite("/tmp/numaextract.png", pixd, IFF_PNG);
    numaDestroy(&na1);
    numaDestroy(&na2);
    numaDestroy(&na3);
    numaDestroy(&na4);
    pixaDestroy(&pixa);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix3);
    pixDestroy(&pix4);
    pixDestroy(&pix5);
    pixDestroy(&pixs);
    pixDestroy(&pixg);
    pixDestroy(&pixd);
#endif

    /* -------------------------------------------------------------------*
     *                     Row and column pixel sums                      *
     * -------------------------------------------------------------------*/
#if  DO_ALL
        /* Sum by columns in two halves (left and right) */
    pixs = pixRead("test8.jpg");
    pixGetDimensions(pixs, &w, &h, NULL);
    box1 = boxCreate(0, 0, w / 2, h);
    box2 = boxCreate(w / 2, 0, w - 2 / 2, h);
    na1 = pixAverageByColumn(pixs, box1, L_BLACK_IS_MAX);
    na2 = pixAverageByColumn(pixs, box2, L_BLACK_IS_MAX);
    numaJoin(na1, na2, 0, -1);
    na3 = pixAverageByColumn(pixs, NULL, L_BLACK_IS_MAX);
    numaSimilar(na1, na3, 0.0, &same);
    if (same)
        fprintf(stderr, "Same for columns\n");
    else
        fprintf(stderr, "Error for columns\n");
    pta = generatePlotPtaFromNuma(na3, L_HORIZONTAL_LINE, 3, h / 2, 80, 1);
    pix = pixConvertTo32(pixs);
    pixRenderPtaArb(pix, pta, 255, 0, 0);
    boxDestroy(&box1);
    boxDestroy(&box2);
    numaDestroy(&na1);
    numaDestroy(&na2);
    numaDestroy(&na3);
    ptaDestroy(&pta);

        /* Sum by rows in two halves (top and bottom) */
    box1 = boxCreate(0, 0, w, h / 2);
    box2 = boxCreate(0, h / 2, w, h - h / 2);
    na1 = pixAverageByRow(pixs, box1, L_WHITE_IS_MAX);
    na2 = pixAverageByRow(pixs, box2, L_WHITE_IS_MAX);
    numaJoin(na1, na2, 0, -1);
    na3 = pixAverageByRow(pixs, NULL, L_WHITE_IS_MAX);
    numaSimilar(na1, na3, 0.0, &same);
    if (same)
        fprintf(stderr, "Same for rows\n");
    else
        fprintf(stderr, "Error for rows\n");
    pta = generatePlotPtaFromNuma(na3, L_VERTICAL_LINE, 3, w / 2, 80, 1);
    pixRenderPtaArb(pix, pta, 0, 255, 0);
    pixDisplay(pix, 500, 200);
    boxDestroy(&box1);
    boxDestroy(&box2);
    numaDestroy(&na1);
    numaDestroy(&na2);
    numaDestroy(&na3);
    pixDestroy(&pix);
    ptaDestroy(&pta);

        /* Average left by rows; right by columns; compare totals */
    box1 = boxCreate(0, 0, w / 2, h);
    box2 = boxCreate(w / 2, 0, w - 2 / 2, h);
    na1 = pixAverageByRow(pixs, box1, L_WHITE_IS_MAX);
    na2 = pixAverageByColumn(pixs, box2, L_WHITE_IS_MAX);
    numaGetSum(na1, &sum1);  /* sum of averages of left box */
    numaGetSum(na2, &sum2);  /* sum of averages of right box */
    ave1 = sum1 / h;
    ave2 = 2.0 * sum2 / w;
    ave3 = 0.5 * (ave1 + ave2);  /* average over both halves */
    fprintf(stderr, "ave1 = %8.4f\n", sum1 / h);
    fprintf(stderr, "ave2 = %8.4f\n", 2.0 * sum2 / w);
    pixAverageInRect(pixs, NULL, &ave4);  /* entire image */
    diff1 = ave4 - ave3;
    diff2 = w * h * ave4 - (0.5 * w * sum1 + h * sum2);
    if (diff1 < 0.001)
        fprintf(stderr, "Average diffs are correct\n");
    else
        fprintf(stderr, "Average diffs are wrong: diff1 = %7.5f\n", diff1);
    if (diff2 < 20)  /* float-to-integer roundoff */
        fprintf(stderr, "Pixel sums are correct\n");
    else
        fprintf(stderr, "Pixel sums are in error: diff = %7.0f\n", diff2);

        /* Variance left and right halves.  Variance doesn't average
         * in a simple way, unlike pixel sums. */
    pixVarianceInRect(pixs, box1, &var1);  /* entire image */
    pixVarianceInRect(pixs, box2, &var2);  /* entire image */
    pixVarianceInRect(pixs, NULL, &var3);  /* entire image */
    fprintf(stderr, "0.5 * (var1 + var2) = %7.3f, var3 = %7.3f\n",
            0.5 * (var1 + var2), var3);
    boxDestroy(&box1);
    boxDestroy(&box2);
    numaDestroy(&na1);
    numaDestroy(&na2);
#endif

    /* -------------------------------------------------------------------*
     *                     Row and column variances                       *
     * -------------------------------------------------------------------*/
#if  DO_ALL
        /* Display variance by rows and columns */
    box1 = boxCreate(415, 0, 130, 425);
    boxGetGeometry(box1, NULL, NULL, &bw, &bh);
    na1 = pixVarianceByRow(pixs, box1);
    na2 = pixVarianceByColumn(pixs, box1);
    pix = pixConvertTo32(pixs);
    pta = generatePlotPtaFromNuma(na1, L_VERTICAL_LINE, 3, 415, 100, 1);
    pixRenderPtaArb(pix, pta, 255, 0, 0);
    ptaDestroy(&pta);
    pta = generatePlotPtaFromNuma(na2, L_HORIZONTAL_LINE, 3, bh / 2, 100, 1);
    pixRenderPtaArb(pix, pta, 0, 255, 0);
    pixDisplay(pix, 500, 900);
    boxDestroy(&box1);
    numaDestroy(&na1);
    numaDestroy(&na2);
    ptaDestroy(&pta);
    pixDestroy(&pix);
    pixDestroy(&pixs);

        /* Again on a different image */
    pix1 = pixRead("boxedpage.jpg");
    pix2 = pixConvertTo8(pix1, 0);
    pixGetDimensions(pix2, &w, &h, NULL);
    na1 = pixVarianceByRow(pix2, NULL);
    pta = generatePlotPtaFromNuma(na1, L_VERTICAL_LINE, 3, 0, 70, 1);
    pix3 = pixConvertTo32(pix1);
    pixRenderPtaArb(pix3, pta, 255, 0, 0);
    ptaDestroy(&pta);
    na2 = pixVarianceByColumn(pix2, NULL);
    pta = generatePlotPtaFromNuma(na2, L_HORIZONTAL_LINE, 3, bh - 1, 70, 1);
    pixRenderPtaArb(pix3, pta, 0, 255, 0);
    pixDisplay(pix3, 1000, 0);
    numaDestroy(&na1);
    numaDestroy(&na2);
    ptaDestroy(&pta);
    pixDestroy(&pix3);

        /* Again, with an erosion */
    pix3 = pixErodeGray(pix2, 3, 21);
    pixDisplay(pix3, 1400, 0);
    na1 = pixVarianceByRow(pix3, NULL);
    pta = generatePlotPtaFromNuma(na1, L_VERTICAL_LINE, 3, 30, 70, 1);
    pix4 = pixConvertTo32(pix1);
    pixRenderPtaArb(pix4, pta, 255, 0, 0);
    ptaDestroy(&pta);
    na2 = pixVarianceByColumn(pix3, NULL);
    pta = generatePlotPtaFromNuma(na2, L_HORIZONTAL_LINE, 3, bh - 1, 70, 1);
    pixRenderPtaArb(pix4, pta, 0, 255, 0);
    pixDisplay(pix4, 1000, 550);
    numaDestroy(&na1);
    numaDestroy(&na2);
    ptaDestroy(&pta);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix3);
    pixDestroy(&pix4);
#endif

    /* -------------------------------------------------------------------*
     *                    Windowed variance along a line                  *
     * -------------------------------------------------------------------*/
#if  DO_ALL
    pix1 = pixRead("boxedpage.jpg");
    pix2 = pixConvertTo8(pix1, 0);
    pixGetDimensions(pix2, &w, &h, NULL);

        /* Plot along horizontal line */
    pixWindowedVarianceOnLine(pix2, L_HORIZONTAL_LINE, h / 2 - 30, 0,
                              w, 5, &na1);
    pta = generatePlotPtaFromNuma(na1, L_HORIZONTAL_LINE, 3,
                                   h / 2 - 30, 80, 1);
    pixRenderPtaArb(pix1, pta, 255, 0, 0);
    numaDestroy(&na1);
    ptaDestroy(&pta);

        /* Plot along vertical line */
    pixWindowedVarianceOnLine(pix2, L_VERTICAL_LINE, 0.78 * w, 0,
                              h, 5, &na1);
    pta = generatePlotPtaFromNuma(na1, L_VERTICAL_LINE, 3,
                                   0.78 * w, 60, 1);
    pixRenderPtaArb(pix1, pta, 0, 255, 0);
    pixDisplay(pix1, 100, 100);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    numaDestroy(&na1);
    ptaDestroy(&pta);
#endif
    return 0;
}
Exemple #23
0
/*!
 *  jbWordsInTextlines()
 *
 *      Input:  dirin (directory of input pages)
 *              reduction (1 for full res; 2 for half-res)
 *              maxwidth (of word mask components, to be kept)
 *              maxheight (of word mask components, to be kept)
 *              thresh (on correlation; 0.80 is reasonable)
 *              weight (for handling thick text; 0.6 is reasonable)
 *              natl (<return> numa with textline index for each component)
 *              firstpage (0-based)
 *              npages (use 0 for all pages in dirin)
 *      Return: classer (for the set of pages)
 *
 *  Notes:
 *      (1) This is a high-level function.  See prog/jbwords for example
 *          of usage.
 *      (2) Typically, words can be found reasonably well at a resolution
 *          of about 150 ppi.  For highest accuracy, you should use 300 ppi.
 *          Assuming that the input images are 300 ppi, use reduction = 1
 *          for finding words at full res, and reduction = 2 for finding
 *          them at 150 ppi.
 */
JBCLASSER *
jbWordsInTextlines(const char  *dirin,
                   l_int32      reduction,
                   l_int32      maxwidth,
                   l_int32      maxheight,
                   l_float32    thresh,
                   l_float32    weight,
                   NUMA       **pnatl,
                   l_int32      firstpage,
                   l_int32      npages)
{
char       *fname;
l_int32     nfiles, i, w, h;
BOXA       *boxa;
JBCLASSER  *classer;
NUMA       *nai, *natl;
PIX        *pix;
PIXA       *pixa;
SARRAY     *safiles;

    PROCNAME("jbWordsInTextlines");

    if (!pnatl)
        return (JBCLASSER *)ERROR_PTR("&natl not defined", procName, NULL);
    *pnatl = NULL;
    if (!dirin)
        return (JBCLASSER *)ERROR_PTR("dirin not defined", procName, NULL);
    if (reduction != 1 && reduction != 2)
        return (JBCLASSER *)ERROR_PTR("reduction not in {1,2}", procName, NULL);

    safiles = getSortedPathnamesInDirectory(dirin, NULL, firstpage, npages);
    nfiles = sarrayGetCount(safiles);

        /* Classify components */
    classer = jbCorrelationInit(JB_WORDS, maxwidth, maxheight, thresh, weight);
    classer->safiles = sarrayCopy(safiles);
    natl = numaCreate(0);
    *pnatl = natl;
    for (i = 0; i < nfiles; i++) {
        fname = sarrayGetString(safiles, i, 0);
        if ((pix = pixRead(fname)) == NULL) {
            L_WARNING("image file %d not read\n", procName, i);
            continue;
        }
        pixGetDimensions(pix, &w, &h, NULL);
        if (reduction == 1) {
            classer->w = w;
            classer->h = h;
        } else {  /* reduction == 2 */
            classer->w = w / 2;
            classer->h = h / 2;
        }
        pixGetWordsInTextlines(pix, reduction, JB_WORDS_MIN_WIDTH,
                               JB_WORDS_MIN_HEIGHT, maxwidth, maxheight,
                               &boxa, &pixa, &nai);
        jbAddPageComponents(classer, pix, boxa, pixa);
        numaJoin(natl, nai, 0, -1);
        pixDestroy(&pix);
        numaDestroy(&nai);
        boxaDestroy(&boxa);
        pixaDestroy(&pixa);
    }

    sarrayDestroy(&safiles);
    return classer;
}
Exemple #24
0
int main(int    argc,
         char **argv)
{
char          seq[512];
l_int32       w, h;
PIX          *pixs, *pix1, *pix2, *pix3, *pix4, *pix5;
PIXA         *pixa;
PIXACC       *pacc;
PIXCMAP      *cmap;
L_REGPARAMS  *rp;

    if (regTestSetup(argc, argv, &rp))
        return 1;

    pixs = pixRead("aneurisms8.jpg");
    pixa = pixaCreate(0);

    /* =========================================================== */

    /* -------- Test gray morph, including interpreter ------------ */
    pix1 = pixDilateGray(pixs, WSIZE, HSIZE);
    snprintf(seq, sizeof(seq), "D%d.%d", WSIZE, HSIZE);
    pix2 = pixGrayMorphSequence(pixs, seq, 0, 0);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 0 */
    regTestComparePix(rp, pix1, pix2);  /* 1 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);

    pix1 = pixErodeGray(pixs, WSIZE, HSIZE);
    snprintf(seq, sizeof(seq), "E%d.%d", WSIZE, HSIZE);
    pix2 = pixGrayMorphSequence(pixs, seq, 0, 100);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 2 */
    regTestComparePix(rp, pix1, pix2);  /* 3 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);

    pix1 = pixOpenGray(pixs, WSIZE, HSIZE);
    snprintf(seq, sizeof(seq), "O%d.%d", WSIZE, HSIZE);
    pix2 = pixGrayMorphSequence(pixs, seq, 0, 200);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 4 */
    regTestComparePix(rp, pix1, pix2);  /* 5 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);

    pix1 = pixCloseGray(pixs, WSIZE, HSIZE);
    snprintf(seq, sizeof(seq), "C%d.%d", WSIZE, HSIZE);
    pix2 = pixGrayMorphSequence(pixs, seq, 0, 300);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 6 */
    regTestComparePix(rp, pix1, pix2);  /* 7 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);

    pix1 = pixTophat(pixs, WSIZE, HSIZE, L_TOPHAT_WHITE);
    snprintf(seq, sizeof(seq), "Tw%d.%d", WSIZE, HSIZE);
    pix2 = pixGrayMorphSequence(pixs, seq, 0, 400);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 8 */
    regTestComparePix(rp, pix1, pix2);  /* 9 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);

    pix1 = pixTophat(pixs, WSIZE, HSIZE, L_TOPHAT_BLACK);
    snprintf(seq, sizeof(seq), "Tb%d.%d", WSIZE, HSIZE);
    pix2 = pixGrayMorphSequence(pixs, seq, 0, 500);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 10 */
    regTestComparePix(rp, pix1, pix2);  /* 11 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);

    /* ------------- Test erode/dilate duality -------------- */
    pix1 = pixDilateGray(pixs, WSIZE, HSIZE);
    pix2 = pixInvert(NULL, pixs);
    pix3 = pixErodeGray(pix2, WSIZE, HSIZE);
    pixInvert(pix3, pix3);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 12 */
    regTestComparePix(rp, pix1, pix3);  /* 13 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);
    pixDestroy(&pix3);

    /* ------------- Test open/close duality -------------- */
    pix1 = pixOpenGray(pixs, WSIZE, HSIZE);
    pix2 = pixInvert(NULL, pixs);
    pix3 = pixCloseGray(pix2, WSIZE, HSIZE);
    pixInvert(pix3, pix3);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 14 */
    regTestComparePix(rp, pix1, pix3);  /* 15 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);
    pixDestroy(&pix3);

    /* ------------- Test tophat duality -------------- */
    pix1 = pixTophat(pixs, WSIZE, HSIZE, L_TOPHAT_WHITE);
    pix2 = pixInvert(NULL, pixs);
    pix3 = pixTophat(pix2, WSIZE, HSIZE, L_TOPHAT_BLACK);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 16 */
    regTestComparePix(rp, pix1, pix3);  /* 17 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);
    pixDestroy(&pix3);

    pix1 = pixGrayMorphSequence(pixs, "Tw9.5", 0, 100);
    pix2 = pixInvert(NULL, pixs);
    pix3 = pixGrayMorphSequence(pix2, "Tb9.5", 0, 300);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 18 */
    regTestComparePix(rp, pix1, pix3);  /* 19 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);
    pixDestroy(&pix3);


    /* ------------- Test opening/closing for large sels -------------- */
    pix1 = pixGrayMorphSequence(pixs,
            "C9.9 + C19.19 + C29.29 + C39.39 + C49.49", 0, 100);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 20 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pix1 = pixGrayMorphSequence(pixs,
            "O9.9 + O19.19 + O29.29 + O39.39 + O49.49", 0, 400);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 21 */
    pixaAddPix(pixa, pix1, L_INSERT);

    pix1 = pixaDisplayTiledInColumns(pixa, 4, 1.0, 20, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 22 */
    pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display);
    pixaDestroy(&pixa);
    pixDestroy(&pix1);

    /* =========================================================== */

    pixa = pixaCreate(0);
    /* ---------- Closing plus white tophat result ------------ *
     *            Parameters: wsize, hsize = 9, 29             *
     * ---------------------------------------------------------*/
    pix1 = pixCloseGray(pixs, 9, 9);
    pix2 = pixTophat(pix1, 9, 9, L_TOPHAT_WHITE);
    pix3 = pixGrayMorphSequence(pixs, "C9.9 + TW9.9", 0, 0);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 23 */
    regTestComparePix(rp, pix2, pix3);  /* 24 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pix1 = pixMaxDynamicRange(pix2, L_LINEAR_SCALE);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 25 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);
    pixDestroy(&pix3);

    pix1 = pixCloseGray(pixs, 29, 29);
    pix2 = pixTophat(pix1, 29, 29, L_TOPHAT_WHITE);
    pix3 = pixGrayMorphSequence(pixs, "C29.29 + Tw29.29", 0, 0);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 26 */
    regTestComparePix(rp, pix2, pix3);  /* 27 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pix1 = pixMaxDynamicRange(pix2, L_LINEAR_SCALE);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 28 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);
    pixDestroy(&pix3);

    /* --------- hdome with parameter height = 100 ------------*/
    pix1 = pixHDome(pixs, 100, 4);
    pix2 = pixMaxDynamicRange(pix1, L_LINEAR_SCALE);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 29 */
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 30 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixaAddPix(pixa, pix2, L_INSERT);

    /* ----- Contrast enhancement with morph parameters 9, 9 -------*/
    pixGetDimensions(pixs, &w, &h, NULL);
    pix1 = pixInitAccumulate(w, h, 0x8000);
    pixAccumulate(pix1, pixs, L_ARITH_ADD);
    pixMultConstAccumulate(pix1, 3., 0x8000);
    pix2 = pixOpenGray(pixs, 9, 9);
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 31 */
    pixaAddPix(pixa, pix2, L_INSERT);
    pixAccumulate(pix1, pix2, L_ARITH_SUBTRACT);

    pix2 = pixCloseGray(pixs, 9, 9);
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 32 */
    pixaAddPix(pixa, pix2, L_INSERT);
    pixAccumulate(pix1, pix2, L_ARITH_SUBTRACT);
    pix2 = pixFinalAccumulate(pix1, 0x8000, 8);
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 33 */
    pixaAddPix(pixa, pix2, L_INSERT);
    pixDestroy(&pix1);

        /* Do the same thing with the Pixacc */
    pacc = pixaccCreate(w, h, 1);
    pixaccAdd(pacc, pixs);
    pixaccMultConst(pacc, 3.);
    pix1 = pixOpenGray(pixs, 9, 9);
    pixaccSubtract(pacc, pix1);
    pixDestroy(&pix1);
    pix1 = pixCloseGray(pixs, 9, 9);
    pixaccSubtract(pacc, pix1);
    pixDestroy(&pix1);
    pix1 = pixaccFinal(pacc, 8);
    pixaccDestroy(&pacc);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 34 */
    pixaAddPix(pixa, pix1, L_INSERT);
    regTestComparePix(rp, pix1, pix2);  /* 35 */

    pix1 = pixaDisplayTiledInColumns(pixa, 4, 1.0, 20, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 36 */
    pixDisplayWithTitle(pix1, 1100, 0, NULL, rp->display);
    pixaDestroy(&pixa);
    pixDestroy(&pix1);
    pixDestroy(&pixs);

    /* =========================================================== */

    pixa = pixaCreate(0);

    /* ----  Tophat result on feynman stamp, to extract diagrams ----- */
    pixs = pixRead("feynman-stamp.jpg");
    pixGetDimensions(pixs, &w, &h, NULL);

        /* Make output image to hold five intermediate images */
    pix1 = pixCreate(5 * w + 18, h + 6, 32);  /* composite output image */
    pixSetAllArbitrary(pix1, 0x0000ff00);  /* set to blue */

        /* Paste in the input image */
    pix2 = pixRemoveColormap(pixs, REMOVE_CMAP_TO_FULL_COLOR);
    pixRasterop(pix1, 3, 3, w, h, PIX_SRC, pix2, 0, 0);  /* 1st one */
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 37 */
    pixaAddPix(pixa, pix2, L_INSERT);

        /* Paste in the grayscale version */
    cmap = pixGetColormap(pixs);
    if (cmap)
        pix2 = pixRemoveColormap(pixs, REMOVE_CMAP_TO_GRAYSCALE);
    else
        pix2 = pixConvertRGBToGray(pixs, 0.33, 0.34, 0.33);
    pix3 = pixConvertTo32(pix2);  /* 8 --> 32 bpp */
    pixRasterop(pix1, w + 6, 3, w, h, PIX_SRC, pix3, 0, 0);  /* 2nd one */
    regTestWritePixAndCheck(rp, pix3, IFF_PNG);  /* 38 */
    pixaAddPix(pixa, pix3, L_INSERT);

         /* Paste in a log dynamic range scaled version of the white tophat */
    pix3 = pixTophat(pix2, 3, 3, L_TOPHAT_WHITE);
    pix4 = pixMaxDynamicRange(pix3, L_LOG_SCALE);
    pix5 = pixConvertTo32(pix4);
    pixRasterop(pix1, 2 * w + 9, 3, w, h, PIX_SRC, pix5, 0, 0);  /* 3rd */
    regTestWritePixAndCheck(rp, pix5, IFF_PNG);  /* 39 */
    pixaAddPix(pixa, pix5, L_INSERT);
    pixDestroy(&pix2);
    pixDestroy(&pix4);

        /* Stretch the range and threshold to binary; paste it in */
    pix2 = pixGammaTRC(NULL, pix3, 1.0, 0, 80);
    pix4 = pixThresholdToBinary(pix2, 70);
    pix5 = pixConvertTo32(pix4);
    pixRasterop(pix1, 3 * w + 12, 3, w, h, PIX_SRC, pix5, 0, 0);  /* 4th */
    regTestWritePixAndCheck(rp, pix5, IFF_PNG);  /* 40 */
    pixaAddPix(pixa, pix5, L_INSERT);
    pixDestroy(&pix2);
    pixDestroy(&pix3);

        /* Invert; this is the final result */
    pixInvert(pix4, pix4);
    pix5 = pixConvertTo32(pix4);
    pixRasterop(pix1, 4 * w + 15, 3, w, h, PIX_SRC, pix5, 0, 0);  /* 5th */
    regTestWritePixAndCheck(rp, pix5, IFF_PNG);  /* 41 */
    pixaAddPix(pixa, pix5, L_INSERT);
    pixDestroy(&pix1);
    pixDestroy(&pix4);

    pix1 = pixaDisplayTiledInRows(pixa, 32, 1700, 1.0, 0, 20, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 42 */
    pixDisplayWithTitle(pix1, 0, 800, NULL, rp->display);
    pixaDestroy(&pixa);
    pixDestroy(&pix1);
    pixDestroy(&pixs);

    return regTestCleanup(rp);
}
Exemple #25
0
/*!
 *  jbCorrelation()
 *
 *       Input:  dirin (directory of input images)
 *               thresh (typically ~0.8)
 *               weight (typically ~0.6)
 *               components (JB_CONN_COMPS, JB_CHARACTERS, JB_WORDS)
 *               rootname (for output files)
 *               firstpage (0-based)
 *               npages (use 0 for all pages in dirin)
 *               renderflag (1 to render from templates; 0 to skip)
 *       Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) The images must be 1 bpp.  If they are not, you can convert
 *          them using convertFilesTo1bpp().
 *      (2) See prog/jbcorrelation for generating more output (e.g.,
 *          for debugging)
 */
l_int32
jbCorrelation(const char  *dirin,
              l_float32    thresh,
              l_float32    weight,
              l_int32      components,
              const char  *rootname,
              l_int32      firstpage,
              l_int32      npages,
              l_int32      renderflag)
{
	char        filename[L_BUF_SIZE];
	l_int32     nfiles, i, numpages;
	JBDATA     *data;
	JBCLASSER  *classer;
	PIX        *pix;
	PIXA       *pixa;
	SARRAY     *safiles;

	PROCNAME("jbCorrelation");

	if (!dirin)
		return ERROR_INT("dirin not defined", procName, 1);
	if (!rootname)
		return ERROR_INT("rootname not defined", procName, 1);
	if (components != JB_CONN_COMPS && components != JB_CHARACTERS &&
		components != JB_WORDS)
		return ERROR_INT("components invalid", procName, 1);

	safiles = getSortedPathnamesInDirectory(dirin, NULL, firstpage, npages);
	nfiles = sarrayGetCount(safiles);

	/* Classify components */
	classer = jbCorrelationInit(components, 0, 0, thresh, weight);
	jbAddPages(classer, safiles);

	/* Save data */
	data = jbDataSave(classer);
	jbDataWrite(rootname, data);

	/* Optionally, render pages using class templates */
	if (renderflag) {
		pixa = jbDataRender(data, FALSE);
		numpages = pixaGetCount(pixa);
		if (numpages != nfiles)
			fprintf(stderr, "numpages = %d, nfiles = %d, not equal!\n",
					numpages, nfiles);
		for (i = 0; i < numpages; i++) {
			pix = pixaGetPix(pixa, i, L_CLONE);
			snprintf(filename, L_BUF_SIZE, "%s.%05d", rootname, i);
			fprintf(stderr, "filename: %s\n", filename);
			pixWrite(filename, pix, IFF_PNG);
			pixDestroy(&pix);
		}
		pixaDestroy(&pixa);
	}

	sarrayDestroy(&safiles);
	jbClasserDestroy(&classer);
	jbDataDestroy(&data);
	return 0;
}
l_int32
GeneratePattern(l_int32       patno,
                l_int32       red,
                L_REGPARAMS  *rp)
{
l_int32  width, cx, cy;
PIX     *pixs, *pixt, *pix, *pixr, *pixp, *pixsel, *pixhmt;
PIX     *pixc1, *pixc2, *pixc3, *pixd;
PIXA    *pixa;
SEL     *selhm;

    PROCNAME("GeneratePattern");

    if ((pixs = pixRead(patname[patno])) == NULL) {
        rp->success = FALSE;
	return ERROR_INT("pixs not made", procName, 1);
    }

        /* Make a hit-miss sel at specified reduction factor */
    if (red == 4) {
        pixt = pixReduceRankBinaryCascade(pixs, 4, 4, 0, 0);
        selhm = pixGenerateSelBoundary(pixt, 2, 2, 20, 30, 1, 1, 0, 0, &pixp);
    }
    else if (red == 8) {
        pixt = pixReduceRankBinaryCascade(pixs, 4, 4, 2, 0);
        selhm = pixGenerateSelBoundary(pixt, 1, 2, 6, 12, 1, 1, 0, 0, &pixp);
    }
    else {  /*  red == 16 */
        pixt = pixReduceRankBinaryCascade(pixs, 4, 4, 2, 2);
        selhm = pixGenerateSelBoundary(pixt, 1, 1, 4, 8, 0, 0, 0, 0, &pixp);
    }
    pixDestroy(&pixt);

        /* Display the sel */
    pixsel = pixDisplayHitMissSel(pixp, selhm, 7, HitColor, MissColor);
    pixa = pixaCreate(2);
    pixaAddPix(pixa, pixs, L_CLONE);
    pixaAddPix(pixa, pixsel, L_CLONE);
    width = (patno == 0) ? 1200 : 400;
    pixd = pixaDisplayTiledAndScaled(pixa, 32, width, 2, 0, 30, 2);
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);
    pixDisplayWithTitle(pixd, 100, 100 + 100 * (3 * patno + red / 4),
                        NULL, rp->display);
    pixaDestroy(&pixa);
    pixDestroy(&pixd);

        /* Use the sel to find all instances in the page */
    pix = pixRead("tribune-page-4x.png");  /* 4x reduced */
    if (red == 4)
        pixr = pixClone(pix);
    else if (red == 8)
        pixr = pixReduceRankBinaryCascade(pix, 2, 0, 0, 0);
    else if (red == 16)
        pixr = pixReduceRankBinaryCascade(pix, 2, 2, 0, 0);
    pixDestroy(&pix);

    startTimer();
    pixhmt = pixHMT(NULL, pixr, selhm);
    fprintf(stderr, "Time to find patterns = %7.3f\n", stopTimer());

        /* Color each instance at full res */
    selGetParameters(selhm, NULL, NULL, &cy, &cx);
    pixc1 = pixDisplayMatchedPattern(pixr, pixp, pixhmt,
                                     cx, cy, 0x0000ff00, 1.0, 5);
    regTestWritePixAndCheck(rp, pixc1, IFF_PNG);
    pixDisplayWithTitle(pixc1, 500, 100, NULL, rp->display);
    
        /* Color each instance at 0.5 scale */
    pixc2 = pixDisplayMatchedPattern(pixr, pixp, pixhmt,
                                     cx, cy, 0x0000ff00, 0.5, 5);
    regTestWritePixAndCheck(rp, pixc2, IFF_PNG);

        /* Remove each instance from the input image */
    pixc3 = pixCopy(NULL, pixr);
    pixRemoveMatchedPattern(pixc3, pixp, pixhmt, cx, cy, 1);
    regTestWritePixAndCheck(rp, pixc3, IFF_PNG);

    selDestroy(&selhm);
    pixDestroy(&pixp);
    pixDestroy(&pixsel);
    pixDestroy(&pixhmt);
    pixDestroy(&pixc1);
    pixDestroy(&pixc2);
    pixDestroy(&pixc3);
    pixDestroy(&pixd);
    pixDestroy(&pixr);
    pixDestroy(&pixs);
    return 0;
}
Exemple #27
0
main(int    argc,
     char **argv)
{
BOX         *box;
PIX         *pix, *pixs, *pixd, *pixt;
PIXA        *pixa;
SEL         *sel, *sel1, *sel2, *sel3;
SELA        *sela4, *sela8, *sela48;
static char  mainName[] = "ccthin1_reg";

    if (argc != 1)
	exit(ERROR_INT(" Syntax: ccthin1_reg", mainName, 1));

        /* Generate and display all of the 4-cc sels */
    sela4 = selaCreate(9);
    sel = selCreateFromString(sel_4_1, 3, 3, "sel_4_1");
    selaAddSel(sela4, sel, NULL, 0);
    sel = selCreateFromString(sel_4_2, 3, 3, "sel_4_2");
    selaAddSel(sela4, sel, NULL, 0);
    sel = selCreateFromString(sel_4_3, 3, 3, "sel_4_3");
    selaAddSel(sela4, sel, NULL, 0);
    sel = selCreateFromString(sel_4_4, 3, 3, "sel_4_4");
    selaAddSel(sela4, sel, NULL, 0);
    sel = selCreateFromString(sel_4_5, 3, 3, "sel_4_5");
    selaAddSel(sela4, sel, NULL, 0);
    sel = selCreateFromString(sel_4_6, 3, 3, "sel_4_6");
    selaAddSel(sela4, sel, NULL, 0);
    sel = selCreateFromString(sel_4_7, 3, 3, "sel_4_7");
    selaAddSel(sela4, sel, NULL, 0);
    sel = selCreateFromString(sel_4_8, 3, 3, "sel_4_8");
    selaAddSel(sela4, sel, NULL, 0);
    sel = selCreateFromString(sel_4_9, 3, 3, "sel_4_9");
    selaAddSel(sela4, sel, NULL, 0);
    pixt = selaDisplayInPix(sela4, 35, 3, 15, 3);
    pixWrite("/tmp/junkallsel4.png", pixt, IFF_PNG);
    pixDestroy(&pixt);
    selaDestroy(&sela4);

        /* Generate and display all of the 8-cc sels */
    sela8 = selaCreate(9);
    sel = selCreateFromString(sel_8_1, 3, 3, "sel_8_1");
    selaAddSel(sela8, sel, NULL, 0);
    sel = selCreateFromString(sel_8_2, 3, 3, "sel_8_2");
    selaAddSel(sela8, sel, NULL, 0);
    sel = selCreateFromString(sel_8_3, 3, 3, "sel_8_3");
    selaAddSel(sela8, sel, NULL, 0);
    sel = selCreateFromString(sel_8_4, 3, 3, "sel_8_4");
    selaAddSel(sela8, sel, NULL, 0);
    sel = selCreateFromString(sel_8_5, 3, 3, "sel_8_5");
    selaAddSel(sela8, sel, NULL, 0);
    sel = selCreateFromString(sel_8_6, 3, 3, "sel_8_6");
    selaAddSel(sela8, sel, NULL, 0);
    sel = selCreateFromString(sel_8_7, 3, 3, "sel_8_7");
    selaAddSel(sela8, sel, NULL, 0);
    sel = selCreateFromString(sel_8_8, 3, 3, "sel_8_8");
    selaAddSel(sela8, sel, NULL, 0);
    sel = selCreateFromString(sel_8_9, 3, 3, "sel_8_9");
    selaAddSel(sela8, sel, NULL, 0);
    pixt = selaDisplayInPix(sela8, 35, 3, 15, 3);
    pixWrite("/tmp/junkallsel8.png", pixt, IFF_PNG);
    pixDestroy(&pixt);
    selaDestroy(&sela8);

        /* Generate and display all of the 4 and 8-cc preserving sels */
    sela48 = selaCreate(3);
    sel = selCreateFromString(sel_48_1, 3, 3, "sel_48_1");
    selaAddSel(sela48, sel, NULL, 0);
    sel = selCreateFromString(sel_48_2, 3, 3, "sel_48_2");
    selaAddSel(sela48, sel, NULL, 0);
    pixt = selaDisplayInPix(sela48, 35, 3, 15, 4);
    pixWrite("/tmp/junkallsel48.png", pixt, IFF_PNG);
    pixDestroy(&pixt);
    selaDestroy(&sela48);

        /* Generate and display three of the 4-cc sels and their rotations */
    sela4 = selaCreate(3);
    sel = selCreateFromString(sel_4_1, 3, 3, "sel_4_1");
    sel1 = selRotateOrth(sel, 1);
    sel2 = selRotateOrth(sel, 2);
    sel3 = selRotateOrth(sel, 3);
    selaAddSel(sela4, sel, NULL, 0);
    selaAddSel(sela4, sel1, "sel_4_1_90", 0);
    selaAddSel(sela4, sel2, "sel_4_1_180", 0);
    selaAddSel(sela4, sel3, "sel_4_1_270", 0);
    sel = selCreateFromString(sel_4_2, 3, 3, "sel_4_2");
    sel1 = selRotateOrth(sel, 1);
    sel2 = selRotateOrth(sel, 2);
    sel3 = selRotateOrth(sel, 3);
    selaAddSel(sela4, sel, NULL, 0);
    selaAddSel(sela4, sel1, "sel_4_2_90", 0);
    selaAddSel(sela4, sel2, "sel_4_2_180", 0);
    selaAddSel(sela4, sel3, "sel_4_2_270", 0);
    sel = selCreateFromString(sel_4_3, 3, 3, "sel_4_3");
    sel1 = selRotateOrth(sel, 1);
    sel2 = selRotateOrth(sel, 2);
    sel3 = selRotateOrth(sel, 3);
    selaAddSel(sela4, sel, NULL, 0);
    selaAddSel(sela4, sel1, "sel_4_3_90", 0);
    selaAddSel(sela4, sel2, "sel_4_3_180", 0);
    selaAddSel(sela4, sel3, "sel_4_3_270", 0);
    pixt = selaDisplayInPix(sela4, 35, 3, 15, 4);
    pixWrite("/tmp/junksel4.png", pixt, IFF_PNG);
    pixDestroy(&pixt);
    selaDestroy(&sela4);

        /* Generate and display four of the 8-cc sels and their rotations */
    sela8 = selaCreate(4);
    sel = selCreateFromString(sel_8_2, 3, 3, "sel_8_2");
    sel1 = selRotateOrth(sel, 1);
    sel2 = selRotateOrth(sel, 2);
    sel3 = selRotateOrth(sel, 3);
    selaAddSel(sela8, sel, NULL, 0);
    selaAddSel(sela8, sel1, "sel_8_2_90", 0);
    selaAddSel(sela8, sel2, "sel_8_2_180", 0);
    selaAddSel(sela8, sel3, "sel_8_2_270", 0);
    sel = selCreateFromString(sel_8_3, 3, 3, "sel_8_3");
    sel1 = selRotateOrth(sel, 1);
    sel2 = selRotateOrth(sel, 2);
    sel3 = selRotateOrth(sel, 3);
    selaAddSel(sela8, sel, NULL, 0);
    selaAddSel(sela8, sel1, "sel_8_3_90", 0);
    selaAddSel(sela8, sel2, "sel_8_3_180", 0);
    selaAddSel(sela8, sel3, "sel_8_3_270", 0);
    sel = selCreateFromString(sel_8_5, 3, 3, "sel_8_5");
    sel1 = selRotateOrth(sel, 1);
    sel2 = selRotateOrth(sel, 2);
    sel3 = selRotateOrth(sel, 3);
    selaAddSel(sela8, sel, NULL, 0);
    selaAddSel(sela8, sel1, "sel_8_5_90", 0);
    selaAddSel(sela8, sel2, "sel_8_5_180", 0);
    selaAddSel(sela8, sel3, "sel_8_5_270", 0);
    sel = selCreateFromString(sel_8_6, 3, 3, "sel_8_6");
    sel1 = selRotateOrth(sel, 1);
    sel2 = selRotateOrth(sel, 2);
    sel3 = selRotateOrth(sel, 3);
    selaAddSel(sela8, sel, NULL, 0);
    selaAddSel(sela8, sel1, "sel_8_6_90", 0);
    selaAddSel(sela8, sel2, "sel_8_6_180", 0);
    selaAddSel(sela8, sel3, "sel_8_6_270", 0);
    pixt = selaDisplayInPix(sela8, 35, 3, 15, 4);
    pixWrite("/tmp/junksel8.png", pixt, IFF_PNG);
    pixDestroy(&pixt);
    selaDestroy(&sela8);

        /* Test the best 4 and 8 cc thinning */
    pixDisplayWrite(NULL, 0);
    if ((pix = pixRead("feyn.tif")) == NULL)
	exit(ERROR_INT("pix not made", mainName, 1));
    box = boxCreate(683, 799, 970, 479);
    pixs = pixClipRectangle(pix, box, NULL);
    pixDisplayWrite(pixs, 1);

    pixt = pixThin(pixs, L_THIN_FG, 4, 0);
    pixDisplayWrite(pixt, 1);
    pixDestroy(&pixt);
    pixt = pixThin(pixs, L_THIN_BG, 4, 0);
    pixDisplayWrite(pixt, 1);
    pixDestroy(&pixt);

    pixt = pixThin(pixs, L_THIN_FG, 8, 0);
    pixDisplayWrite(pixt, 1);
    pixDestroy(&pixt);
    pixt = pixThin(pixs, L_THIN_BG, 8, 0);
    pixDisplayWrite(pixt, 1);
    pixDestroy(&pixt);

        /* Display tiled */
    pixa = pixaReadFiles("/tmp", "junk_write_display");
    pixd = pixaDisplayTiledAndScaled(pixa, 8, 500, 1, 0, 25, 2);
    pixWrite("/tmp/junktiles.jpg", pixd, IFF_JFIF_JPEG);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);
    pixDestroy(&pix);
    pixDestroy(&pixs);
    boxDestroy(&box);

    pixDisplayMultiple("/tmp/junk_write_display*");
    return 0;
}
Exemple #28
0
/*!
 *  pixaDisplayOnLattice()
 *
 *      Input:  pixa
 *              xspace
 *              yspace
 *      Return: pix of composite images, or null on error
 *
 *  Notes:
 *      (1) This places each pix on sequentially on a regular lattice
 *          in the rendered composite.  If a pix is too large to fit in the
 *          allocated lattice space, it is not rendered.
 *      (2) If any pix has a colormap, all pix are rendered in rgb.
 *      (3) This is useful when putting bitmaps of components,
 *          such as characters, into a single image.
 */
PIX *
pixaDisplayOnLattice(PIXA    *pixa,
                     l_int32  xspace,
                     l_int32  yspace)
{
l_int32  n, nw, nh, w, h, d, wt, ht;
l_int32  index, i, j, hascmap;
PIX     *pix, *pixt, *pixd;
PIXA    *pixat;

    PROCNAME("pixaDisplayOnLattice");

    if (!pixa)
        return (PIX *)ERROR_PTR("pixa not defined", procName, NULL);
    
        /* If any pix have colormaps, generate rgb */
    if ((n = pixaGetCount(pixa)) == 0)
        return (PIX *)ERROR_PTR("no components", procName, NULL);
    pixaAnyColormaps(pixa, &hascmap);
    if (hascmap) {
        pixat = pixaCreate(n);
        for (i = 0; i < n; i++) {
            pixt = pixaGetPix(pixa, i, L_CLONE);
            pix = pixConvertTo32(pixt);
            pixaAddPix(pixat, pix, L_INSERT);
            pixDestroy(&pixt);
        }
    }
    else
        pixat = pixaCopy(pixa, L_CLONE);

    nw = (l_int32)sqrt((l_float64)n);
    nh = (n + nw - 1) / nw;
    w = xspace * nw;
    h = yspace * nh;

        /* Use the first pix in pixa to determine the depth.  */
    pixaGetPixDimensions(pixat, 0, NULL, NULL, &d);

    if ((pixd = pixCreate(w, h, d)) == NULL) {
        pixaDestroy(&pixat);
        return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    }
    
    index = 0;
    for (i = 0; i < nh; i++) {
        for (j = 0; j < nw && index < n; j++, index++) {
            pixt = pixaGetPix(pixat, index, L_CLONE);
            pixGetDimensions(pixt, &wt, &ht, NULL);
            if (wt > xspace || ht > yspace) {
                fprintf(stderr, "pix(%d) omitted; size %dx%d\n", index, wt, ht);
                pixDestroy(&pixt);
                continue;
            }
            pixRasterop(pixd, j * xspace, i * yspace, wt, ht, 
                        PIX_PAINT, pixt, 0, 0);
            pixDestroy(&pixt);
        }
    }

    pixaDestroy(&pixat);
    return pixd;
}
int main(int    argc,
         char **argv)
{
l_int32  w, h, n, i, sum, sumi, empty;
BOX     *box1, *box2, *box3, *box4;
BOXA    *boxa, *boxat;
NUMA    *na1, *na2, *na3, *na4, *na5;
NUMA    *na2i, *na3i, *na4i, *nat, *naw, *nah;
PIX     *pixs, *pixc, *pixt, *pixt2, *pixd, *pixcount;
PIXA    *pixas, *pixad, *pixac;

    pixDisplayWrite(NULL, -1);

        /* Draw 4 filled boxes of different sizes */
    pixs = pixCreate(200, 200, 1);
    box1 = boxCreate(10, 10, 20, 30);
    box2 = boxCreate(50, 10, 40, 20);
    box3 = boxCreate(110, 10, 35, 5);
    box4 = boxCreate(160, 10, 5, 15);
    boxa = boxaCreate(4);
    boxaAddBox(boxa, box1, L_INSERT);
    boxaAddBox(boxa, box2, L_INSERT);
    boxaAddBox(boxa, box3, L_INSERT);
    boxaAddBox(boxa, box4, L_INSERT);
    pixRenderBox(pixs, box1, 1, L_SET_PIXELS);
    pixRenderBox(pixs, box2, 1, L_SET_PIXELS);
    pixRenderBox(pixs, box3, 1, L_SET_PIXELS);
    pixRenderBox(pixs, box4, 1, L_SET_PIXELS);
    pixt = pixFillClosedBorders(pixs, 4);
    pixDisplayWrite(pixt, 1);
    pixt2 = pixCreateTemplate(pixs);
    pixRenderHashBox(pixt2, box1, 6, 4, L_POS_SLOPE_LINE, 1, L_SET_PIXELS);
    pixRenderHashBox(pixt2, box2, 7, 2, L_POS_SLOPE_LINE, 1, L_SET_PIXELS);
    pixRenderHashBox(pixt2, box3, 4, 2, L_VERTICAL_LINE, 1, L_SET_PIXELS);
    pixRenderHashBox(pixt2, box4, 3, 1, L_HORIZONTAL_LINE, 1, L_SET_PIXELS);
    pixDisplayWrite(pixt2, 1);

        /* Exercise the parameters */
    pixd = pixSelectBySize(pixt, 0, 22, 8, L_SELECT_HEIGHT,
                           L_SELECT_IF_GT, NULL);
    count_pieces(pixd, 1);
    pixd = pixSelectBySize(pixt, 0, 30, 8, L_SELECT_HEIGHT,
                           L_SELECT_IF_LT, NULL);
    count_pieces(pixd, 3);
    pixd = pixSelectBySize(pixt, 0, 5, 8, L_SELECT_HEIGHT,
                           L_SELECT_IF_GT, NULL);
    count_pieces(pixd, 3);
    pixd = pixSelectBySize(pixt, 0, 6, 8, L_SELECT_HEIGHT,
                           L_SELECT_IF_LT, NULL);
    count_pieces(pixd, 1);
    pixd = pixSelectBySize(pixt, 20, 0, 8, L_SELECT_WIDTH,
                           L_SELECT_IF_GT, NULL);
    count_pieces(pixd, 2);
    pixd = pixSelectBySize(pixt, 31, 0, 8, L_SELECT_WIDTH,
                           L_SELECT_IF_LT, NULL);
    count_pieces(pixd, 2);
    pixd = pixSelectBySize(pixt, 21, 10, 8, L_SELECT_IF_EITHER,
                           L_SELECT_IF_LT, NULL);
    count_pieces(pixd, 3);
    pixd = pixSelectBySize(pixt, 20, 30, 8, L_SELECT_IF_EITHER,
                           L_SELECT_IF_GT, NULL);
    count_pieces(pixd, 2);
    pixd = pixSelectBySize(pixt, 22, 32, 8, L_SELECT_IF_BOTH,
                           L_SELECT_IF_LT, NULL);
    count_pieces(pixd, 2);
    pixd = pixSelectBySize(pixt, 6, 32, 8, L_SELECT_IF_BOTH,
                           L_SELECT_IF_LT, NULL);
    count_pieces(pixd, 1);
    pixd = pixSelectBySize(pixt, 5, 25, 8, L_SELECT_IF_BOTH,
                           L_SELECT_IF_GT, NULL);
    count_pieces(pixd, 1);
    pixd = pixSelectBySize(pixt, 25, 5, 8, L_SELECT_IF_BOTH,
                           L_SELECT_IF_GT, NULL);
    count_pieces(pixd, 1);

    pixd = pixSelectByPerimToAreaRatio(pixt, 0.3, 8, L_SELECT_IF_GT, NULL);
    count_pieces(pixd, 2);
    pixd = pixSelectByPerimToAreaRatio(pixt, 0.15, 8, L_SELECT_IF_GT, NULL);
    count_pieces(pixd, 3);
    pixd = pixSelectByPerimToAreaRatio(pixt, 0.4, 8, L_SELECT_IF_LTE, NULL);
    count_pieces(pixd, 2);
    pixd = pixSelectByPerimToAreaRatio(pixt, 0.45, 8, L_SELECT_IF_LT, NULL);
    count_pieces(pixd, 3);

    pixd = pixSelectByPerimSizeRatio(pixt2, 2.3, 8, L_SELECT_IF_GT, NULL);
    count_pieces(pixd, 2);
    pixd = pixSelectByPerimSizeRatio(pixt2, 1.2, 8, L_SELECT_IF_GT, NULL);
    count_pieces(pixd, 3);
    pixd = pixSelectByPerimSizeRatio(pixt2, 1.7, 8, L_SELECT_IF_LTE, NULL);
    count_pieces(pixd, 1);
    pixd = pixSelectByPerimSizeRatio(pixt2, 2.9, 8, L_SELECT_IF_LT, NULL);
    count_pieces(pixd, 3);

    pixd = pixSelectByAreaFraction(pixt2, 0.3, 8, L_SELECT_IF_LT, NULL);
    count_pieces(pixd, 0);
    pixd = pixSelectByAreaFraction(pixt2, 0.9, 8, L_SELECT_IF_LT, NULL);
    count_pieces(pixd, 4);
    pixd = pixSelectByAreaFraction(pixt2, 0.5, 8, L_SELECT_IF_GTE, NULL);
    count_pieces(pixd, 3);
    pixd = pixSelectByAreaFraction(pixt2, 0.7, 8, L_SELECT_IF_GT, NULL);
    count_pieces(pixd, 2);

    boxat = boxaSelectBySize(boxa, 21, 10, L_SELECT_IF_EITHER,
                             L_SELECT_IF_LT, NULL);
    count_pieces2(boxat, 3);
    boxat = boxaSelectBySize(boxa, 22, 32, L_SELECT_IF_BOTH,
                             L_SELECT_IF_LT, NULL);
    count_pieces2(boxat, 2);

    boxaDestroy(&boxa);
    pixDestroy(&pixt);
    pixDestroy(&pixt2);
    pixDestroy(&pixs);

        /* Here's the most general method for selecting components.
         * We do it for area fraction, but any combination of
         * size, area/perimeter ratio and area fraction can be used. */
    pixs = pixRead("feyn.tif");
/*    pixs = pixRead("rabi.png"); */
    pixc = pixCopy(NULL, pixs);  /* subtract bands from this */
    pixt = pixCreateTemplate(pixs);  /* add bands to this */
    pixGetDimensions(pixs, &w, &h, NULL);
    boxa = pixConnComp(pixs, &pixas, 8);
    n = boxaGetCount(boxa);
    fprintf(stderr, "total: %d\n", n);
    na1 = pixaFindAreaFraction(pixas);
    nat = numaCreate(0);
    numaSetCount(nat, n);  /* initialize to all 0 */
    sum = sumi = 0;
    pixac = pixaCreate(0);
    for (i = 0; i < 12; i++) {
            /* Compute within the intervals using an intersection. */
        na2 = numaMakeThresholdIndicator(na1, edges[i], L_SELECT_IF_GTE);
        if (i != 11)
            na3 = numaMakeThresholdIndicator(na1, edges[i + 1], L_SELECT_IF_LT);
        else
            na3 = numaMakeThresholdIndicator(na1, edges[i + 1],
                                             L_SELECT_IF_LTE);
        na4 = numaLogicalOp(NULL, na2, na3, L_INTERSECTION);
        sum += count_ones(na4, 0, 0, NULL);

            /* Compute outside the intervals using a union, and invert */
        na2i = numaMakeThresholdIndicator(na1, edges[i], L_SELECT_IF_LT);
        if (i != 11)
            na3i = numaMakeThresholdIndicator(na1, edges[i + 1],
                                              L_SELECT_IF_GTE);
        else
            na3i = numaMakeThresholdIndicator(na1, edges[i + 1],
                                              L_SELECT_IF_GT);
        na4i = numaLogicalOp(NULL, na3i, na2i, L_UNION);
        numaInvert(na4i, na4i);
        sumi += count_ones(na4i, 0, 0, NULL);

            /* Compare the two methods */
        if (sum == sumi)
            fprintf(stderr, "\nCorrect: sum = sumi = %d\n", sum);
        else
            fprintf(stderr, "\nWRONG: sum = %d, sumi = %d\n", sum, sumi);

            /* Reconstruct the image, band by band. */
        numaLogicalOp(nat, nat, na4, L_UNION);
        pixad = pixaSelectWithIndicator(pixas, na4, NULL);
        pixd = pixaDisplay(pixad, w, h);
        pixOr(pixt, pixt, pixd);  /* add them in */
        pixcount = pixCopy(NULL, pixt);  /* destroyed by count_pieces */
        count_ones(na4, band[i], i, "band");
        count_pieces(pixd, band[i]);
        count_ones(nat, total[i], i, "total");
        count_pieces(pixcount, total[i]);
        pixaDestroy(&pixad);

            /* Remove band successively from full image */
        pixRemoveWithIndicator(pixc, pixas, na4);
        pixSaveTiled(pixc, pixac, 0.25, 1 - i % 2, 25, 8);

        numaDestroy(&na2);
        numaDestroy(&na3);
        numaDestroy(&na4);
        numaDestroy(&na2i);
        numaDestroy(&na3i);
        numaDestroy(&na4i);
    }

        /* Did we remove all components from pixc? */
    pixZero(pixc, &empty);
    if (!empty)
        fprintf(stderr, "\nWRONG: not all pixels removed from pixc\n");

    pixDestroy(&pixs);
    pixDestroy(&pixc);
    pixDestroy(&pixt);
    boxaDestroy(&boxa);
    pixaDestroy(&pixas);
    numaDestroy(&na1);
    numaDestroy(&nat);

        /* One last extraction.  Get all components that have either
         * a height of at least 50 or a width of between 30 and 35,
         * and also have a relatively large perimeter/area ratio. */
    pixs = pixRead("feyn.tif");
    boxa = pixConnComp(pixs, &pixas, 8);
    n = boxaGetCount(boxa);
    pixaFindDimensions(pixas, &naw, &nah);
    na1 = pixaFindPerimToAreaRatio(pixas);
    na2 = numaMakeThresholdIndicator(nah, 50, L_SELECT_IF_GTE);
    na3 = numaMakeThresholdIndicator(naw, 30, L_SELECT_IF_GTE);
    na4 = numaMakeThresholdIndicator(naw, 35, L_SELECT_IF_LTE);
    na5 = numaMakeThresholdIndicator(na1, 0.4, L_SELECT_IF_GTE);
    numaLogicalOp(na3, na3, na4, L_INTERSECTION);
    numaLogicalOp(na2, na2, na3, L_UNION);
    numaLogicalOp(na2, na2, na5, L_INTERSECTION);
    numaInvert(na2, na2);  /* get components to be removed */
    pixRemoveWithIndicator(pixs, pixas, na2);
    pixSaveTiled(pixs, pixac, 0.25, 1, 25, 8);
    pixDestroy(&pixs);
    boxaDestroy(&boxa);
    pixaDestroy(&pixas);
    numaDestroy(&naw);
    numaDestroy(&nah);
    numaDestroy(&na1);
    numaDestroy(&na2);
    numaDestroy(&na3);
    numaDestroy(&na4);
    numaDestroy(&na5);

    pixDisplayMultiple("/tmp/display/file*");
    pixd = pixaDisplay(pixac, 0, 0);
    pixDisplay(pixd, 100, 100);
    pixWrite("/tmp/comp.jpg", pixd, IFF_JFIF_JPEG);
    pixDestroy(&pixd);
    pixaDestroy(&pixac);
    return 0;
}
main(int    argc,
     char **argv)
{
char         outname[256];
l_int32      loc, display, success;
L_BMF       *bmf, *bmftop;
FILE        *fp;
PIX         *pixs, *pixt, *pixd;
PIX         *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7, *pix8;
PIXA        *pixa;

    if (regTestSetup(argc, argv, &fp, &display, &success, NULL))
              return 1;

    bmf = bmfCreate("./fonts", 6);
    bmftop = bmfCreate("./fonts", 10);
    pixs = pixRead("lucasta-47.jpg");
    pix1 = pixScale(pixs, 0.4, 0.4);          /* 8 bpp grayscale */
    pix2 = pixConvertTo32(pix1);              /* 32 bpp rgb */
    pix3 = pixThresholdOn8bpp(pix1, 12, 1);   /* 8 bpp cmapped */
    pix4 = pixThresholdTo4bpp(pix1, 10, 1);   /* 4 bpp cmapped */
    pix5 = pixThresholdTo4bpp(pix1, 10, 0);   /* 4 bpp not cmapped */
    pix6 = pixThresholdTo2bpp(pix1, 3, 1);    /* 2 bpp cmapped */
    pix7 = pixThresholdTo2bpp(pix1, 3, 0);    /* 2 bpp not cmapped */
    pix8 = pixThresholdToBinary(pix1, 160);   /* 1 bpp */

    for (loc = 1; loc < 5; loc++) {
        pixa = pixaCreate(0);
        AddTextAndSave(pixa, pix1, bmf, textstr[0], loc, 190);
        AddTextAndSave(pixa, pix2, bmf, textstr[1], loc, 0xff000000);
        AddTextAndSave(pixa, pix3, bmf, textstr[2], loc, 0x00ff0000);
        AddTextAndSave(pixa, pix4, bmf, textstr[3], loc, 0x0000ff00);
        AddTextAndSave(pixa, pix5, bmf, textstr[4], loc, 11);
        AddTextAndSave(pixa, pix6, bmf, textstr[5], loc, 0xff000000);
        AddTextAndSave(pixa, pix7, bmf, textstr[6], loc, 2);
        AddTextAndSave(pixa, pix8, bmf, textstr[7], loc, 1);
        pixt = pixaDisplay(pixa, 0, 0);
        pixd = pixAddSingleTextblock(pixt, bmftop, topstr[loc - 1],
                                     0xff00ff00, L_ADD_ABOVE, NULL);
        snprintf(outname, 240, "/tmp/writetext.%d.png", loc - 1);
        pixWrite(outname, pixd, IFF_PNG);
        regTestCheckFile(fp, argv, outname, loc - 1, &success);
        pixDisplayWithTitle(pixd, 50 * loc, 50, NULL, display);
        pixDestroy(&pixt);
        pixDestroy(&pixd);
        pixaDestroy(&pixa);
    }

    pixDestroy(&pixs);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix3);
    pixDestroy(&pix4);
    pixDestroy(&pix5);
    pixDestroy(&pix6);
    pixDestroy(&pix7);
    pixDestroy(&pix8);
    bmfDestroy(&bmf);
    bmfDestroy(&bmftop);
    regTestCleanup(argc, argv, fp, success, NULL);
    return 0;
}