src/boxfunc5.c
BOXA *
boxaReconcileSidesByMedian(BOXA    *boxas,
                           l_int32  select,
                           l_int32  thresh,
                           l_int32  extra,
                           PIXA    *pixadb)
 {
char     buf[128];
l_int32  i, n, diff;
l_int32  left, right, top, bot, medleft, medright, medtop, medbot;
BOX     *box;
BOXA    *boxa1, *boxad;
PIX     *pix;

    PROCNAME("boxaReconcileSidesByMedian");

    if (!boxas)
        return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
    if (select != L_ADJUST_LEFT && select != L_ADJUST_RIGHT &&
        select != L_ADJUST_TOP && select != L_ADJUST_BOT &&
        select != L_ADJUST_LEFT_AND_RIGHT && select != L_ADJUST_TOP_AND_BOT) {
        L_WARNING("invalid select; returning copy\n", procName);
        return boxaCopy(boxas, L_COPY);
    }
    if (thresh < 0) {
        L_WARNING("thresh must be >= 0; returning copy\n", procName);
        return boxaCopy(boxas, L_COPY);
    }
    if (boxaGetValidCount(boxas) < 3) {
        L_WARNING("need at least 3 valid boxes; returning copy\n", procName);
        return boxaCopy(boxas, L_COPY);
    }

    if (select == L_ADJUST_LEFT_AND_RIGHT) {
        boxa1 = boxaReconcileSidesByMedian(boxas, L_ADJUST_LEFT, thresh, extra,
                                           pixadb);
        boxad = boxaReconcileSidesByMedian(boxa1, L_ADJUST_RIGHT, thresh, extra,
                                           pixadb);
        boxaDestroy(&boxa1);
        return boxad;
    }
    if (select == L_ADJUST_TOP_AND_BOT) {
        boxa1 = boxaReconcileSidesByMedian(boxas, L_ADJUST_TOP, thresh, extra,
                                           pixadb);
        boxad = boxaReconcileSidesByMedian(boxa1, L_ADJUST_BOT, thresh, extra,
                                           pixadb);
        boxaDestroy(&boxa1);
        return boxad;
    }

    if (pixadb) {
        l_int32 ndb = pixaGetCount(pixadb);
        if (ndb == 0 || ndb == 5) {  /* first of even and odd box sets */
            adjustSidePlotName(buf, sizeof(buf), "init", select);
            boxaPlotSides(boxas, buf, NULL, NULL, NULL, NULL, &pix);
            pixaAddPix(pixadb, pix, L_INSERT);
        }
    }

    n = boxaGetCount(boxas);
    boxad = boxaCreate(n);
    if (select == L_ADJUST_LEFT) {
        boxaGetMedianVals(boxas, &medleft, NULL, NULL, NULL, NULL, NULL);
        for (i = 0; i < n; i++) {
            box = boxaGetBox(boxas, i, L_COPY);
            boxGetSideLocations(box, &left, NULL, NULL, NULL);
            diff = medleft - left;
            if (L_ABS(diff) >= thresh)
                boxAdjustSides(box, box, diff - extra, 0, 0, 0);
            boxaAddBox(boxad, box, L_INSERT);
        }
    } else if (select == L_ADJUST_RIGHT) {
        boxaGetMedianVals(boxas, NULL, NULL, &medright, NULL, NULL, NULL);
        for (i = 0; i < n; i++) {
            box = boxaGetBox(boxas, i, L_COPY);
            boxGetSideLocations(box, NULL, &right, NULL, NULL);
            diff = medright - right;
            if (L_ABS(diff) >= thresh)
                boxAdjustSides(box, box, 0, diff + extra, 0, 0);
            boxaAddBox(boxad, box, L_INSERT);
        }
    } else if (select == L_ADJUST_TOP) {
        boxaGetMedianVals(boxas, NULL, &medtop, NULL, NULL, NULL, NULL);
        for (i = 0; i < n; i++) {
            box = boxaGetBox(boxas, i, L_COPY);
            boxGetSideLocations(box, NULL, NULL, &top, NULL);
            diff = medtop - top;
            if (L_ABS(diff) >= thresh)
                boxAdjustSides(box, box, 0, 0, diff - extra, 0);
            boxaAddBox(boxad, box, L_INSERT);
        }
    } else {  /* select == L_ADJUST_BOT */
        boxaGetMedianVals(boxas, NULL, NULL, NULL, &medbot, NULL, NULL);
        for (i = 0; i < n; i++) {
            box = boxaGetBox(boxas, i, L_COPY);
            boxGetSideLocations(box, NULL, NULL, NULL, &bot);
            diff = medbot - bot;
            if (L_ABS(diff) >= thresh)
                boxAdjustSides(box, box, 0, 0, 0, diff + extra);
            boxaAddBox(boxad, box, L_INSERT);
        }
    }

    if (pixadb) {
        adjustSidePlotName(buf, sizeof(buf), "final", select);
        boxaPlotSides(boxad, buf, NULL, NULL, NULL, NULL, &pix);
        pixaAddPix(pixadb, pix, L_INSERT);
    }
    return boxad;
}
/*!
 * \brief   boxaReconcileSidesByMedian()
 *
 * \param[in]    boxas    containing at least 3 valid boxes
 * \param[in]    select   L_ADJUST_LEFT, L_ADJUST_RIGHT, etc.
 * \param[in]    thresh   threshold number of pixels to make adjustment
 * \param[in]    extra    extra pixels to add beyond median value
 * \param[in]    pixadb   use NULL to skip debug output
 * \return  boxad  possibly adjusted from boxas; a copy of boxas on error
 *
 * <pre>
 * Notes:
 *      (1) This modifies individual box sides if their location differs
 *          significantly (>= %thresh) from the median value.
 *      (2) %select specifies which sides are to be checked.
 *      (3) %thresh specifies the tolerance for different side locations.
 *          Any box side that differs from the median by this much will
 *          be set to the median value, plus the %extra amount.
 *      (4) If %extra is positive, the box dimensions are expanded.
 *          For example, for the left side, a positive %extra results in
 *          moving the left side farther to the left (i.e., in a negative
 *          direction).
 *      (5) If all box sides are within %thresh - 1 of the median value,
 *          the returned box will be identical to %boxas.
 *      (6) N.B. If you expect that even and odd box sides should be
 *          significantly different, this function must be called separately
 *          on the even and odd boxes in %boxas.  Note also that the
 *          higher level function boxaReconcileAllByMedian() handles the
 *          even and odd box sides separately.
 * </pre>
 */
