src/boxfunc5.c
l_ok
boxaSizeConsistency2(BOXA       *boxas,
                     l_float32  *pfdevw,
                     l_float32  *pfdevh,
                     l_int32     debug)
{
l_int32    i, n, bw1, bh1, bw2, bh2, npairs;
l_float32  medw, medh, devw, devh, minw, maxw, minh, w;
BOX       *box;
BOXA      *boxa1;
NUMA      *naw, *nah;
PIX       *pix1, *pix2, *pix3;
PIXA      *pixa;

    PROCNAME("boxaSizeConsistency2");

    if (pfdevw) *pfdevw = 0.0;
    if (pfdevh) *pfdevh = 0.0;
    if (!boxas)
        return ERROR_INT("boxas not defined", procName, 1);
    if (!pfdevw || !pfdevh)
        return ERROR_INT("&fdevw and &fdevh not both defined", procName, 1);
    n = boxaGetCount(boxas);
    if (n < 10) {
        L_WARNING("small boxa; assuming OK", procName);
        return 0;
    }

        /* Regularize w and h in pairs; skip last box if n is odd */
    boxa1 = (debug) ? boxaCreate(n) : NULL;
    naw = numaCreate(0);
    nah = numaCreate(0);
    for (i = 0, npairs = 0; i < n - 1; i += 2) {
        boxaGetBoxGeometry(boxas, i, NULL, NULL, &bw1, &bh1);
        boxaGetBoxGeometry(boxas, i + 1, NULL, NULL, &bw2, &bh2);
        if (bw1 == 0 || bh1 == 0 || bw2 == 0 || bh2 == 0)
            continue;
        npairs++;
        minw = (l_float32)L_MIN(bw1, bw2);
        maxw = (l_float32)L_MAX(bw1, bw2);
        minh = (l_float32)L_MIN(bh1, bh2);
        w = (minw / minh > 0.5) ? minw : maxw;
        numaAddNumber(naw, w);
        numaAddNumber(nah, minh);
        if (debug) {
            box = boxCreate(0, 0, w, minh);
            boxaAddBox(boxa1, box, L_COPY);
            boxaAddBox(boxa1, box, L_INSERT);
        }
    }
    if (npairs == 0) {
        L_WARNING("no valid box pairs\n", procName);
        numaDestroy(&naw);
        numaDestroy(&nah);
        boxaDestroy(&boxa1);
    }

        /* Get the median value of the regularized sizes, and find
         * the average absolute fractional deviation from the median. */
    numaGetMedian(naw, &medw);
    numaGetMedian(nah, &medh);
    numaGetMeanDevFromMedian(naw, medw, &devw);
    numaGetMeanDevFromMedian(nah, medh, &devh);
    *pfdevw = devw / medw;
    *pfdevh = devh / medh;
    if (debug) {
        lept_stderr("medw = %5.1f, medh = %5.1f\n", medw, medh);
        lept_stderr("fdevw = %6.3f, fdevh = %6.3f\n", *pfdevw, *pfdevh);
        boxaPlotSizes(boxas, "input_boxa", NULL, NULL, &pix1);
        boxaPlotSizes(boxa1, "regularized_boxa", NULL, NULL, &pix2);
        pixDisplay(pix1, 500, 0);
        pixDisplay(pix2, 500, 1000);
        pixa = pixaCreate(2);
        pixaAddPix(pixa, pix1, L_INSERT);
        pixaAddPix(pixa, pix2, L_INSERT);
        pix3 = pixaDisplayTiledInColumns(pixa, 2, 1.0, 3, 2);
        lept_mkdir("lept/boxa");
        pixWrite("/tmp/lept/boxa/eval.png", pix3, IFF_PNG);
        pixDisplay(pix3, 100, 100);
        pixDestroy(&pix3);
        pixaDestroy(&pixa);
        boxaDestroy(&boxa1);
    }

    numaDestroy(&naw);
    numaDestroy(&nah);
    return 0;
}
/*!
 * \brief   boxaSizeConsistency2()
 *
 * \param[in]    boxas     of size >= 10
 * \param[out]   pfdevw    average fractional deviation from median width
 * \param[out]   pfdevh    average fractional deviation from median height
 * \param[in]    debug     1 for debug plot output of input and regularized
 *                         width and height
 *
 * <pre>
 * Notes:
 *      (1) This evaluates a boxa for consistency of the box sizes.
 *          The intended application is that the boxes are a sequence of
 *          page regions in a book scan, and the output is a decision
 *          about whether the pages should be approximately the same size.
 *          The determination should be robust to outliers, both random
 *          and (for many cases) systematic.
 *      (2) This differs from boxaSizeConsistency1() in that it attempts
 *          to correct for box dimensional errors before doing the
 *          evaluation.  For this reason, it may be less robust.
 *      (3) Adjacent even and odd boxes are expected to be the same size.
 *          Take them pairwise, and assume the minimum height, hmin,
 *          is correct.  Then for (the usual case) wmin/hmin > 0.5, assume
 *          the minimum width is correct.  If wmin/hmin <= 0.5, assume
 *          the maximum width is correct.
 *      (4) After correcting each pair so that they are the same size,
 *          compute the average fractional deviation, from median width and
 *          height.  A deviation of width or height by more than about
 *          0.02 is evidence that the boxes may be from a non-homogeneous
 *          source, such as a book with significantly different page sizes.
 * </pre>
 */



