src/boxfunc5.c
BOXA *
boxaSmoothSequenceMedian(BOXA    *boxas,
                         l_int32  halfwin,
                         l_int32  subflag,
                         l_int32  maxdiff,
                         l_int32  extrapixels,
                         l_int32  debug)
{
l_int32  n;
BOXA    *boxae, *boxao, *boxamede, *boxamedo, *boxame, *boxamo, *boxad;
PIX     *pix1;

    PROCNAME("boxaSmoothSequenceMedian");

    if (!boxas)
        return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
    if (halfwin <= 0) {
        L_WARNING("halfwin must be > 0; returning copy\n", procName);
        return boxaCopy(boxas, L_COPY);
    }
    if (maxdiff < 0) {
        L_WARNING("maxdiff must be >= 0; returning copy\n", procName);
        return boxaCopy(boxas, L_COPY);
    }
    if (subflag != L_USE_MINSIZE && subflag != L_USE_MAXSIZE &&
        subflag != L_SUB_ON_LOC_DIFF && subflag != L_SUB_ON_SIZE_DIFF &&
        subflag != L_USE_CAPPED_MIN && subflag != L_USE_CAPPED_MAX) {
        L_WARNING("invalid subflag; returning copy\n", procName);
        return boxaCopy(boxas, L_COPY);
    }
    if ((n = boxaGetCount(boxas)) < 6) {
        L_WARNING("need at least 6 boxes; returning copy\n", procName);
        return boxaCopy(boxas, L_COPY);
    }

    boxaSplitEvenOdd(boxas, 0, &boxae, &boxao);
    if (debug) {
        lept_mkdir("lept/smooth");
        boxaWriteDebug("/tmp/lept/smooth/boxae.ba", boxae);
        boxaWriteDebug("/tmp/lept/smooth/boxao.ba", boxao);
    }

    boxamede = boxaWindowedMedian(boxae, halfwin, debug);
    boxamedo = boxaWindowedMedian(boxao, halfwin, debug);
    if (debug) {
        boxaWriteDebug("/tmp/lept/smooth/boxamede.ba", boxamede);
        boxaWriteDebug("/tmp/lept/smooth/boxamedo.ba", boxamedo);
    }

    boxame = boxaModifyWithBoxa(boxae, boxamede, subflag, maxdiff, extrapixels);
    boxamo = boxaModifyWithBoxa(boxao, boxamedo, subflag, maxdiff, extrapixels);
    if (debug) {
        boxaWriteDebug("/tmp/lept/smooth/boxame.ba", boxame);
        boxaWriteDebug("/tmp/lept/smooth/boxamo.ba", boxamo);
    }

    boxad = boxaMergeEvenOdd(boxame, boxamo, 0);
    if (debug) {
        boxaPlotSides(boxas, NULL, NULL, NULL, NULL, NULL, &pix1);
        pixWrite("/tmp/lept/smooth/plotsides1.png", pix1, IFF_PNG);
        pixDestroy(&pix1);
        boxaPlotSides(boxad, NULL, NULL, NULL, NULL, NULL, &pix1);
        pixWrite("/tmp/lept/smooth/plotsides2.png", pix1, IFF_PNG);
        pixDestroy(&pix1);
        boxaPlotSizes(boxas, NULL, NULL, NULL, &pix1);
        pixWrite("/tmp/lept/smooth/plotsizes1.png", pix1, IFF_PNG);
        pixDestroy(&pix1);
        boxaPlotSizes(boxad, NULL, NULL, NULL, &pix1);
        pixWrite("/tmp/lept/smooth/plotsizes2.png", pix1, IFF_PNG);
        pixDestroy(&pix1);
    }

    boxaDestroy(&boxae);
    boxaDestroy(&boxao);
    boxaDestroy(&boxamede);
    boxaDestroy(&boxamedo);
    boxaDestroy(&boxame);
    boxaDestroy(&boxamo);
    return boxad;
}
/*!
 * \brief   boxaSmoothSequenceMedian()
 *
 * \param[in]    boxas        source boxa
 * \param[in]    halfwin      half-width of sliding window; used to find median
 * \param[in]    subflag      L_USE_MINSIZE, L_USE_MAXSIZE,
 *                            L_SUB_ON_LOC_DIFF, L_SUB_ON_SIZE_DIFF,
 *                            L_USE_CAPPED_MIN, L_USE_CAPPED_MAX
 * \param[in]    maxdiff      parameter used with L_SUB_ON_LOC_DIFF,
 *                            L_SUB_ON_SIZE_DIFF, L_USE_CAPPED_MIN,
 *                            L_USE_CAPPED_MAX
 * \param[in]    extrapixels  pixels added on all sides (or subtracted
 *                            if %extrapixels < 0) when using
 *                            L_SUB_ON_LOC_DIFF and L_SUB_ON_SIZE_DIFF
 * \param[in]    debug        1 for debug output
 * \return  boxad fitted boxa, or NULL on error
 *
 * <pre>
 * Notes:
 *      (1) The target width of the sliding window is 2 * %halfwin + 1.
 *          If necessary, this will be reduced by boxaWindowedMedian().
 *      (2) This returns a modified version of %boxas by constructing
 *          for each input box a box that has been smoothed with windowed
 *          median filtering.  The filtering is done to each of the
 *          box sides independently, and it is computed separately for
 *          sequences of even and odd boxes.  The output %boxad is
 *          constructed from the input boxa and the filtered boxa,
 *          depending on %subflag.  See boxaModifyWithBoxa() for
 *          details on the use of %subflag, %maxdiff and %extrapixels.
 *      (3) This is useful for removing noise separately in the even
 *          and odd sets, where the box edge locations can have
 *          discontinuities but otherwise vary roughly linearly within
 *          intervals of size %halfwin or larger.
 *      (4) If you don't need to handle even and odd sets separately,
 *          just do this:
 *              boxam = boxaWindowedMedian(boxas, halfwin, debug);
 *              boxad = boxaModifyWithBoxa(boxas, boxam, subflag, maxdiff,
 *                                         extrapixels);
 *              boxaDestroy(&boxam);
 * </pre>
 */



