Пример #1
0
int main(int argc,
         char **argv) {
    l_int32 w, d, tilewidth;
    PIX *pixs;
    PIXA *pixa, *pixad1, *pixad2;
    PIXAA *pixaa1, *pixaa2;
    static char mainName[] = "pixaatest";

    if (argc != 1)
        return ERROR_INT(" Syntax: pixaatest", mainName, 1);

    /* Read in file, split it into a set of tiles, and generate a pdf.
     * Two things to note for these tiny images:
     *  (1) If you use dct format (jpeg) for each image instead of
     *      flate (lossless), the quantization will be apparent.
     *  (2) If the resolution in pixaConvertToPdf() is above 50, and
     *      you add a red boundary, you will see errors in the boundary
     *      width.
     */
    pixs = pixRead("test24.jpg");
    pixGetDimensions(pixs, &w, NULL, &d);
    pixa = pixaSplitPix(pixs, nx, ny, 0, 0);
/*    pixa = pixaSplitPix(pixs, nx, ny, 2, 0xff000000);  */ /* red border */
    pixWrite("/tmp/junk0", pixa->pix[0], IFF_PNG);
    pixWrite("/tmp/junk9", pixa->pix[9], IFF_PNG);
    pixaConvertToPdf(pixa, 50, 1.0, 0, 95, "individual", "/tmp/junkout0.pdf");

    /* Generate two pixaa by sampling the pixa, and write them to file */
    pixaa1 = pixaaCreateFromPixa(pixa, nx, L_CHOOSE_CONSECUTIVE, L_CLONE);
    pixaa2 = pixaaCreateFromPixa(pixa, nx, L_CHOOSE_SKIP_BY, L_CLONE);
    pixaaWrite("/tmp/pixaa1.paa", pixaa1);
    pixaaWrite("/tmp/pixaa2.paa", pixaa2);
    pixaDestroy(&pixa);
    pixaaDestroy(&pixaa1);
    pixaaDestroy(&pixaa2);

    /* Read each pixaa from file; tile/scale into a pixa */
    pixaa1 = pixaaRead("/tmp/pixaa1.paa");
    pixaa2 = pixaaRead("/tmp/pixaa2.paa");
    tilewidth = w / nx;
    pixad1 = pixaaDisplayTiledAndScaled(pixaa1, d, tilewidth, ncols, 0, 10, 0);
    pixad2 = pixaaDisplayTiledAndScaled(pixaa2, d, tilewidth, ncols, 0, 10, 0);

    /* Generate a pdf from each pixa */
    pixaConvertToPdf(pixad1, 50, 1.0, 0, 75, "consecutive", "/tmp/junkout1.pdf");
    pixaConvertToPdf(pixad2, 50, 1.0, 0, 75, "skip_by", "/tmp/junkout2.pdf");

    /* Write each pixa to a set of files, and generate a PS */
    pixaWriteFiles("/tmp/junksplit1.", pixad1, IFF_JFIF_JPEG);
    pixaWriteFiles("/tmp/junksplit2.", pixad2, IFF_JFIF_JPEG);
    convertFilesToPS("/tmp", "junksplit1", 40, "/tmp/junkout1.ps");
    convertFilesToPS("/tmp", "junksplit2", 40, "/tmp/junkout2.ps");

    pixDestroy(&pixs);
    pixaaDestroy(&pixaa1);
    pixaaDestroy(&pixaa2);
    pixaDestroy(&pixad1);
    pixaDestroy(&pixad2);
    return 0;
}
Пример #2
0
/*!
 *  recogDestroy()
 *
 *      Input:  &recog (<will be set to null before returning>)
 *      Return: void
 *
 *  Notes:
 *      (1) If a recog has a parent, the parent owns it.  A recogDestroy()
 *          will fail if there is a parent.
 */
