src/dewarp.c
PTAA *
pixGetTextlineCenters(PIX     *pixs,
                      l_int32  debugflag)
{
l_int32   i, w, h, bx, by, nsegs;
BOXA     *boxa;
PIX      *pix, *pixt1, *pixt2, *pixt3;
PIXA     *pixa1, *pixa2;
PTA      *pta;
PTAA     *ptaa;

    PROCNAME("pixGetTextlineCenters");

    if (!pixs || pixGetDepth(pixs) != 1)
        return (PTAA *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
    pixGetDimensions(pixs, &w, &h, NULL);

        /* Filter to solidify the text lines within the x-height region,
         * and to remove most of the ascenders and descenders. */
    pixt1 = pixMorphSequence(pixs, "c15.1 + o15.1 + c30.1", 0);
    pixDisplayWithTitle(pixt1, 0, 800, "pix1", debugflag);

        /* Get the 8-connected components ... */
    boxa = pixConnComp(pixt1, &pixa1, 8);
    pixDestroy(&pixt1);
    boxaDestroy(&boxa);
    if (pixaGetCount(pixa1) == 0) {
        pixaDestroy(&pixa1);
        return NULL;
    }

        /* ... and remove the short and thin c.c */
    pixa2 = pixaSelectBySize(pixa1, 100, 4, L_SELECT_IF_BOTH,
                                   L_SELECT_IF_GT, 0);
    if ((nsegs = pixaGetCount(pixa2)) == 0) {
        pixaDestroy(&pixa2);
        return NULL;
    }
    if (debugflag) {
        pixt2 = pixaDisplay(pixa2, w, h);
        pixDisplayWithTitle(pixt2, 800, 800, "pix2", 1);
        pixDestroy(&pixt2);
    }

        /* For each c.c., get the weighted center of each vertical column.
         * The result is a set of points going approximately through
         * the center of the x-height part of the text line.  */
    ptaa = ptaaCreate(nsegs);
    for (i = 0; i < nsegs; i++) {
        pixaGetBoxGeometry(pixa2, i, &bx, &by, NULL, NULL);
        pix = pixaGetPix(pixa2, i, L_CLONE);
        pta = pixGetMeanVerticals(pix, bx, by);
        ptaaAddPta(ptaa, pta, L_INSERT);
        pixDestroy(&pix);
    }
    if (debugflag) {
        pixt3 = pixCreateTemplate(pixt2);
        pix = pixDisplayPtaa(pixt3, ptaa);
        pixDisplayWithTitle(pix, 0, 1400, "pix3", 1);
        pixDestroy(&pix);
        pixDestroy(&pixt3);
    }

    pixaDestroy(&pixa1);
    pixaDestroy(&pixa2);
    return ptaa;
}
/*!
 *  pixGetTextlineCenters()
 *
 *      Input:  pixs (1 bpp)
 *              debugflag (1 for debug output)
 *      Return: ptaa (of center values of textlines)
 *
 *  Notes:
 *      (1) This in general does not have a point for each value
 *          of x, because there will be gaps between words.
 *          It doesn't matter because we will fit a quadratic to the
 *          points that we do have.
 */
pixGetTextlineCenters()
Input:  pixs (1 bpp)
debugflag (1 for debug output)
Return: ptaa (of center values of textlines)

(1) This in general does not have a point for each value
of x, because there will be gaps between words.
It doesn't matter because we will fit a quadratic to the
points that we do have.
pixGetTextlineCenters () Input : pixs ( 1 bpp ) debugflag ( 1 for debug output ) Return : ptaa ( of center values of textlines ) ( 1 ) This in general does not have a point for each value of x because there will be gaps between words . It doesn ' t matter because we will fit a quadratic to the points that we do have .
PTAA *
pixGetTextlineCenters(PIX     *pixs,
                      l_int32  debugflag)
{
l_int32   i, w, h, bx, by, nsegs;
BOXA     *boxa;
PIX      *pix, *pixt1, *pixt2, *pixt3;
PIXA     *pixa1, *pixa2;
PTA      *pta;
PTAA     *ptaa;
    PROCNAME("pixGetTextlineCenters");
    if (!pixs || pixGetDepth(pixs) != 1)
        return (PTAA *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
    pixGetDimensions(pixs, &w, &h, NULL);
    pixt1 = pixMorphSequence(pixs, "c15.1 + o15.1 + c30.1", 0);
    pixDisplayWithTitle(pixt1, 0, 800, "pix1", debugflag);
    boxa = pixConnComp(pixt1, &pixa1, 8);
    pixDestroy(&pixt1);
    boxaDestroy(&boxa);
    if (pixaGetCount(pixa1) == 0) {
        pixaDestroy(&pixa1);
        return NULL;
    }
    pixa2 = pixaSelectBySize(pixa1, 100, 4, L_SELECT_IF_BOTH,
                                   L_SELECT_IF_GT, 0);
    if ((nsegs = pixaGetCount(pixa2)) == 0) {
        pixaDestroy(&pixa2);
        return NULL;
    }
    if (debugflag) {
        pixt2 = pixaDisplay(pixa2, w, h);
        pixDisplayWithTitle(pixt2, 800, 800, "pix2", 1);
        pixDestroy(&pixt2);
    }
    ptaa = ptaaCreate(nsegs);
    for (i = 0; i < nsegs; i++) {
        pixaGetBoxGeometry(pixa2, i, &bx, &by, NULL, NULL);
        pix = pixaGetPix(pixa2, i, L_CLONE);
        pta = pixGetMeanVerticals(pix, bx, by);
        ptaaAddPta(ptaa, pta, L_INSERT);
        pixDestroy(&pix);
    }
    if (debugflag) {
        pixt3 = pixCreateTemplate(pixt2);
        pix = pixDisplayPtaa(pixt3, ptaa);
        pixDisplayWithTitle(pix, 0, 1400, "pix3", 1);
        pixDestroy(&pix);
        pixDestroy(&pixt3);
    }
    pixaDestroy(&pixa1);
    pixaDestroy(&pixa2);
    return ptaa;
}
PTAA * pixGetTextlineCenters ( PIX * pixs , l_int32 debugflag ) { l_int32 i , w , h , bx , by , nsegs ; BOXA * boxa ; PIX * pix , * pixt1 , * pixt2 , * pixt3 ; PIXA * pixa1 , * pixa2 ; PTA * pta ; PTAA * ptaa ; PROCNAME ( " " ) ; if ( ! pixs || pixGetDepth ( pixs ) != 1 ) return ( PTAA * ) ERROR_PTR ( " " , procName , NULL ) ; pixGetDimensions ( pixs , & w , & h , NULL ) ; pixt1 = pixMorphSequence ( pixs , " " , 0 ) ; pixDisplayWithTitle ( pixt1 , 0 , 800 , " " , debugflag ) ; boxa = pixConnComp ( pixt1 , & pixa1 , 8 ) ; pixDestroy ( & pixt1 ) ; boxaDestroy ( & boxa ) ; if ( pixaGetCount ( pixa1 ) == 0 ) { pixaDestroy ( & pixa1 ) ; return NULL ; } pixa2 = pixaSelectBySize ( pixa1 , 100 , 4 , L_SELECT_IF_BOTH , L_SELECT_IF_GT , 0 ) ; if ( ( nsegs = pixaGetCount ( pixa2 ) ) == 0 ) { pixaDestroy ( & pixa2 ) ; return NULL ; } if ( debugflag ) { pixt2 = pixaDisplay ( pixa2 , w , h ) ; pixDisplayWithTitle ( pixt2 , 800 , 800 , " " , 1 ) ; pixDestroy ( & pixt2 ) ; } ptaa = ptaaCreate ( nsegs ) ; for ( i = 0 ; i < nsegs ; i ++ ) { pixaGetBoxGeometry ( pixa2 , i , & bx , & by , NULL , NULL ) ; pix = pixaGetPix ( pixa2 , i , L_CLONE ) ; pta = pixGetMeanVerticals ( pix , bx , by ) ; ptaaAddPta ( ptaa , pta , L_INSERT ) ; pixDestroy ( & pix ) ; } if ( debugflag ) { pixt3 = pixCreateTemplate ( pixt2 ) ; pix = pixDisplayPtaa ( pixt3 , ptaa ) ; pixDisplayWithTitle ( pix , 0 , 1400 , " " , 1 ) ; pixDestroy ( & pix ) ; pixDestroy ( & pixt3 ) ; } pixaDestroy ( & pixa1 ) ; pixaDestroy ( & pixa2 ) ; return ptaa ; }
pixGetTextlineCenters()
      Input:  pixs (1 bpp)
              debugflag (1 for debug output)
      Return: ptaa (of center values of textlines)
pixGetTextlineCenters () Input : pixs ( 1 bpp ) debugflag ( 1 for debug output ) Return : ptaa ( of center values of textlines )
/* Filter to solidify the text lines within the x-height region,
         * and to remove most of the ascenders and descenders. */ /* Get the 8-connected components ... */ /* ... and remove the short and thin c.c */ /* For each c.c., get the weighted center of each vertical column.
         * The result is a set of points going approximately through
         * the center of the x-height part of the text line.  */