Пример #1
0
/*!
 *  pixaSelectByWidthHeightRatio()
 *
 *      Input:  pixas
 *              thresh (threshold ratio of width/height)
 *              type (L_SELECT_IF_LT, L_SELECT_IF_GT,
 *                    L_SELECT_IF_LTE, L_SELECT_IF_GTE)
 *              &changed (<optional return> 1 if changed; 0 if clone returned)
 *      Return: pixad, or null on error
 *
 *  Notes:
 *      (1) Returns a pixa clone if no components are removed.
 *      (2) Uses pix and box clones in the new pixa.
 *      (3) This filters components based on the width-to-height ratio
 *          of each pix.
 *      (4) Use L_SELECT_IF_LT or L_SELECT_IF_LTE to save components
 *          with less than the threshold ratio, and
 *          L_SELECT_IF_GT or L_SELECT_IF_GTE to remove them.
 */
PIXA *
pixaSelectByWidthHeightRatio(PIXA      *pixas,
                             l_float32  thresh,
                             l_int32    type,
                             l_int32   *pchanged)
{
NUMA  *na, *nai;
PIXA  *pixad;

    PROCNAME("pixaSelectByWidthHeightRatio");

    if (!pixas)
        return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
    if (type != L_SELECT_IF_LT && type != L_SELECT_IF_GT &&
        type != L_SELECT_IF_LTE && type != L_SELECT_IF_GTE)
        return (PIXA *)ERROR_PTR("invalid type", procName, NULL);

        /* Compute component ratios. */
    na = pixaFindWidthHeightRatio(pixas);

        /* Generate indicator array for elements to be saved. */
    nai = numaMakeThresholdIndicator(na, thresh, type);
    numaDestroy(&na);

        /* Filter to get output */
    pixad = pixaSelectWithIndicator(pixas, nai, pchanged);

    numaDestroy(&nai);
    return pixad;
}
Пример #2
0
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;
}
Пример #3
0
l_int32 main(int    argc,
             char **argv)
{
l_int32       i, w, h, n, val, ne, no, nbins, minw, maxw, minh, maxh;
l_int32       mine, mino, maxe, maxo;
l_int32       w_diff, h_diff, median_w_diff, median_h_diff;
l_int32       noutw, nouth;
l_float32     medwe, medhe, medwo, medho;
BOXA         *boxa1, *boxa2, *boxae, *boxao;
NUMA         *na1, *nawe, *nahe, *nawo, *naho;
NUMA         *nadiffw, *nadiffh;  /* diff from median w and h */
NUMA         *naiw, *naih;  /* indicator arrays for small outlier dimensions */
NUMA         *narbwe, *narbhe, *narbwo, *narbho;  /* rank-binned w and h */
PIX          *pix1;
PIXA         *pixa1;
L_REGPARAMS  *rp;

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

    lept_mkdir("lept/boxa");
    boxa1 = boxaRead("boxa4.ba");

        /* Fill invalid boxes */
    n = boxaGetCount(boxa1);
    na1 = boxaFindInvalidBoxes(boxa1);
    if (na1)
        boxa2 = boxaFillSequence(boxa1, L_USE_SAME_PARITY_BOXES, 0);
    else
        boxa2 = boxaCopy(boxa1, L_CLONE);
    boxaDestroy(&boxa1);

        /* Get the widths and heights for even and odd parity */
    boxaSplitEvenOdd(boxa2, 0, &boxae, &boxao);
    boxaGetSizes(boxae, &nawe, &nahe);
    boxaGetSizes(boxao, &nawo, &naho);
    boxaDestroy(&boxa2);

        /* Find the medians */
    numaGetMedian(nawe, &medwe);
    numaGetMedian(nahe, &medhe);
    numaGetMedian(nawo, &medwo);
    numaGetMedian(naho, &medho);

        /* Find the median even/odd differences for width and height */
    median_w_diff = L_ABS(medwe - medwo);
    median_h_diff = L_ABS(medhe - medho);
    regTestCompareValues(rp, 210, median_w_diff, 0.0);  /* 0 */
    regTestCompareValues(rp, 15, median_h_diff, 0.0);  /* 1 */
    if (rp->display) {
        fprintf(stderr, "diff of e/o median widths = %d\n", median_w_diff);
        fprintf(stderr, "diff of e/o median heights = %d\n", median_h_diff);
    }

        /* Find the differences of box width and height from the median */
    nadiffw = numaMakeConstant(0, n);
    nadiffh = numaMakeConstant(0, n);
    ne = numaGetCount(nawe);
    no = numaGetCount(nawo);
    for (i = 0; i < ne; i++) {
        numaGetIValue(nawe, i, &val);
        numaSetValue(nadiffw, 2 * i, L_ABS(val - medwe));
        numaGetIValue(nahe, i, &val);
        numaSetValue(nadiffh, 2 * i, L_ABS(val - medhe));
    }
    for (i = 0; i < no; i++) {
        numaGetIValue(nawo, i, &val);
        numaSetValue(nadiffw, 2 * i + 1, L_ABS(val - medwo));
        numaGetIValue(naho, i, &val);
        numaSetValue(nadiffh, 2 * i + 1, L_ABS(val - medho));
    }

        /* Don't count invalid boxes; set the diffs to 0 for them */
    if (na1) {
        for (i = 0; i < n; i++) {
            numaGetIValue(na1, i, &val);
            if (val == 1) {
                numaSetValue(nadiffw, i, 0);
                numaSetValue(nadiffh, i, 0);
            }
        }
    }

        /* Make an indicator array for boxes that differ from the
         * median by more than a threshold value for outliers */
    naiw = numaMakeThresholdIndicator(nadiffw, 90, L_SELECT_IF_GT);
    naih = numaMakeThresholdIndicator(nadiffh, 90, L_SELECT_IF_GT);
    numaGetCountRelativeToZero(naiw, L_GREATER_THAN_ZERO, &noutw);
    numaGetCountRelativeToZero(naih, L_GREATER_THAN_ZERO, &nouth);
    regTestCompareValues(rp, 24, noutw, 0.0);  /* 2 */
    regTestCompareValues(rp, 0, nouth, 0.0);  /* 3 */
    if (rp->display)
        fprintf(stderr, "num width outliers = %d, num height outliers = %d\n",
                noutw, nouth);
    numaDestroy(&nadiffw);
    numaDestroy(&nadiffh);
    numaDestroy(&naiw);
    numaDestroy(&naih);

        /* Find the rank bins for width and height */
    nbins = L_MAX(5, ne / 50);  // up to 50 pages/bin
    numaGetRankBinValues(nawe, nbins, NULL, &narbwe);
    numaGetRankBinValues(nawo, nbins, NULL, &narbwo);
    numaGetRankBinValues(nahe, nbins, NULL, &narbhe);
    numaGetRankBinValues(naho, nbins, NULL, &narbho);
    numaDestroy(&nawe);
    numaDestroy(&nawo);
    numaDestroy(&nahe);
    numaDestroy(&naho);

        /* Find min and max binned widths and heights; get the max diffs */
    numaGetIValue(narbwe, 0, &mine);
    numaGetIValue(narbwe, nbins - 1, &maxe);
    numaGetIValue(narbwo, 0, &mino);
    numaGetIValue(narbwo, nbins - 1, &maxo);
    minw = L_MIN(mine, mino);
    maxw = L_MAX(maxe, maxo);
    w_diff = maxw - minw;
    numaGetIValue(narbhe, 0, &mine);
    numaGetIValue(narbhe, nbins - 1, &maxe);
    numaGetIValue(narbho, 0, &mino);
    numaGetIValue(narbho, nbins - 1, &maxo);
    minh = L_MIN(mine, mino);
    maxh = L_MAX(maxe, maxo);
    h_diff = maxh - minh;
    numaDestroy(&narbwe);
    numaDestroy(&narbhe);
    numaDestroy(&narbwo);
    numaDestroy(&narbho);
    regTestCompareValues(rp, 409, w_diff, 0.0);  /* 4 */
    regTestCompareValues(rp, 49, h_diff, 0.0);  /* 5 */
    if (rp->display)
        fprintf(stderr, "Binned rank results: w_diff = %d, h_diff = %d\n",
                w_diff, h_diff);

        /* Plot the results */
    if (noutw > 0 || nouth > 0) {
        pixa1 = pixaCreate(2);
        boxaPlotSizes(boxae, "even", NULL, NULL, &pix1);
        pixaAddPix(pixa1, pix1, L_INSERT);
        boxaPlotSizes(boxao, "odd", NULL, NULL, &pix1);
        pixaAddPix(pixa1, pix1, L_INSERT);
        pix1 = pixaDisplayTiledInRows(pixa1, 32, 1500, 1.0, 0, 30, 2);
        regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 6 */
        pixDisplayWithTitle(pix1, 100, 100, NULL, rp->display);
        pixDestroy(&pix1);
        pixaDestroy(&pixa1);
    }

    boxaDestroy(&boxae);
    boxaDestroy(&boxao);
    return regTestCleanup(rp);
}