void
recogDestroy(L_RECOG  **precog)
{
L_RECOG  *recog;

    PROCNAME("recogDestroy");

    if (!precog) {
        L_WARNING("ptr address is null\n", procName);
        return;
    }

    if ((recog = *precog) == NULL) return;
    if (recogGetParent(recog) != NULL) {
        L_ERROR("recog has parent; can't be destroyed\n", procName);
        return;
    }

    FREE(recog->bootdir);
    FREE(recog->bootpattern);
    FREE(recog->bootpath);
    FREE(recog->centtab);
    FREE(recog->sumtab);
    FREE(recog->fname);
    sarrayDestroy(&recog->sa_text);
    l_dnaDestroy(&recog->dna_tochar);
    pixaaDestroy(&recog->pixaa_u);
    pixaDestroy(&recog->pixa_u);
    ptaaDestroy(&recog->ptaa_u);
    ptaDestroy(&recog->pta_u);
    numaDestroy(&recog->nasum_u);
    numaaDestroy(&recog->naasum_u);
    pixaaDestroy(&recog->pixaa);
    pixaDestroy(&recog->pixa);
    ptaaDestroy(&recog->ptaa);
    ptaDestroy(&recog->pta);
    numaDestroy(&recog->nasum);
    numaaDestroy(&recog->naasum);
    pixaDestroy(&recog->pixa_tr);
    pixaDestroy(&recog->pixadb_ave);
    pixaDestroy(&recog->pixa_id);
    pixDestroy(&recog->pixdb_ave);
    pixDestroy(&recog->pixdb_range);
    pixaDestroy(&recog->pixadb_boot);
    pixaDestroy(&recog->pixadb_split);
    FREE(recog->fontdir);
    bmfDestroy(&recog->bmf);
    rchDestroy(&recog->rch);
    rchaDestroy(&recog->rcha);
    recogDestroyDid(recog);
    FREE(recog);
    *precog = NULL;
    return;
}
Пример #3
0
/*!
 *  recogaWritePixaa()
 *
 *      Input:  filename
 *              recoga
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) For each recognizer, this generates a pixa of all the
 *          unscaled images.  They are combined into a pixaa for
 *          the set of recognizers.  Each pix has has its character
 *          string in the pix text field.
 *      (2) As a side-effect, the character class label is written
 *          into each pix in recog.
 */
l_int32
recogaWritePixaa(const char  *filename,
                 L_RECOGA    *recoga)
{
l_int32   i;
PIXA     *pixa;
PIXAA    *paa;
L_RECOG  *recog;

    PROCNAME("recogaWritePixaa");

    if (!filename)
        return ERROR_INT("filename not defined", procName, 1);
    if (!recoga)
        return ERROR_INT("recoga not defined", procName, 1);

    paa = pixaaCreate(recoga->n);
    for (i = 0; i < recoga->n; i++) {
        recog = recogaGetRecog(recoga, i);
        recogAddCharstrLabels(recog);
        pixa = pixaaFlattenToPixa(recog->pixaa_u, NULL, L_CLONE);
        pixaaAddPixa(paa, pixa, L_INSERT);
    }
    pixaaWrite(filename, paa);
    pixaaDestroy(&paa);
    return 0;
}
Пример #4
0
void
CopyStoreClean(PIXA    *pixas,
               l_int32  nlevels,
               l_int32  ncopies)
{
l_int32  i, j;
PIX     *pix, *pixt;
PIXA    *pixa;
PIXAA   *paa;

    paa = pixaaCreate(0);
    for (i = 0; i < nlevels ; i++) {
        pixa = pixaCreate(0);
        pixaaAddPixa(paa, pixa, L_INSERT);
        pix = pixaGetPix(pixas, i, L_CLONE);
        for (j = 0; j < ncopies; j++) {
            pixt = pixCopy(NULL, pix);
            pixaAddPix(pixa, pixt, L_INSERT);
        }
        pixDestroy(&pix);
    }
    pixaaDestroy(&paa);

    return;
}
Пример #5
0
/*!
 * \brief   recogDestroy()
 *
 * \param[in,out]   precog will be set to null before returning
 * \return  void
 */