\brief   boxaReconcileSidesByMedian()
\param[in]    boxas    containing at least 3 valid boxes
\param[in]    select   L_ADJUST_LEFT, L_ADJUST_RIGHT, etc.
\param[in]    thresh   threshold number of pixels to make adjustment
\param[in]    extra    extra pixels to add beyond median value
\param[in]    pixadb   use NULL to skip debug output
\return  boxad  possibly adjusted from boxas; a copy of boxas on error


Notes:
(1) This modifies individual box sides if their location differs
significantly (>= %thresh) from the median value.
(2) %select specifies which sides are to be checked.
(3) %thresh specifies the tolerance for different side locations.
Any box side that differs from the median by this much will
be set to the median value, plus the %extra amount.
(4) If %extra is positive, the box dimensions are expanded.
For example, for the left side, a positive %extra results in
moving the left side farther to the left .
(5) If all box sides are within %thresh - 1 of the median value,
the returned box will be identical to %boxas.
\ brief boxaReconcileSidesByMedian () \ param [ in ] boxas containing at least 3 valid boxes \ param [ in ] select L_ADJUST_LEFT L_ADJUST_RIGHT etc . \ param [ in ] thresh threshold number of pixels to make adjustment \ param [ in ] extra extra pixels to add beyond median value \ param [ in ] pixadb use NULL to skip debug output \ return boxad possibly adjusted from boxas ; a copy of boxas on error Notes : ( 1 ) This modifies individual box sides if their location differs significantly ( > = %thresh ) from the median value . ( 2 ) %select specifies which sides are to be checked . ( 3 ) %thresh specifies the tolerance for different side locations . Any box side that differs from the median by this much will be set to the median value plus the %extra amount . ( 4 ) If %extra is positive the box dimensions are expanded . For example for the left side a positive %extra results in moving the left side farther to the left . ( 5 ) If all box sides are within %thresh - 1 of the median value the returned box will be identical to %boxas .
BOXA *
boxaReconcileSidesByMedian(BOXA    *boxas,
                           l_int32  select,
                           l_int32  thresh,
                           l_int32  extra,
                           PIXA    *pixadb)
 {
char     buf[128];
l_int32  i, n, diff;
l_int32  left, right, top, bot, medleft, medright, medtop, medbot;
BOX     *box;
BOXA    *boxa1, *boxad;
PIX     *pix;
    PROCNAME("boxaReconcileSidesByMedian");
    if (!boxas)
        return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
    if (select != L_ADJUST_LEFT && select != L_ADJUST_RIGHT &&
        select != L_ADJUST_TOP && select != L_ADJUST_BOT &&
        select != L_ADJUST_LEFT_AND_RIGHT && select != L_ADJUST_TOP_AND_BOT) {
        L_WARNING("invalid select; returning copy\n", procName);
        return boxaCopy(boxas, L_COPY);
    }
    if (thresh < 0) {
        L_WARNING("thresh must be >= 0; returning copy\n", procName);
        return boxaCopy(boxas, L_COPY);
    }
    if (boxaGetValidCount(boxas) < 3) {
        L_WARNING("need at least 3 valid boxes; returning copy\n", procName);
        return boxaCopy(boxas, L_COPY);
    }
    if (select == L_ADJUST_LEFT_AND_RIGHT) {
        boxa1 = boxaReconcileSidesByMedian(boxas, L_ADJUST_LEFT, thresh, extra,
                                           pixadb);
        boxad = boxaReconcileSidesByMedian(boxa1, L_ADJUST_RIGHT, thresh, extra,
                                           pixadb);
        boxaDestroy(&boxa1);
        return boxad;
    }
    if (select == L_ADJUST_TOP_AND_BOT) {
        boxa1 = boxaReconcileSidesByMedian(boxas, L_ADJUST_TOP, thresh, extra,
                                           pixadb);
        boxad = boxaReconcileSidesByMedian(boxa1, L_ADJUST_BOT, thresh, extra,
                                           pixadb);
        boxaDestroy(&boxa1);
        return boxad;
    }
    if (pixadb) {
        l_int32 ndb = pixaGetCount(pixadb);
        if (ndb == 0 || ndb == 5) {  
            adjustSidePlotName(buf, sizeof(buf), "init", select);
            boxaPlotSides(boxas, buf, NULL, NULL, NULL, NULL, &pix);
            pixaAddPix(pixadb, pix, L_INSERT);
        }
    }
    n = boxaGetCount(boxas);
    boxad = boxaCreate(n);
    if (select == L_ADJUST_LEFT) {
        boxaGetMedianVals(boxas, &medleft, NULL, NULL, NULL, NULL, NULL);
        for (i = 0; i < n; i++) {
            box = boxaGetBox(boxas, i, L_COPY);
            boxGetSideLocations(box, &left, NULL, NULL, NULL);
            diff = medleft - left;
            if (L_ABS(diff) >= thresh)
                boxAdjustSides(box, box, diff - extra, 0, 0, 0);
            boxaAddBox(boxad, box, L_INSERT);
        }
    } else if (select == L_ADJUST_RIGHT) {
        boxaGetMedianVals(boxas, NULL, NULL, &medright, NULL, NULL, NULL);
        for (i = 0; i < n; i++) {
            box = boxaGetBox(boxas, i, L_COPY);
            boxGetSideLocations(box, NULL, &right, NULL, NULL);
            diff = medright - right;
            if (L_ABS(diff) >= thresh)
                boxAdjustSides(box, box, 0, diff + extra, 0, 0);
            boxaAddBox(boxad, box, L_INSERT);
        }
    } else if (select == L_ADJUST_TOP) {
        boxaGetMedianVals(boxas, NULL, &medtop, NULL, NULL, NULL, NULL);
        for (i = 0; i < n; i++) {
            box = boxaGetBox(boxas, i, L_COPY);
            boxGetSideLocations(box, NULL, NULL, &top, NULL);
            diff = medtop - top;
            if (L_ABS(diff) >= thresh)
                boxAdjustSides(box, box, 0, 0, diff - extra, 0);
            boxaAddBox(boxad, box, L_INSERT);
        }
    } else {  
        boxaGetMedianVals(boxas, NULL, NULL, NULL, &medbot, NULL, NULL);
        for (i = 0; i < n; i++) {
            box = boxaGetBox(boxas, i, L_COPY);
            boxGetSideLocations(box, NULL, NULL, NULL, &bot);
            diff = medbot - bot;
            if (L_ABS(diff) >= thresh)
                boxAdjustSides(box, box, 0, 0, 0, diff + extra);
            boxaAddBox(boxad, box, L_INSERT);
        }
    }
    if (pixadb) {
        adjustSidePlotName(buf, sizeof(buf), "final", select);
        boxaPlotSides(boxad, buf, NULL, NULL, NULL, NULL, &pix);
        pixaAddPix(pixadb, pix, L_INSERT);
    }
    return boxad;
}
BOXA * boxaReconcileSidesByMedian ( BOXA * boxas , l_int32 select , l_int32 thresh , l_int32 extra , PIXA * pixadb ) { char buf [ 128 ] ; l_int32 i , n , diff ; l_int32 left , right , top , bot , medleft , medright , medtop , medbot ; BOX * box ; BOXA * boxa1 , * boxad ; PIX * pix ; PROCNAME ( " " ) ; if ( ! boxas ) return ( BOXA * ) ERROR_PTR ( " " , procName , NULL ) ; if ( select != L_ADJUST_LEFT && select != L_ADJUST_RIGHT && select != L_ADJUST_TOP && select != L_ADJUST_BOT && select != L_ADJUST_LEFT_AND_RIGHT && select != L_ADJUST_TOP_AND_BOT ) { L_WARNING ( " \n " , procName ) ; return boxaCopy ( boxas , L_COPY ) ; } if ( thresh < 0 ) { L_WARNING ( " \n " , procName ) ; return boxaCopy ( boxas , L_COPY ) ; } if ( boxaGetValidCount ( boxas ) < 3 ) { L_WARNING ( " \n " , procName ) ; return boxaCopy ( boxas , L_COPY ) ; } if ( select == L_ADJUST_LEFT_AND_RIGHT ) { boxa1 = boxaReconcileSidesByMedian ( boxas , L_ADJUST_LEFT , thresh , extra , pixadb ) ; boxad = boxaReconcileSidesByMedian ( boxa1 , L_ADJUST_RIGHT , thresh , extra , pixadb ) ; boxaDestroy ( & boxa1 ) ; return boxad ; } if ( select == L_ADJUST_TOP_AND_BOT ) { boxa1 = boxaReconcileSidesByMedian ( boxas , L_ADJUST_TOP , thresh , extra , pixadb ) ; boxad = boxaReconcileSidesByMedian ( boxa1 , L_ADJUST_BOT , thresh , extra , pixadb ) ; boxaDestroy ( & boxa1 ) ; return boxad ; } if ( pixadb ) { l_int32 ndb = pixaGetCount ( pixadb ) ; if ( ndb == 0 || ndb == 5 ) { adjustSidePlotName ( buf , sizeof ( buf ) , " " , select ) ; boxaPlotSides ( boxas , buf , NULL , NULL , NULL , NULL , & pix ) ; pixaAddPix ( pixadb , pix , L_INSERT ) ; } } n = boxaGetCount ( boxas ) ; boxad = boxaCreate ( n ) ; if ( select == L_ADJUST_LEFT ) { boxaGetMedianVals ( boxas , & medleft , NULL , NULL , NULL , NULL , NULL ) ; for ( i = 0 ; i < n ; i ++ ) { box = boxaGetBox ( boxas , i , L_COPY ) ; boxGetSideLocations ( box , & left , NULL , NULL , NULL ) ; diff = medleft - left ; if ( L_ABS ( diff ) >= thresh ) boxAdjustSides ( box , box , diff - extra , 0 , 0 , 0 ) ; boxaAddBox ( boxad , box , L_INSERT ) ; } } else if ( select == L_ADJUST_RIGHT ) { boxaGetMedianVals ( boxas , NULL , NULL , & medright , NULL , NULL , NULL ) ; for ( i = 0 ; i < n ; i ++ ) { box = boxaGetBox ( boxas , i , L_COPY ) ; boxGetSideLocations ( box , NULL , & right , NULL , NULL ) ; diff = medright - right ; if ( L_ABS ( diff ) >= thresh ) boxAdjustSides ( box , box , 0 , diff + extra , 0 , 0 ) ; boxaAddBox ( boxad , box , L_INSERT ) ; } } else if ( select == L_ADJUST_TOP ) { boxaGetMedianVals ( boxas , NULL , & medtop , NULL , NULL , NULL , NULL ) ; for ( i = 0 ; i < n ; i ++ ) { box = boxaGetBox ( boxas , i , L_COPY ) ; boxGetSideLocations ( box , NULL , NULL , & top , NULL ) ; diff = medtop - top ; if ( L_ABS ( diff ) >= thresh ) boxAdjustSides ( box , box , 0 , 0 , diff - extra , 0 ) ; boxaAddBox ( boxad , box , L_INSERT ) ; } } else { boxaGetMedianVals ( boxas , NULL , NULL , NULL , & medbot , NULL , NULL ) ; for ( i = 0 ; i < n ; i ++ ) { box = boxaGetBox ( boxas , i , L_COPY ) ; boxGetSideLocations ( box , NULL , NULL , NULL , & bot ) ; diff = medbot - bot ; if ( L_ABS ( diff ) >= thresh ) boxAdjustSides ( box , box , 0 , 0 , 0 , diff + extra ) ; boxaAddBox ( boxad , box , L_INSERT ) ; } } if ( pixadb ) { adjustSidePlotName ( buf , sizeof ( buf ) , " " , select ) ; boxaPlotSides ( boxad , buf , NULL , NULL , NULL , NULL , & pix ) ; pixaAddPix ( pixadb , pix , L_INSERT ) ; } return boxad ; }
\brief   boxaReconcileSidesByMedian()
 \param[in]    boxas    containing at least 3 valid boxes
 \param[in]    select   L_ADJUST_LEFT, L_ADJUST_RIGHT, etc.
\ brief boxaReconcileSidesByMedian () \ param [ in ] boxas containing at least 3 valid boxes \ param [ in ] select L_ADJUST_LEFT L_ADJUST_RIGHT etc .
/* first of even and odd box sets */ /* select == L_ADJUST_BOT */