Notes:
(1) The target width of the sliding window is 2 * %halfwin + 1.
If necessary, this will be reduced by boxaWindowedMedian().
(2) This returns a modified version of %boxas by constructing
for each input box a box that has been smoothed with windowed
median filtering.  The filtering is done to each of the
box sides independently, and it is computed separately for
sequences of even and odd boxes.  The output %boxad is
constructed from the input boxa and the filtered boxa,
depending on %subflag.  See boxaModifyWithBoxa() for
details on the use of %subflag, %maxdiff and %extrapixels.
(3) This is useful for removing noise separately in the even
and odd sets, where the box edge locations can have
discontinuities but otherwise vary roughly linearly within
intervals of size %halfwin or larger.
(4) If you don't need to handle even and odd sets separately,
just do this:
boxam = boxaWindowedMedian(boxas, halfwin, debug);
boxad = boxaModifyWithBoxa(boxas, boxam, subflag, maxdiff,
extrapixels);
boxaDestroy(&boxam);

Notes : ( 1 ) The target width of the sliding window is 2 * %halfwin + 1 . If necessary this will be reduced by boxaWindowedMedian () . ( 2 ) This returns a modified version of %boxas by constructing for each input box a box that has been smoothed with windowed median filtering . The filtering is done to each of the box sides independently and it is computed separately for sequences of even and odd boxes . The output %boxad is constructed from the input boxa and the filtered boxa depending on %subflag . See boxaModifyWithBoxa () for details on the use of %subflag %maxdiff and %extrapixels . ( 3 ) This is useful for removing noise separately in the even and odd sets where the box edge locations can have discontinuities but otherwise vary roughly linearly within intervals of size %halfwin or larger . ( 4 ) If you don ' t need to handle even and odd sets separately just do this : boxam = boxaWindowedMedian ( boxas halfwin debug ) ; boxad = boxaModifyWithBoxa ( boxas boxam subflag maxdiff extrapixels ) ; boxaDestroy ( &boxam ) ;
BOXA *
boxaSmoothSequenceMedian(BOXA    *boxas,
                         l_int32  halfwin,
                         l_int32  subflag,
                         l_int32  maxdiff,
                         l_int32  extrapixels,
                         l_int32  debug)
{
l_int32  n;
BOXA    *boxae, *boxao, *boxamede, *boxamedo, *boxame, *boxamo, *boxad;
PIX     *pix1;
    PROCNAME("boxaSmoothSequenceMedian");
    if (!boxas)
        return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
    if (halfwin <= 0) {
        L_WARNING("halfwin must be > 0; returning copy\n", procName);
        return boxaCopy(boxas, L_COPY);
    }
    if (maxdiff < 0) {
        L_WARNING("maxdiff must be >= 0; returning copy\n", procName);
        return boxaCopy(boxas, L_COPY);
    }
    if (subflag != L_USE_MINSIZE && subflag != L_USE_MAXSIZE &&
        subflag != L_SUB_ON_LOC_DIFF && subflag != L_SUB_ON_SIZE_DIFF &&
        subflag != L_USE_CAPPED_MIN && subflag != L_USE_CAPPED_MAX) {
        L_WARNING("invalid subflag; returning copy\n", procName);
        return boxaCopy(boxas, L_COPY);
    }
    if ((n = boxaGetCount(boxas)) < 6) {
        L_WARNING("need at least 6 boxes; returning copy\n", procName);
        return boxaCopy(boxas, L_COPY);
    }
    boxaSplitEvenOdd(boxas, 0, &boxae, &boxao);
    if (debug) {
        lept_mkdir("lept/smooth");
        boxaWriteDebug("/tmp/lept/smooth/boxae.ba", boxae);
        boxaWriteDebug("/tmp/lept/smooth/boxao.ba", boxao);
    }
    boxamede = boxaWindowedMedian(boxae, halfwin, debug);
    boxamedo = boxaWindowedMedian(boxao, halfwin, debug);
    if (debug) {
        boxaWriteDebug("/tmp/lept/smooth/boxamede.ba", boxamede);
        boxaWriteDebug("/tmp/lept/smooth/boxamedo.ba", boxamedo);
    }
    boxame = boxaModifyWithBoxa(boxae, boxamede, subflag, maxdiff, extrapixels);
    boxamo = boxaModifyWithBoxa(boxao, boxamedo, subflag, maxdiff, extrapixels);
    if (debug) {
        boxaWriteDebug("/tmp/lept/smooth/boxame.ba", boxame);
        boxaWriteDebug("/tmp/lept/smooth/boxamo.ba", boxamo);
    }
    boxad = boxaMergeEvenOdd(boxame, boxamo, 0);
    if (debug) {
        boxaPlotSides(boxas, NULL, NULL, NULL, NULL, NULL, &pix1);
        pixWrite("/tmp/lept/smooth/plotsides1.png", pix1, IFF_PNG);
        pixDestroy(&pix1);
        boxaPlotSides(boxad, NULL, NULL, NULL, NULL, NULL, &pix1);
        pixWrite("/tmp/lept/smooth/plotsides2.png", pix1, IFF_PNG);
        pixDestroy(&pix1);
        boxaPlotSizes(boxas, NULL, NULL, NULL, &pix1);
        pixWrite("/tmp/lept/smooth/plotsizes1.png", pix1, IFF_PNG);
        pixDestroy(&pix1);
        boxaPlotSizes(boxad, NULL, NULL, NULL, &pix1);
        pixWrite("/tmp/lept/smooth/plotsizes2.png", pix1, IFF_PNG);
        pixDestroy(&pix1);
    }
    boxaDestroy(&boxae);
    boxaDestroy(&boxao);
    boxaDestroy(&boxamede);
    boxaDestroy(&boxamedo);
    boxaDestroy(&boxame);
    boxaDestroy(&boxamo);
    return boxad;
}
BOXA * boxaSmoothSequenceMedian ( BOXA * boxas , l_int32 halfwin , l_int32 subflag , l_int32 maxdiff , l_int32 extrapixels , l_int32 debug ) { l_int32 n ; BOXA * boxae , * boxao , * boxamede , * boxamedo , * boxame , * boxamo , * boxad ; PIX * pix1 ; PROCNAME ( " " ) ; if ( ! boxas ) return ( BOXA * ) ERROR_PTR ( " " , procName , NULL ) ; if ( halfwin <= 0 ) { L_WARNING ( " \n " , procName ) ; return boxaCopy ( boxas , L_COPY ) ; } if ( maxdiff < 0 ) { L_WARNING ( " \n " , procName ) ; return boxaCopy ( boxas , L_COPY ) ; } if ( subflag != L_USE_MINSIZE && subflag != L_USE_MAXSIZE && subflag != L_SUB_ON_LOC_DIFF && subflag != L_SUB_ON_SIZE_DIFF && subflag != L_USE_CAPPED_MIN && subflag != L_USE_CAPPED_MAX ) { L_WARNING ( " \n " , procName ) ; return boxaCopy ( boxas , L_COPY ) ; } if ( ( n = boxaGetCount ( boxas ) ) < 6 ) { L_WARNING ( " \n " , procName ) ; return boxaCopy ( boxas , L_COPY ) ; } boxaSplitEvenOdd ( boxas , 0 , & boxae , & boxao ) ; if ( debug ) { lept_mkdir ( " " ) ; boxaWriteDebug ( " " , boxae ) ; boxaWriteDebug ( " " , boxao ) ; } boxamede = boxaWindowedMedian ( boxae , halfwin , debug ) ; boxamedo = boxaWindowedMedian ( boxao , halfwin , debug ) ; if ( debug ) { boxaWriteDebug ( " " , boxamede ) ; boxaWriteDebug ( " " , boxamedo ) ; } boxame = boxaModifyWithBoxa ( boxae , boxamede , subflag , maxdiff , extrapixels ) ; boxamo = boxaModifyWithBoxa ( boxao , boxamedo , subflag , maxdiff , extrapixels ) ; if ( debug ) { boxaWriteDebug ( " " , boxame ) ; boxaWriteDebug ( " " , boxamo ) ; } boxad = boxaMergeEvenOdd ( boxame , boxamo , 0 ) ; if ( debug ) { boxaPlotSides ( boxas , NULL , NULL , NULL , NULL , NULL , & pix1 ) ; pixWrite ( " " , pix1 , IFF_PNG ) ; pixDestroy ( & pix1 ) ; boxaPlotSides ( boxad , NULL , NULL , NULL , NULL , NULL , & pix1 ) ; pixWrite ( " " , pix1 , IFF_PNG ) ; pixDestroy ( & pix1 ) ; boxaPlotSizes ( boxas , NULL , NULL , NULL , & pix1 ) ; pixWrite ( " " , pix1 , IFF_PNG ) ; pixDestroy ( & pix1 ) ; boxaPlotSizes ( boxad , NULL , NULL , NULL , & pix1 ) ; pixWrite ( " " , pix1 , IFF_PNG ) ; pixDestroy ( & pix1 ) ; } boxaDestroy ( & boxae ) ; boxaDestroy ( & boxao ) ; boxaDestroy ( & boxamede ) ; boxaDestroy ( & boxamedo ) ; boxaDestroy ( & boxame ) ; boxaDestroy ( & boxamo ) ; return boxad ; }
\brief   boxaSmoothSequenceMedian()
 \param[in]    boxas        source boxa
 \param[in]    halfwin      half-width of sliding window; used to find median
 \param[in]    subflag      L_USE_MINSIZE, L_USE_MAXSIZE,
                            L_SUB_ON_LOC_DIFF, L_SUB_ON_SIZE_DIFF,
                            L_USE_CAPPED_MIN, L_USE_CAPPED_MAX
 \param[in]    maxdiff      parameter used with L_SUB_ON_LOC_DIFF,
                            L_SUB_ON_SIZE_DIFF, L_USE_CAPPED_MIN,
                            L_USE_CAPPED_MAX
 \param[in]    extrapixels  pixels added on all sides (or subtracted
                            if %extrapixels < 0) when using
                            L_SUB_ON_LOC_DIFF and L_SUB_ON_SIZE_DIFF
 \param[in]    debug        1 for debug output
 \return  boxad fitted boxa, or NULL on error
\ brief boxaSmoothSequenceMedian () \ param [ in ] boxas source boxa \ param [ in ] halfwin half - width of sliding window ; used to find median \ param [ in ] subflag L_USE_MINSIZE L_USE_MAXSIZE L_SUB_ON_LOC_DIFF L_SUB_ON_SIZE_DIFF L_USE_CAPPED_MIN L_USE_CAPPED_MAX \ param [ in ] maxdiff parameter used with L_SUB_ON_LOC_DIFF L_SUB_ON_SIZE_DIFF L_USE_CAPPED_MIN L_USE_CAPPED_MAX \ param [ in ] extrapixels pixels added on all sides ( or subtracted if %extrapixels < 0 ) when using L_SUB_ON_LOC_DIFF and L_SUB_ON_SIZE_DIFF \ param [ in ] debug 1 for debug output \ return boxad fitted boxa or NULL on error