void
recogDestroy(L_RECOG  **precog)
{
L_RECOG  *recog;

    PROCNAME("recogDestroy");

    if (!precog) {
        L_WARNING("ptr address is null\n", procName);
        return;
    }

    if ((recog = *precog) == NULL) return;

    LEPT_FREE(recog->centtab);
    LEPT_FREE(recog->sumtab);
    sarrayDestroy(&recog->sa_text);
    l_dnaDestroy(&recog->dna_tochar);
    pixaaDestroy(&recog->pixaa_u);
    pixaDestroy(&recog->pixa_u);
    ptaaDestroy(&recog->ptaa_u);
    ptaDestroy(&recog->pta_u);
    numaDestroy(&recog->nasum_u);
    numaaDestroy(&recog->naasum_u);
    pixaaDestroy(&recog->pixaa);
    pixaDestroy(&recog->pixa);
    ptaaDestroy(&recog->ptaa);
    ptaDestroy(&recog->pta);
    numaDestroy(&recog->nasum);
    numaaDestroy(&recog->naasum);
    pixaDestroy(&recog->pixa_tr);
    pixaDestroy(&recog->pixadb_ave);
    pixaDestroy(&recog->pixa_id);
    pixDestroy(&recog->pixdb_ave);
    pixDestroy(&recog->pixdb_range);
    pixaDestroy(&recog->pixadb_boot);
    pixaDestroy(&recog->pixadb_split);
    bmfDestroy(&recog->bmf);
    rchDestroy(&recog->rch);
    rchaDestroy(&recog->rcha);
    recogDestroyDid(recog);
    LEPT_FREE(recog);
    *precog = NULL;
    return;
}
Пример #6
0
/*!
 * \brief   pixGetWordsInTextlines()
 *
 * \param[in]    pixs 1 bpp, typ. 75 - 150 ppi
 * \param[in]    minwidth, minheight of saved components; smaller are discarded
 * \param[in]    maxwidth, maxheight of saved components; larger are discarded
 * \param[out]   pboxad word boxes sorted in textline line order
 * \param[out]   ppixad word images sorted in textline line order
 * \param[out]   pnai index of textline for each word
 * \return  0 if OK, 1 on error
 *
 * <pre>
 * Notes:
 *      (1) The input should be at a resolution of between 75 and 150 ppi.
 *      (2) The four size constraints on saved components are all
 *          scaled by %reduction.
 *      (3) The result are word images (and their b.b.), extracted in
 *          textline order, at either full res or 2x reduction,
 *          and with a numa giving the textline index for each word.
 *      (4) The pixa and boxa interfaces should make this type of
 *          application simple to put together.  The steps are:
 *           ~ generate first estimate of word masks
 *           ~ get b.b. of these, and remove the small and big ones
 *           ~ extract pixa of the word images, using the b.b.
 *           ~ sort actual word images in textline order (2d)
 *           ~ flatten them to a pixa (1d), saving the textline index
 *             for each pix
 *      (5) In an actual application, it may be desirable to pre-filter
 *          the input image to remove large components, to extract
 *          single columns of text, and to deskew them.  For example,
 *          to remove both large components and small noisy components
 *          that can interfere with the statistics used to estimate
 *          parameters for segmenting by words, but still retain text lines,
 *          the following image preprocessing can be done:
 *                Pix *pixt = pixMorphSequence(pixs, "c40.1", 0);
 *                Pix *pixf = pixSelectBySize(pixt, 0, 60, 8,
 *                                     L_SELECT_HEIGHT, L_SELECT_IF_LT, NULL);
 *                pixAnd(pixf, pixf, pixs);  // the filtered image
 *          The closing turns text lines into long blobs, but does not
 *          significantly increase their height.  But if there are many
 *          small connected components in a dense texture, this is likely
 *          to generate tall components that will be eliminated in pixf.
 * </pre>
 */
l_int32
pixGetWordsInTextlines(PIX     *pixs,
                       l_int32  minwidth,
                       l_int32  minheight,
                       l_int32  maxwidth,
                       l_int32  maxheight,
                       BOXA   **pboxad,
                       PIXA   **ppixad,
                       NUMA   **pnai)
{
BOXA    *boxa1, *boxad;
BOXAA   *baa;
NUMA    *nai;
NUMAA   *naa;
PIXA    *pixa1, *pixad;
PIXAA   *paa;

    PROCNAME("pixGetWordsInTextlines");

    if (!pboxad || !ppixad || !pnai)
        return ERROR_INT("&boxad, &pixad, &nai not all defined", procName, 1);
    *pboxad = NULL;
    *ppixad = NULL;
    *pnai = NULL;
    if (!pixs)
        return ERROR_INT("pixs not defined", procName, 1);

        /* Get the bounding boxes of the words from the word mask. */
    pixWordBoxesByDilation(pixs, minwidth, minheight, maxwidth, maxheight,
                           &boxa1, NULL, NULL);

        /* Generate a pixa of the word images */
    pixa1 = pixaCreateFromBoxa(pixs, boxa1, NULL);  /* mask over each word */

        /* Sort the bounding boxes of these words by line.  We use the
         * index mapping to allow identical sorting of the pixa. */
    baa = boxaSort2d(boxa1, &naa, -1, -1, 4);
    paa = pixaSort2dByIndex(pixa1, naa, L_CLONE);

        /* Flatten the word paa */
    pixad = pixaaFlattenToPixa(paa, &nai, L_CLONE);
    boxad = pixaGetBoxa(pixad, L_COPY);

    *pnai = nai;
    *pboxad = boxad;
    *ppixad = pixad;

    pixaDestroy(&pixa1);
    boxaDestroy(&boxa1);
    boxaaDestroy(&baa);
    pixaaDestroy(&paa);
    numaaDestroy(&naa);
    return 0;
}
Пример #7
0
CubeLineSegmenter::~CubeLineSegmenter() {
  if (img_ != NULL) {
    pixDestroy(&img_);
    img_ = NULL;
  }

  if (lines_pixa_ != NULL) {
    pixaDestroy(&lines_pixa_);
    lines_pixa_ = NULL;
  }

  if (con_comps_ != NULL) {
    pixaDestroy(&con_comps_);
    con_comps_ = NULL;
  }

  if (columns_ != NULL) {
    pixaaDestroy(&columns_);
    columns_ = NULL;
  }
}
Пример #8
0
/*!
 * \brief   recogReadStream()
 *
 * \param[in]    fp file stream
 * \return  recog, or NULL on error
 */