Notes:
(1) This evaluates a boxa for consistency of the box sizes.
The intended application is that the boxes are a sequence of
page regions in a book scan, and the output is a decision
about whether the pages should be approximately the same size.
The determination should be robust to outliers, both random
and (for many cases) systematic.
(2) This differs from boxaSizeConsistency1() in that it attempts
to correct for box dimensional errors before doing the
evaluation.  For this reason, it may be less robust.
(3) Adjacent even and odd boxes are expected to be the same size.
Take them pairwise, and assume the minimum height, hmin,
is correct.  Then for (the usual case) wmin/hmin > 0.5, assume
the minimum width is correct.  If wmin/hmin <= 0.5, assume
the maximum width is correct.
(4) After correcting each pair so that they are the same size,
compute the average fractional deviation, from median width and
height.  A deviation of width or height by more than about
0.02 is evidence that the boxes may be from a non-homogeneous
source, such as a book with significantly different page sizes.
Notes : ( 1 ) This evaluates a boxa for consistency of the box sizes . The intended application is that the boxes are a sequence of page regions in a book scan and the output is a decision about whether the pages should be approximately the same size . The determination should be robust to outliers both random and ( for many cases ) systematic . ( 2 ) This differs from boxaSizeConsistency1 () in that it attempts to correct for box dimensional errors before doing the evaluation . For this reason it may be less robust . ( 3 ) Adjacent even and odd boxes are expected to be the same size . Take them pairwise and assume the minimum height hmin is correct . Then for ( the usual case ) wmin / hmin > 0 . 5 assume the minimum width is correct . If wmin / hmin < = 0 . 5 assume the maximum width is correct . ( 4 ) After correcting each pair so that they are the same size compute the average fractional deviation from median width and height . A deviation of width or height by more than about 0 . 02 is evidence that the boxes may be from a non - homogeneous source such as a book with significantly different page sizes .
l_ok
boxaSizeConsistency2(BOXA       *boxas,
                     l_float32  *pfdevw,
                     l_float32  *pfdevh,
                     l_int32     debug)
{
l_int32    i, n, bw1, bh1, bw2, bh2, npairs;
l_float32  medw, medh, devw, devh, minw, maxw, minh, w;
BOX       *box;
BOXA      *boxa1;
NUMA      *naw, *nah;
PIX       *pix1, *pix2, *pix3;
PIXA      *pixa;
    PROCNAME("boxaSizeConsistency2");
    if (pfdevw) *pfdevw = 0.0;
    if (pfdevh) *pfdevh = 0.0;
    if (!boxas)
        return ERROR_INT("boxas not defined", procName, 1);
    if (!pfdevw || !pfdevh)
        return ERROR_INT("&fdevw and &fdevh not both defined", procName, 1);
    n = boxaGetCount(boxas);
    if (n < 10) {
        L_WARNING("small boxa; assuming OK", procName);
        return 0;
    }
    boxa1 = (debug) ? boxaCreate(n) : NULL;
    naw = numaCreate(0);
    nah = numaCreate(0);
    for (i = 0, npairs = 0; i < n - 1; i += 2) {
        boxaGetBoxGeometry(boxas, i, NULL, NULL, &bw1, &bh1);
        boxaGetBoxGeometry(boxas, i + 1, NULL, NULL, &bw2, &bh2);
        if (bw1 == 0 || bh1 == 0 || bw2 == 0 || bh2 == 0)
            continue;
        npairs++;
        minw = (l_float32)L_MIN(bw1, bw2);
        maxw = (l_float32)L_MAX(bw1, bw2);
        minh = (l_float32)L_MIN(bh1, bh2);
        w = (minw / minh > 0.5) ? minw : maxw;
        numaAddNumber(naw, w);
        numaAddNumber(nah, minh);
        if (debug) {
            box = boxCreate(0, 0, w, minh);
            boxaAddBox(boxa1, box, L_COPY);
            boxaAddBox(boxa1, box, L_INSERT);
        }
    }
    if (npairs == 0) {
        L_WARNING("no valid box pairs\n", procName);
        numaDestroy(&naw);
        numaDestroy(&nah);
        boxaDestroy(&boxa1);
    }
    numaGetMedian(naw, &medw);
    numaGetMedian(nah, &medh);
    numaGetMeanDevFromMedian(naw, medw, &devw);
    numaGetMeanDevFromMedian(nah, medh, &devh);
    *pfdevw = devw / medw;
    *pfdevh = devh / medh;
    if (debug) {
        lept_stderr("medw = %5.1f, medh = %5.1f\n", medw, medh);
        lept_stderr("fdevw = %6.3f, fdevh = %6.3f\n", *pfdevw, *pfdevh);
        boxaPlotSizes(boxas, "input_boxa", NULL, NULL, &pix1);
        boxaPlotSizes(boxa1, "regularized_boxa", NULL, NULL, &pix2);
        pixDisplay(pix1, 500, 0);
        pixDisplay(pix2, 500, 1000);
        pixa = pixaCreate(2);
        pixaAddPix(pixa, pix1, L_INSERT);
        pixaAddPix(pixa, pix2, L_INSERT);
        pix3 = pixaDisplayTiledInColumns(pixa, 2, 1.0, 3, 2);
        lept_mkdir("lept/boxa");
        pixWrite("/tmp/lept/boxa/eval.png", pix3, IFF_PNG);
        pixDisplay(pix3, 100, 100);
        pixDestroy(&pix3);
        pixaDestroy(&pixa);
        boxaDestroy(&boxa1);
    }
    numaDestroy(&naw);
    numaDestroy(&nah);
    return 0;
}
l_ok boxaSizeConsistency2 ( BOXA * boxas , l_float32 * pfdevw , l_float32 * pfdevh , l_int32 debug ) { l_int32 i , n , bw1 , bh1 , bw2 , bh2 , npairs ; l_float32 medw , medh , devw , devh , minw , maxw , minh , w ; BOX * box ; BOXA * boxa1 ; NUMA * naw , * nah ; PIX * pix1 , * pix2 , * pix3 ; PIXA * pixa ; PROCNAME ( " " ) ; if ( pfdevw ) * pfdevw = 0.0 ; if ( pfdevh ) * pfdevh = 0.0 ; if ( ! boxas ) return ERROR_INT ( " " , procName , 1 ) ; if ( ! pfdevw || ! pfdevh ) return ERROR_INT ( " " , procName , 1 ) ; n = boxaGetCount ( boxas ) ; if ( n < 10 ) { L_WARNING ( " " , procName ) ; return 0 ; } boxa1 = ( debug ) ? boxaCreate ( n ) : NULL ; naw = numaCreate ( 0 ) ; nah = numaCreate ( 0 ) ; for ( i = 0 , npairs = 0 ; i < n - 1 ; i += 2 ) { boxaGetBoxGeometry ( boxas , i , NULL , NULL , & bw1 , & bh1 ) ; boxaGetBoxGeometry ( boxas , i + 1 , NULL , NULL , & bw2 , & bh2 ) ; if ( bw1 == 0 || bh1 == 0 || bw2 == 0 || bh2 == 0 ) continue ; npairs ++ ; minw = ( l_float32 ) L_MIN ( bw1 , bw2 ) ; maxw = ( l_float32 ) L_MAX ( bw1 , bw2 ) ; minh = ( l_float32 ) L_MIN ( bh1 , bh2 ) ; w = ( minw / minh > 0.5 ) ? minw : maxw ; numaAddNumber ( naw , w ) ; numaAddNumber ( nah , minh ) ; if ( debug ) { box = boxCreate ( 0 , 0 , w , minh ) ; boxaAddBox ( boxa1 , box , L_COPY ) ; boxaAddBox ( boxa1 , box , L_INSERT ) ; } } if ( npairs == 0 ) { L_WARNING ( " \n " , procName ) ; numaDestroy ( & naw ) ; numaDestroy ( & nah ) ; boxaDestroy ( & boxa1 ) ; } numaGetMedian ( naw , & medw ) ; numaGetMedian ( nah , & medh ) ; numaGetMeanDevFromMedian ( naw , medw , & devw ) ; numaGetMeanDevFromMedian ( nah , medh , & devh ) ; * pfdevw = devw / medw ; * pfdevh = devh / medh ; if ( debug ) { lept_stderr ( " \n " , medw , medh ) ; lept_stderr ( " \n " , * pfdevw , * pfdevh ) ; boxaPlotSizes ( boxas , " " , NULL , NULL , & pix1 ) ; boxaPlotSizes ( boxa1 , " " , NULL , NULL , & pix2 ) ; pixDisplay ( pix1 , 500 , 0 ) ; pixDisplay ( pix2 , 500 , 1000 ) ; pixa = pixaCreate ( 2 ) ; pixaAddPix ( pixa , pix1 , L_INSERT ) ; pixaAddPix ( pixa , pix2 , L_INSERT ) ; pix3 = pixaDisplayTiledInColumns ( pixa , 2 , 1.0 , 3 , 2 ) ; lept_mkdir ( " " ) ; pixWrite ( " " , pix3 , IFF_PNG ) ; pixDisplay ( pix3 , 100 , 100 ) ; pixDestroy ( & pix3 ) ; pixaDestroy ( & pixa ) ; boxaDestroy ( & boxa1 ) ; } numaDestroy ( & naw ) ; numaDestroy ( & nah ) ; return 0 ; }
\brief   boxaSizeConsistency2()
 \param[in]    boxas     of size >= 10
 \param[out]   pfdevw    average fractional deviation from median width
 \param[out]   pfdevh    average fractional deviation from median height
 \param[in]    debug     1 for debug plot output of input and regularized
                         width and height
\ brief boxaSizeConsistency2 () \ param [ in ] boxas of size > = 10 \ param [ out ] pfdevw average fractional deviation from median width \ param [ out ] pfdevh average fractional deviation from median height \ param [ in ] debug 1 for debug plot output of input and regularized width and height
/* Regularize w and h in pairs; skip last box if n is odd */ /* Get the median value of the regularized sizes, and find
         * the average absolute fractional deviation from the median. */