L_RECOG *
recogReadStream(FILE  *fp)
{
l_int32   version, setsize, threshold, scalew, scaleh, linew;
l_int32   maxyshift, nc;
L_DNA    *dna_tochar;
PIXAA    *paa;
L_RECOG  *recog;
SARRAY   *sa_text;

    PROCNAME("recogReadStream");

    if (!fp)
        return (L_RECOG *)ERROR_PTR("stream not defined", procName, NULL);

    if (fscanf(fp, "\nRecog Version %d\n", &version) != 1)
        return (L_RECOG *)ERROR_PTR("not a recog file", procName, NULL);
    if (version != RECOG_VERSION_NUMBER)
        return (L_RECOG *)ERROR_PTR("invalid recog version", procName, NULL);
    if (fscanf(fp, "Size of character set = %d\n", &setsize) != 1)
        return (L_RECOG *)ERROR_PTR("setsize not read", procName, NULL);
    if (fscanf(fp, "Binarization threshold = %d\n", &threshold) != 1)
        return (L_RECOG *)ERROR_PTR("binary thresh not read", procName, NULL);
    if (fscanf(fp, "Maxyshift = %d\n", &maxyshift) != 1)
        return (L_RECOG *)ERROR_PTR("maxyshift not read", procName, NULL);
    if (fscanf(fp, "Scale to width = %d\n", &scalew) != 1)
        return (L_RECOG *)ERROR_PTR("width not read", procName, NULL);
    if (fscanf(fp, "Scale to height = %d\n", &scaleh) != 1)
        return (L_RECOG *)ERROR_PTR("height not read", procName, NULL);
    if (fscanf(fp, "Normalized line width = %d\n", &linew) != 1)
        return (L_RECOG *)ERROR_PTR("line width not read", procName, NULL);
    if ((recog = recogCreate(scalew, scaleh, linew, threshold,
                             maxyshift)) == NULL)
        return (L_RECOG *)ERROR_PTR("recog not made", procName, NULL);

    if (fscanf(fp, "\nLabels for character set:\n") != 0) {
        recogDestroy(&recog);
        return (L_RECOG *)ERROR_PTR("label intro not read", procName, NULL);
    }
    l_dnaDestroy(&recog->dna_tochar);
    if ((dna_tochar = l_dnaReadStream(fp)) == NULL) {
        recogDestroy(&recog);
        return (L_RECOG *)ERROR_PTR("dna_tochar not read", procName, NULL);
    }
    recog->dna_tochar = dna_tochar;
    sarrayDestroy(&recog->sa_text);
    if ((sa_text = sarrayReadStream(fp)) == NULL) {
        recogDestroy(&recog);
        return (L_RECOG *)ERROR_PTR("sa_text not read", procName, NULL);
    }
    recog->sa_text = sa_text;

    if (fscanf(fp, "\nPixaa of all samples in the training set:\n") != 0) {
        recogDestroy(&recog);
        return (L_RECOG *)ERROR_PTR("pixaa intro not read", procName, NULL);
    }
    if ((paa = pixaaReadStream(fp)) == NULL) {
        recogDestroy(&recog);
        return (L_RECOG *)ERROR_PTR("pixaa not read", procName, NULL);
    }
    recog->setsize = setsize;
    nc = pixaaGetCount(paa, NULL);
    if (nc != setsize) {
        recogDestroy(&recog);
        pixaaDestroy(&paa);
        L_ERROR("(setsize = %d) != (paa count = %d)\n", procName,
                     setsize, nc);
        return NULL;
    }

    recogAddAllSamples(&recog, paa, 0);  /* this finishes */
    pixaaDestroy(&paa);
    if (!recog)
        return (L_RECOG *)ERROR_PTR("bad templates", procName, NULL);
    return recog;
}
/*!
 * \brief   pixGetWordsInTextlines()
 *
 * \param[in]    pixs 1 bpp, typ. 300 ppi
 * \param[in]    reduction 1 for input res; 2 for 2x reduction of input res
 * \param[in]    minwidth, minheight of saved components; smaller are discarded
 * \param[in]    maxwidth, maxheight of saved components; larger are discarded
 * \param[out]   pboxad word boxes sorted in textline line order
 * \param[out]   ppixad word images sorted in textline line order
 * \param[out]   pnai index of textline for each word
 * \return  0 if OK, 1 on error
 *
 * <pre>
 * Notes:
 *      (1) The input should be at a resolution of about 300 ppi.
 *          The word masks and word images can be computed at either
 *          150 ppi or 300 ppi.  For the former, set reduction = 2.
 *      (2) The four size constraints on saved components are all
 *          scaled by %reduction.
 *      (3) The result are word images (and their b.b.), extracted in
 *          textline order, at either full res or 2x reduction,
 *          and with a numa giving the textline index for each word.
 *      (4) The pixa and boxa interfaces should make this type of
 *          application simple to put together.  The steps are:
 *           ~ optionally reduce by 2x
 *           ~ generate first estimate of word masks
 *           ~ get b.b. of these, and remove the small and big ones
 *           ~ extract pixa of the word images, using the b.b.
 *           ~ sort actual word images in textline order (2d)
 *           ~ flatten them to a pixa (1d), saving the textline index
 *             for each pix
 *      (5) In an actual application, it may be desirable to pre-filter
 *          the input image to remove large components, to extract
 *          single columns of text, and to deskew them.  For example,
 *          to remove both large components and small noisy components
 *          that can interfere with the statistics used to estimate
 *          parameters for segmenting by words, but still retain text lines,
 *          the following image preprocessing can be done:
 *                Pix *pixt = pixMorphSequence(pixs, "c40.1", 0);
 *                Pix *pixf = pixSelectBySize(pixt, 0, 60, 8,
 *                                     L_SELECT_HEIGHT, L_SELECT_IF_LT, NULL);
 *                pixAnd(pixf, pixf, pixs);  // the filtered image
 *          The closing turns text lines into long blobs, but does not
 *          significantly increase their height.  But if there are many
 *          small connected components in a dense texture, this is likely
 *          to generate tall components that will be eliminated in pixf.
 * </pre>
 */
l_int32
pixGetWordsInTextlines(PIX     *pixs,
                       l_int32  reduction,
                       l_int32  minwidth,
                       l_int32  minheight,
                       l_int32  maxwidth,
                       l_int32  maxheight,
                       BOXA   **pboxad,
                       PIXA   **ppixad,
                       NUMA   **pnai)
{
l_int32  maxdil;
BOXA    *boxa1, *boxad;
BOXAA   *baa;
NUMA    *nai;
NUMAA   *naa;
PIXA    *pixa1, *pixad;
PIX     *pix1;
PIXAA   *paa;

    PROCNAME("pixGetWordsInTextlines");

    if (!pboxad || !ppixad || !pnai)
        return ERROR_INT("&boxad, &pixad, &nai not all defined", procName, 1);
    *pboxad = NULL;
    *ppixad = NULL;
    *pnai = NULL;
    if (!pixs)
        return ERROR_INT("pixs not defined", procName, 1);
    if (reduction != 1 && reduction != 2)
        return ERROR_INT("reduction not in {1,2}", procName, 1);

    if (reduction == 1) {
        pix1 = pixClone(pixs);
        maxdil = 18;
    } else {  /* reduction == 2 */
        pix1 = pixReduceRankBinaryCascade(pixs, 1, 0, 0, 0);
        maxdil = 9;
    }

        /* Get the bounding boxes of the words from the word mask. */
    pixWordBoxesByDilation(pix1, maxdil, minwidth, minheight,
                           maxwidth, maxheight, &boxa1, NULL);

        /* Generate a pixa of the word images */
    pixa1 = pixaCreateFromBoxa(pix1, boxa1, NULL);  /* mask over each word */

        /* Sort the bounding boxes of these words by line.  We use the
         * index mapping to allow identical sorting of the pixa. */
    baa = boxaSort2d(boxa1, &naa, -1, -1, 4);
    paa = pixaSort2dByIndex(pixa1, naa, L_CLONE);

        /* Flatten the word paa */
    pixad = pixaaFlattenToPixa(paa, &nai, L_CLONE);
    boxad = pixaGetBoxa(pixad, L_COPY);

    *pnai = nai;
    *pboxad = boxad;
    *ppixad = pixad;

    pixDestroy(&pix1);
    pixaDestroy(&pixa1);
    boxaDestroy(&boxa1);
    boxaaDestroy(&baa);
    pixaaDestroy(&paa);
    numaaDestroy(&naa);
    return 0;
}
Пример #10
0
int main(int    argc,
         char **argv)
{
l_int32      w, h, d, w2, h2, i, ncols, ret;
l_float32    angle, conf;
BOX         *box;
BOXA        *boxa, *boxa2;
PIX         *pix, *pixs, *pixb, *pixb2, *pixd;
PIX         *pix1, *pix2, *pix3, *pix4, *pix5, *pix6;
PIXA        *pixam;  /* mask with a single component over each column */
PIXA        *pixac, *pixad, *pixat;
PIXAA       *pixaa, *pixaa2;
SEL         *selsplit;
static char  mainName[] = "arabic_lines";

    if (argc != 1)
        return ERROR_INT(" Syntax:  arabic_lines", mainName, 1);

    pixDisplayWrite(NULL, -1);  /* init debug output */

        /* Binarize input */
    pixs = pixRead("arabic.png");
    pixGetDimensions(pixs, &w, &h, &d);
    pix = pixConvertTo1(pixs, 128);

        /* Deskew */
    pixb = pixFindSkewAndDeskew(pix, 1, &angle, &conf);
    pixDestroy(&pix);
    fprintf(stderr, "Skew angle: %7.2f degrees; %6.2f conf\n", angle, conf);
    pixDisplayWrite(pixb, 1);

        /* Use full image morphology to find columns, at 2x reduction.
           This only works for very simple layouts where each column
           of text extends the full height of the input image.  */
    pixb2 = pixReduceRankBinary2(pixb, 2, NULL);
    pix1 = pixMorphCompSequence(pixb2, "c5.500", 0);
    boxa = pixConnComp(pix1, &pixam, 8);
    ncols = boxaGetCount(boxa);
    fprintf(stderr, "Num columns: %d\n", ncols);
    pixDisplayWrite(pix1, 1);

        /* Use selective region-based morphology to get the textline mask. */
    pixad = pixaMorphSequenceByRegion(pixb2, pixam, "c100.3", 0, 0);
    pixGetDimensions(pixb2, &w2, &h2, NULL);
    pix2 = pixaDisplay(pixad, w2, h2);
    pixDisplayWrite(pix2, 1);
    pixDestroy(&pix2);

        /* Some of the lines may be touching, so use a HMT to split the
           lines in each column, and use a pixaa to save the results. */
    selsplit = selCreateFromString(seltext, 17, 7, "selsplit");
    pixaa = pixaaCreate(ncols);
    for (i = 0; i < ncols; i++) {
        pix3 = pixaGetPix(pixad, i, L_CLONE);
        box = pixaGetBox(pixad, i, L_COPY);
        pix4 = pixHMT(NULL, pix3, selsplit);
        pixXor(pix4, pix4, pix3);
        boxa2 = pixConnComp(pix4, &pixac, 8);
        pixaaAddPixa(pixaa, pixac, L_INSERT);
        pixaaAddBox(pixaa, box, L_INSERT);
        pix5 = pixaDisplayRandomCmap(pixac, 0, 0);
        pixDisplayWrite(pix5, 1);
        fprintf(stderr, "Num textlines in col %d: %d\n", i,
                boxaGetCount(boxa2));
        pixDestroy(&pix5);
        pixDestroy(&pix3);
        pixDestroy(&pix4);
        boxaDestroy(&boxa2);
    }

        /* Visual output */
    ret = system("gthumb /tmp/display/file* &");
    pixat = pixaReadFiles("/tmp/display", "file");
    pix5 = selDisplayInPix(selsplit, 31, 2);
    pixaAddPix(pixat, pix5, L_INSERT);
    pix6 = pixaDisplayTiledAndScaled(pixat, 32, 400, 3, 0, 35, 3);
    pixWrite("/tmp/result.png", pix6, IFF_PNG);
    pixaDestroy(&pixat);
    pixDestroy(&pix6);

        /* Test pixaa I/O */
    pixaaWrite("/tmp/pixaa", pixaa);
    pixaa2 = pixaaRead("/tmp/pixaa");
    pixaaWrite("/tmp/pixaa2", pixaa2);

        /* Test pixaa display */
    pixd = pixaaDisplay(pixaa, w2, h2);
    pixWrite("/tmp/textlines.png", pixd, IFF_PNG);
    pixDestroy(&pixd);

        /* Cleanup */
    pixDestroy(&pixb2);
    pixDestroy(&pix1);
    pixaDestroy(&pixam);
    pixaDestroy(&pixad);
    pixaaDestroy(&pixaa);
    pixaaDestroy(&pixaa2);
    boxaDestroy(&boxa);
    selDestroy(&selsplit);
    pixDestroy(&pixs);
    pixDestroy(&pixb);
    return 0;
}
Пример #11
0
main(int    argc,
     char **argv)
{
char        *filein, *fileout;
l_int32      w, h, d, w2, h2, i, ncols;
l_float32    angle, conf;
BOX         *box;
BOXA        *boxa, *boxas, *boxad, *boxa2;
NUMA        *numa;
PIX         *pixs, *pixt, *pixb, *pixb2, *pixd;
PIX         *pixtlm, *pixvws;
PIX         *pixt1, *pixt2, *pixt3, *pixt4, *pixt5, *pixt6;
PIXA        *pixam, *pixac, *pixad, *pixat;
PIXAA       *pixaa, *pixaa2;
PTA         *pta;
SEL         *selsplit;
static char  mainName[] = "textlinemask";

    if (argc != 3)
        exit(ERROR_INT(" Syntax:  textlinemask filein fileout", mainName, 1));

    filein = argv[1];
    fileout = argv[2];

    pixDisplayWrite(NULL, -1);  /* init debug output */

    if ((pixs = pixRead(filein)) == NULL)
        return ERROR_INT("pixs not made", mainName, 1);
    pixGetDimensions(pixs, &w, &h, &d);

        /* Binarize input */
    if (d == 8)
        pixt = pixThresholdToBinary(pixs, 128);
    else if (d == 1)
        pixt = pixClone(pixs);
    else {
        fprintf(stderr, "depth is %d\n", d);
        exit(1);
    }

        /* Deskew */
    pixb = pixFindSkewAndDeskew(pixt, 1, &angle, &conf);
    pixDestroy(&pixt);
    fprintf(stderr, "Skew angle: %7.2f degrees; %6.2f conf\n", angle, conf);
    pixDisplayWrite(pixb, DEBUG_OUTPUT);

#if 1
        /* Use full image morphology to find columns, at 2x reduction.
         * This only works for very simple layouts where each column
         * of text extends the full height of the input image. 
         * pixam has a pix component over each column.  */
    pixb2 = pixReduceRankBinary2(pixb, 2, NULL);
    pixt1 = pixMorphCompSequence(pixb2, "c5.500", 0);
    boxa = pixConnComp(pixt1, &pixam, 8);
    ncols = boxaGetCount(boxa);
    fprintf(stderr, "Num columns: %d\n", ncols);
    pixDisplayWrite(pixt1, DEBUG_OUTPUT);

        /* Use selective region-based morphology to get the textline mask. */
    pixad = pixaMorphSequenceByRegion(pixb2, pixam, "c100.3", 0, 0);
    pixGetDimensions(pixb2, &w2, &h2, NULL);
    if (DEBUG_OUTPUT) {
        pixt2 = pixaDisplay(pixad, w2, h2);
        pixDisplayWrite(pixt2, DEBUG_OUTPUT);
        pixDestroy(&pixt2);
    }

        /* Some of the lines may be touching, so use a HMT to split the
         * lines in each column, and use a pixaa to save the results. */
    selsplit = selCreateFromString(seltext, 17, 7, "selsplit");
    pixaa = pixaaCreate(ncols);
    for (i = 0; i < ncols; i++) {
        pixt3 = pixaGetPix(pixad, i, L_CLONE);
        box = pixaGetBox(pixad, i, L_COPY);
        pixt4 = pixHMT(NULL, pixt3, selsplit);
        pixXor(pixt4, pixt4, pixt3);
        boxa2 = pixConnComp(pixt4, &pixac, 8);
        pixaaAddPixa(pixaa, pixac, L_INSERT);
        pixaaAddBox(pixaa, box, L_INSERT);
        if (DEBUG_OUTPUT) {
            pixt5 = pixaDisplayRandomCmap(pixac, 0, 0);
            pixDisplayWrite(pixt5, DEBUG_OUTPUT);
            fprintf(stderr, "Num textlines in col %d: %d\n", i,
                    boxaGetCount(boxa2));
            pixDestroy(&pixt5);
        }
        pixDestroy(&pixt3);
        pixDestroy(&pixt4);
        boxaDestroy(&boxa2);
    }

        /* Visual output */
    if (DEBUG_OUTPUT) {
        pixDisplayMultiple("/tmp/junk_write_display*");
        pixat = pixaReadFiles("/tmp", "junk_write_display");
        pixt5 = selDisplayInPix(selsplit, 31, 2);
        pixaAddPix(pixat, pixt5, L_INSERT);
        pixt6 = pixaDisplayTiledAndScaled(pixat, 32, 400, 3, 0, 35, 3);
        pixWrite(fileout, pixt6, IFF_PNG);
        pixaDestroy(&pixat);
        pixDestroy(&pixt6);
    }

        /* Test pixaa I/O */
    pixaaWrite("/tmp/junkpixaa", pixaa);
    pixaa2 = pixaaRead("/tmp/junkpixaa");
    pixaaWrite("/tmp/junkpixaa2", pixaa2);

        /* Test pixaa display */
    pixd = pixaaDisplay(pixaa, w2, h2);
    pixWrite("/tmp/junkdisplay", pixd, IFF_PNG);
    pixDestroy(&pixd);

        /* Cleanup */
    pixDestroy(&pixb2);
    pixDestroy(&pixt1);
    pixaDestroy(&pixam);
    pixaDestroy(&pixad);
    pixaaDestroy(&pixaa);
    pixaaDestroy(&pixaa2);
    boxaDestroy(&boxa);
    selDestroy(&selsplit);
#endif

#if 0
        /*  Use the baseline finder; not really what is needed */
    numa = pixFindBaselines(pixb, &pta, 1);
#endif

#if 0
        /* Use the textline mask function; parameters are not quite right */
    pixb2 = pixReduceRankBinary2(pixb, 2, NULL);
    pixtlm = pixGenTextlineMask(pixb2, &pixvws, NULL, 1);
    pixDisplay(pixtlm, 0, 100);
    pixDisplay(pixvws, 500, 100);
    pixDestroy(&pixb2);
    pixDestroy(&pixtlm);
    pixDestroy(&pixvws);
#endif

#if 0
        /* Use the Breuel whitespace partition method; slow and we would
         * still need to work to extract the fg regions. */
    pixb2 = pixReduceRankBinary2(pixb, 2, NULL);
    boxas = pixConnComp(pixb2, NULL, 8);
    boxad = boxaGetWhiteblocks(boxas, NULL, L_SORT_BY_HEIGHT,
                              3, 0.1, 200, 0.2, 0);
    pixd = pixDrawBoxa(pixb2, boxad, 7, 0xe0708000);
    pixDisplay(pixd, 100, 500);
    pixDestroy(&pixb2);
    pixDestroy(&pixd);
    boxaDestroy(&boxas);
    boxaDestroy(&boxad);
#endif


#if 0
        /* Use morphology to find columns and then selective
         * region-based morphology to get the textline mask.
         * This is for display; we really want to get a pixa of the
         * specific textline masks.   */
    startTimer();
    pixb2 = pixReduceRankBinary2(pixb, 2, NULL);
    pixt1 = pixMorphCompSequence(pixb2, "c5.500", 0);  /* column mask */
    pixt2 = pixMorphSequenceByRegion(pixb2, pixt1, "c100.3", 8, 0, 0, &boxa);
    fprintf(stderr, "time = %7.3f sec\n", stopTimer());
    pixDisplay(pixt1, 100, 500);
    pixDisplay(pixt2, 800, 500);
    pixDestroy(&pixb2);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    boxaDestroy(&boxa);
#endif

    pixDestroy(&pixs);
    pixDestroy(&pixb);

    exit(0);
}
Пример #12
0
int main(int    argc,
         char **argv)
{
char         buf[8];
l_int32      i, n, h;
l_float32    scalefact;
BOXA        *boxa;
PIX         *pixs, *pix, *pixt1, *pixt2;
PIXA        *pixa, *pixas, *pixad;
PIXAA       *pixaa;
static char  mainName[] = "digitprep1";

    if (argc != 1) {
        ERROR_INT(" Syntax: digitprep1", mainName, 1);
        return 1;
    }

    if ((pixs = pixRead("barcode-digits.png")) == NULL)
        return ERROR_INT("pixs not read", mainName, 1);

        /* Extract the digits and scale to HEIGHT */
    boxa = pixConnComp(pixs, &pixa, 8);
    pixas = pixaSort(pixa, L_SORT_BY_X, L_SORT_INCREASING, NULL, L_CLONE);
    n = pixaGetCount(pixas);

        /* Move the last ("0") to the first position */
    pixt1 = pixaGetPix(pixas, n - 1, L_CLONE);
    pixaInsertPix(pixas, 0, pixt1, NULL);
    pixaRemovePix(pixas, n);

        /* Make the output scaled pixa */
    pixad = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pixt1 = pixaGetPix(pixas, i, L_CLONE);
        pixGetDimensions(pixt1, NULL, &h, NULL);
        scalefact = HEIGHT / (l_float32)h;
        pixt2 = pixScale(pixt1, scalefact, scalefact);
        if (pixGetHeight(pixt2) != 32)
            return ERROR_INT("height not 32!", mainName, 1);
        sprintf(buf, "%d", i);
        pixSetText(pixt2, buf);
        pixaAddPix(pixad, pixt2, L_INSERT);
        pixDestroy(&pixt1);
    }

        /* Save in a pixaa, with 1 pix in each pixa */
    pixaa = pixaaCreateFromPixa(pixad, 1, L_CHOOSE_CONSECUTIVE, L_CLONE);
    pixaaWrite("junkdigits.pixaa", pixaa);

        /* Show result */
    pixt1 = pixaaDisplayByPixa(pixaa, 20, 20, 1000);
    pixDisplay(pixt1, 100, 100);
    pixDestroy(&pixt1);

    boxaDestroy(&boxa);
    pixaDestroy(&pixa);
    pixaDestroy(&pixas);
    pixaDestroy(&pixad);
    pixaaDestroy(&pixaa);
    return 0;
}