Beispiel #1
0
/*!
 *  dewarpaApplyInit()
 *
 *      Input:  dewa
 *              pageno (of page model to be used; may be a ref model)
 *              pixs (image to be modified; can be 1, 8 or 32 bpp)
 *              x, y (origin for generation of disparity arrays)
 *              &pdew (<return> dewarp to be used for this page
 *              debugfile (use null to skip writing this)
 *      Return: 0 if OK, 1 on error (no models or ref models available)
 *
 *  Notes:
 *      (1) This prepares pixs for being dewarped.  It returns 1 if
 *          no dewarping model exists.
 *      (2) The returned @dew contains the model to be used for this page
 *          image.  The @dew is owned by dewa; do not destroy.
 *      (3) See dewarpApplyDisparity() for other details on inputs.
 */
static l_int32
dewarpaApplyInit(L_DEWARPA   *dewa,
                 l_int32      pageno,
                 PIX         *pixs,
                 l_int32      x,
                 l_int32      y,
                 L_DEWARP   **pdew,
                 const char  *debugfile)
{
l_int32    debug;
L_DEWARP  *dew1, *dew2;

    PROCNAME("dewarpaApplyInit");

    if (!pdew)
        return ERROR_INT("&dew not defined", procName, 1);
    *pdew = NULL;

    if (!dewa)
        return ERROR_INT("dewa not defined", procName, 1);
    if (pageno < 0 || pageno > dewa->maxpage)
        return ERROR_INT("invalid pageno", procName, 1);
    if (!pixs)
        return ERROR_INT("pixs not defined", procName, 1);
    if (x < 0) x = 0;
    if (y < 0) y = 0;
    debug = (debugfile) ? 1 : 0;

        /* Make sure all models are valid and all refmodels have
         * been added to dewa */
    if (dewa->modelsready == FALSE)
        dewarpaInsertRefModels(dewa, 0, debug);

        /* Check for the existence of a valid model; we don't expect
         * all pages to have them. */
    if ((dew1 = dewarpaGetDewarp(dewa, pageno)) == NULL) {
        L_INFO("no valid dew model for page %d\n", procName, pageno);
        return 1;
    }

        /* Get the page model that we will use and sanity-check that
         * it is valid.  The ultimate result will be put in dew1->pixd. */
    if (dew1->hasref)  /* point to another page with a model */
        dew2 = dewarpaGetDewarp(dewa, dew1->refpage);
    else
        dew2 = dew1;
    if (dew2->vvalid == FALSE)
        return ERROR_INT("no model; shouldn't happen", procName, 1);
    *pdew = dew2;

        /* Generate the full res disparity arrays if they don't exist
         * (e.g., if they've been minimized or read from file), or if
         * they are too small for the current image.  */
    dewarpPopulateFullRes(dew2, pixs, x, y);
    return 0;
}
/*!
 *  dewarpaListPages()
 *
 *      Input:  dewa (populated with dewarp structs for pages)
 *      Return: 0 if OK, 1 on error (list of page numbers), or null on error
 *
 *  Notes:
 *      (1) This generates two numas, stored in the dewarpa, that give:
 *          (a) the page number for each dew that has a page model.
 *          (b) the page number for each dew that has either a page
 *              model or a reference model.
 *          It can be called at any time.
 *      (2) It is called by the dewarpa serializer before writing.
 */
l_int32
dewarpaListPages(L_DEWARPA  *dewa)
{
l_int32    i;
L_DEWARP  *dew;
NUMA      *namodels, *napages;

    PROCNAME("dewarpaListPages");

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

    numaDestroy(&dewa->namodels);
    numaDestroy(&dewa->napages);
    namodels = numaCreate(dewa->maxpage + 1);
    napages = numaCreate(dewa->maxpage + 1);
    dewa->namodels = namodels;
    dewa->napages = napages;
    for (i = 0; i <= dewa->maxpage; i++) {
        if ((dew = dewarpaGetDewarp(dewa, i)) != NULL) {
            if (dew->hasref == 0)
                numaAddNumber(namodels, dew->pageno);
            numaAddNumber(napages, dew->pageno);
        }
    }
    return 0;
}
Beispiel #3
0
/*!
 *  dewarpMinimize()
 *
 *      Input:  dew
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) This removes all data that is not needed for serialization.
 *          It keeps the subsampled disparity array(s), so the full
 *          resolution arrays can be reconstructed.
 */
l_int32
dewarpMinimize(L_DEWARP  *dew)
{
L_DEWARP  *dewt;

    PROCNAME("dewarpMinimize");

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

        /* If dew is a ref, minimize the actual dewarp */
    if (dew->hasref)
        dewt = dewarpaGetDewarp(dew->dewa, dew->refpage);
    else
        dewt = dew;
    if (!dewt)
        return ERROR_INT("dewt not found", procName, 1);

    pixDestroy(&dewt->pixs);
    fpixDestroy(&dewt->fullvdispar);
    fpixDestroy(&dewt->fullhdispar);
    numaDestroy(&dewt->namidys);
    numaDestroy(&dewt->nacurves);
    return 0;
}
/*!
 *  dewarpaInfo()
 *
 *      Input:  fp
 *              dewa
 *      Return: 0 if OK, 1 on error
 */
l_int32
dewarpaInfo(FILE       *fp,
            L_DEWARPA  *dewa)
{
l_int32    i, n, pageno, nnone, nvsuccess, nvvalid, nhsuccess, nhvalid, nref;
L_DEWARP  *dew;

    PROCNAME("dewarpaInfo");

    if (!fp)
        return ERROR_INT("dewa not defined", procName, 1);
    if (!dewa)
        return ERROR_INT("dewa not defined", procName, 1);

    fprintf(fp, "\nDewarpaInfo: %p\n", dewa);
    fprintf(fp, "nalloc = %d, maxpage = %d\n", dewa->nalloc, dewa->maxpage);
    fprintf(fp, "sampling = %d, redfactor = %d, minlines = %d\n",
            dewa->sampling, dewa->redfactor, dewa->minlines);
    fprintf(fp, "maxdist = %d, useboth = %d\n",
            dewa->maxdist, dewa->useboth);

    dewarpaModelStats(dewa, &nnone, &nvsuccess, &nvvalid,
                      &nhsuccess, &nhvalid, &nref);
    n = numaGetCount(dewa->napages);
    fprintf(stderr, "Total number of pages with a dew = %d\n", n);
    fprintf(stderr, "Number of pages without any models = %d\n", nnone);
    fprintf(stderr, "Number of pages with a vert model = %d\n", nvsuccess);
    fprintf(stderr, "Number of pages with a valid vert model = %d\n", nvvalid);
    fprintf(stderr, "Number of pages with both models = %d\n", nhsuccess);
    fprintf(stderr, "Number of pages with both models valid = %d\n", nhvalid);
    fprintf(stderr, "Number of pages with a ref model = %d\n", nref);

    for (i = 0; i < n; i++) {
        numaGetIValue(dewa->napages, i, &pageno);
        if ((dew = dewarpaGetDewarp(dewa, pageno)) == NULL)
            continue;
        fprintf(stderr, "Page: %d\n", dew->pageno);
        fprintf(stderr, "  hasref = %d, refpage = %d\n",
                dew->hasref, dew->refpage);
        fprintf(stderr, "  nlines = %d\n", dew->nlines);
        fprintf(stderr, "  w = %d, h = %d, nx = %d, ny = %d\n",
                dew->w, dew->h, dew->nx, dew->ny);
        if (dew->sampvdispar)
            fprintf(stderr, "  Vertical disparity builds:\n"
                    "    (min,max,abs-diff) line curvature = (%d,%d,%d)\n",
                    dew->mincurv, dew->maxcurv, dew->maxcurv - dew->mincurv);
        if (dew->samphdispar)
            fprintf(stderr, "  Horizontal disparity builds:\n"
                    "    left edge slope = %d, right edge slope = %d\n"
                    "    (left,right,abs-diff) edge curvature = (%d,%d,%d)\n",
                    dew->leftslope, dew->rightslope, dew->leftcurv,
                    dew->rightcurv, L_ABS(dew->leftcurv - dew->rightcurv));
    }
    return 0;
}
/*!
 *  dewarpaModelStats()
 *
 *      Input:  dewa
 *              &nnone (<optional return> number without any model)
 *              &nvsuccess (<optional return> number with a vert model)
 *              &nvvalid (<optional return> number with a valid vert model)
 *              &nhsuccess (<optional return> number with both models)
 *              &nhvalid (<optional return> number with both models valid)
 *              &nref (<optional return> number with a reference model)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) A page without a model has no dew.  It most likely failed to
 *          generate a vertical model, and has not been assigned a ref
 *          model from a neighboring page with a valid vertical model.
 *      (2) A page has vsuccess == 1 if there is at least a model of the
 *          vertical disparity.  The model may be invalid, in which case
 *          dewarpaInsertRefModels() will stash it in the cache and
 *          attempt to replace it by a valid ref model.
 *      (3) A vvvalid model is a vertical disparity model whose parameters
 *          satisfy the constraints given in dewarpaSetValidModels().
 *      (4) A page has hsuccess == 1 if both the vertical and horizontal
 *          disparity arrays have been constructed.
 *      (5) An  hvalid model has vertical and horizontal disparity
 *          models whose parameters satisfy the constraints given
 *          in dewarpaSetValidModels().
 *      (6) A page has a ref model if it failed to generate a valid
 *          model but was assigned a vvalid or hvalid model on another
 *          page (within maxdist) by dewarpaInsertRefModel().
 *      (7) This calls dewarpaTestForValidModel(); it ignores the vvalid
 *          and hvalid fields.
 */
l_int32
dewarpaModelStats(L_DEWARPA  *dewa,
                  l_int32    *pnnone,
                  l_int32    *pnvsuccess,
                  l_int32    *pnvvalid,
                  l_int32    *pnhsuccess,
                  l_int32    *pnhvalid,
                  l_int32    *pnref)
{
l_int32    i, n, pageno, nnone, nvsuccess, nvvalid, nhsuccess, nhvalid, nref;
L_DEWARP  *dew;

    PROCNAME("dewarpaModelStats");

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

    dewarpaListPages(dewa);
    n = numaGetCount(dewa->napages);
    nnone = nref = nvsuccess = nvvalid = nhsuccess = nhvalid = 0;
    for (i = 0; i < n; i++) {
        numaGetIValue(dewa->napages, i, &pageno);
        dew = dewarpaGetDewarp(dewa, pageno);
        if (!dew) {
            nnone++;
            continue;
        }
        if (dew->hasref == 1)
            nref++;
        if (dew->vsuccess == 1)
            nvsuccess++;
        if (dew->hsuccess == 1)
            nhsuccess++;
        dewarpaTestForValidModel(dewa, dew, 0);
        if (dew->vvalid == 1)
            nvvalid++;
        if (dew->hvalid == 1)
            nhvalid++;
    }

    if (pnnone) *pnnone = nnone;
    if (pnref) *pnref = nref;
    if (pnvsuccess) *pnvsuccess = nvsuccess;
    if (pnvvalid) *pnvvalid = nvvalid;
    if (pnhsuccess) *pnhsuccess = nhsuccess;
    if (pnhvalid) *pnhvalid = nhvalid;
    return 0;
}
/*!
 *  dewarpaStripRefModels()
 *
 *      Input:  dewa (populated with dewarp structs for pages)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) This examines each dew in a dewarpa, and removes
 *          all that don't have their own page model (i.e., all
 *          that have "references" to nearby pages with valid models).
 *          These references were generated by dewarpaInsertRefModels(dewa).
 */
l_int32
dewarpaStripRefModels(L_DEWARPA  *dewa)
{
l_int32    i;
L_DEWARP  *dew;

    PROCNAME("dewarpaStripRefModels");

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

    for (i = 0; i <= dewa->maxpage; i++) {
        if ((dew = dewarpaGetDewarp(dewa, i)) != NULL) {
            if (dew->hasref)
                dewarpDestroy(&dewa->dewarp[i]);
        }
    }
    dewa->modelsready = 0;

        /* Regenerate the page lists */
    dewarpaListPages(dewa);
    return 0;
}
/*!
 *  dewarpaShowArrays()
 *
 *      Input:  dewa
 *              scalefact (on contour images; typ. 0.5)
 *              first (first page model to render)
 *              last (last page model to render; use 0 to go to end)
 *              fontdir (for text bitmap fonts)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) Generates a pdf of contour plots of the disparity arrays.
 *      (2) This only shows actual models; not ref models
 */
l_int32
dewarpaShowArrays(L_DEWARPA   *dewa,
                  l_float32    scalefact,
                  l_int32      first,
                  l_int32      last,
                  const char  *fontdir)
{
char       buf[256];
char      *pathname;
l_int32    i, svd, shd;
L_BMF     *bmf;
L_DEWARP  *dew;
PIX       *pixv, *pixvs, *pixh, *pixhs, *pixt, *pixd;
PIXA      *pixa;

    PROCNAME("dewarpaShowArrays");

    if (!dewa)
        return ERROR_INT("dew not defined", procName, 1);
    if (first < 0 || first > dewa->maxpage)
        return ERROR_INT("first out of bounds", procName, 1);
    if (last <= 0 || last > dewa->maxpage) last = dewa->maxpage;
    if (last < first)
        return ERROR_INT("last < first", procName, 1);

    lept_rmdir("lept");
    lept_mkdir("lept");
    if ((bmf = bmfCreate(fontdir, 8)) == NULL)
              L_ERROR("bmf not made; page info not displayed", procName);

    fprintf(stderr, "Generating contour plots\n");
    for (i = first; i <= last; i++) {
        if (i && ((i % 10) == 0))
            fprintf(stderr, " .. %d", i);
        dew = dewarpaGetDewarp(dewa, i);
        if (!dew) continue;
        if (dew->hasref == 1) continue;
        svd = shd = 0;
        if (dew->sampvdispar) svd = 1;
        if (dew->samphdispar) shd = 1;
        if (!svd) {
            L_ERROR("sampvdispar not made for page %d!\n", procName, i);
            continue;
        }

            /* Generate contour plots at reduced resolution */
        dewarpPopulateFullRes(dew, NULL, 0, 0);
        pixv = fpixRenderContours(dew->fullvdispar, 3.0, 0.15);
        pixvs = pixScaleBySampling(pixv, scalefact, scalefact);
        pixDestroy(&pixv);
        if (shd) {
            pixh = fpixRenderContours(dew->fullhdispar, 3.0, 0.15);
            pixhs = pixScaleBySampling(pixh, scalefact, scalefact);
            pixDestroy(&pixh);
        }
        dewarpMinimize(dew);

            /* Save side-by-side */
        pixa = pixaCreate(2);
        pixaAddPix(pixa, pixvs, L_INSERT);
        if (shd)
            pixaAddPix(pixa, pixhs, L_INSERT);
        pixt = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 30, 2);
        snprintf(buf, sizeof(buf), "Page %d", i);
        pixd = pixAddSingleTextblock(pixt, bmf, buf, 0x0000ff00,
                                     L_ADD_BELOW, NULL);
        snprintf(buf, sizeof(buf), "arrays_%04d.png", i);
        pathname = genPathname("/tmp/lept", buf);
        pixWrite(pathname, pixd, IFF_PNG);
        pixaDestroy(&pixa);
        pixDestroy(&pixt);
        pixDestroy(&pixd);
        FREE(pathname);
    }
    bmfDestroy(&bmf);
    fprintf(stderr, "\n");

    fprintf(stderr, "Generating pdf of contour plots\n");
    convertFilesToPdf("/tmp/lept", "arrays_", 90, 1.0, L_FLATE_ENCODE,
                      0, "Disparity arrays", "/tmp/lept/disparity_arrays.pdf");
    fprintf(stderr, "Output written to: /tmp/lept/disparity_arrays.pdf\n");
    return 0;
}
/*!
 *  dewarpaInsertRefModels()
 *
 *      Input:  dewa
 *              notests (if 1, ignore curvature constraints on model)
 *              debug (1 to output information on invalid page models)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) This destroys all dewarp models that are invalid, and then
 *          inserts reference models where possible.
 *      (2) If @notests == 1, this ignores the curvature constraints
 *          and assumes that all successfully built models are valid.
 *      (3) If useboth == 0, it uses the closest valid model within the
 *          distance and parity constraints.  If useboth == 1, it tries
 *          to use the closest allowed hvalid model; if it doesn't find
 *          an hvalid model, it uses the closest valid model.
 *      (4) For all pages without a model, this clears out any existing
 *          invalid and reference dewarps, finds the nearest valid model
 *          with the same parity, and inserts an empty dewarp with the
 *          reference page.
 *      (5) Then if it is requested to use both vertical and horizontal
 *          disparity arrays (useboth == 1), it tries to replace any
 *          hvalid == 0 model or reference with an hvalid == 1 reference.
 *      (6) The distance constraint is that any reference model must
 *          be within maxdist.  Note that with the parity constraint,
 *          no reference models will be used if maxdist < 2.
 *      (7) This function must be called, even if reference models will
 *          not be used.  It should be called after building models on all
 *          available pages, and after setting the rendering parameters.
 *      (8) If the dewa has been serialized, this function is called by
 *          dewarpaRead() when it is read back.  It is also called
 *          any time the rendering parameters are changed.
 *      (9) Note: if this has been called with useboth == 1, and useboth
 *          is reset to 0, you should first call dewarpRestoreModels()
 *          to bring real models from the cache back to the primary array.
 */
l_int32
dewarpaInsertRefModels(L_DEWARPA  *dewa,
                       l_int32     notests,
                       l_int32     debug)
{
l_int32    i, j, n, val, min, distdown, distup;
L_DEWARP  *dew;
NUMA      *na, *nah;

    PROCNAME("dewarpaInsertRefModels");

    if (!dewa)
        return ERROR_INT("dewa not defined", procName, 1);
    if (dewa->maxdist < 2)
        L_INFO("maxdist < 2; no ref models can be used\n", procName);

        /* Make an indicator numa for pages with valid models. */
    dewarpaSetValidModels(dewa, notests, debug);
    n = dewa->maxpage + 1;
    na = numaMakeConstant(0, n);
    for (i = 0; i < n; i++) {
        dew = dewarpaGetDewarp(dewa, i);
        if (dew && dew->vvalid)
            numaReplaceNumber(na, i, 1);
    }

        /* Remove all existing ref models and restore models from cache */
    dewarpaRestoreModels(dewa);

        /* Move invalid models to the cache, and insert reference dewarps
         * for pages that need to borrow a model.
         * First, try to find a valid model for each page. */
    for (i = 0; i < n; i++) {
        numaGetIValue(na, i, &val);
        if (val == 1) continue;  /* already has a valid model */
        if ((dew = dewa->dewarp[i]) != NULL) {  /* exists but is not valid; */
            dewa->dewarpcache[i] = dew;  /* move it to the cache */
            dewa->dewarp[i] = NULL;
        }
        if (dewa->maxdist < 2) continue;  /* can't use a ref model */
            /* Look back for nearest model */
        distdown = distup = dewa->maxdist + 1;
        for (j = i - 2; j >= 0 && distdown > dewa->maxdist; j -= 2) {
            numaGetIValue(na, j, &val);
            if (val == 1) distdown = i - j;
        }
            /* Look ahead for nearest model */
        for (j = i + 2; j < n && distup > dewa->maxdist; j += 2) {
            numaGetIValue(na, j, &val);
            if (val == 1) distup = j - i;
        }
        min = L_MIN(distdown, distup);
        if (min > dewa->maxdist) continue;  /* no valid model in range */
        if (distdown <= distup)
            dewarpaInsertDewarp(dewa, dewarpCreateRef(i, i - distdown));
        else
            dewarpaInsertDewarp(dewa, dewarpCreateRef(i, i + distup));
    }
    numaDestroy(&na);

        /* If a valid model will do, we're finished. */
    if (dewa->useboth == 0) {
        dewa->modelsready = 1;  /* validated */
        return 0;
    }

        /* The request is useboth == 1.  Now try to find an hvalid model */
    nah = numaMakeConstant(0, n);
    for (i = 0; i < n; i++) {
        dew = dewarpaGetDewarp(dewa, i);
        if (dew && dew->hvalid)
            numaReplaceNumber(nah, i, 1);
    }
    for (i = 0; i < n; i++) {
        numaGetIValue(nah, i, &val);
        if (val == 1) continue;  /* already has a hvalid model */
        if (dewa->maxdist < 2) continue;  /* can't use a ref model */
        distdown = distup = 100000;
        for (j = i - 2; j >= 0; j -= 2) {  /* look back for nearest model */
            numaGetIValue(nah, j, &val);
            if (val == 1) {
                distdown = i - j;
                break;
            }
        }
        for (j = i + 2; j < n; j += 2) {  /* look ahead for nearest model */
            numaGetIValue(nah, j, &val);
            if (val == 1) {
                distup = j - i;
                break;
            }
        }
        min = L_MIN(distdown, distup);
        if (min > dewa->maxdist) continue;  /* no hvalid model within range */

            /* We can replace the existing valid model with an hvalid model.
             * If it's not a reference, save it in the cache. */
        if ((dew = dewarpaGetDewarp(dewa, i)) == NULL) {
            L_ERROR("dew is null for page %d!\n", procName, i);
        } else {
            if (dew->hasref == 0) {  /* not a ref model */
                dewa->dewarpcache[i] = dew;  /* move it to the cache */
                dewa->dewarp[i] = NULL;  /* must null the ptr */
            }
        }
        if (distdown <= distup)  /* insert the hvalid ref model */
            dewarpaInsertDewarp(dewa, dewarpCreateRef(i, i - distdown));
        else
            dewarpaInsertDewarp(dewa, dewarpCreateRef(i, i + distup));
    }
    numaDestroy(&nah);

    dewa->modelsready = 1;  /* validated */
    return 0;
}
/*!
 *  dewarpaSetValidModels()
 *
 *      Input:  dewa
 *              notests
 *              debug (1 to output information on invalid page models)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) A valid model must meet the rendering requirements, which
 *          include whether or not a vertical disparity model exists
 *          and conditions on curvatures for vertical and horizontal
 *          disparity models.
 *      (2) If @notests == 1, this ignores the curvature constraints
 *          and assumes that all successfully built models are valid.
 *      (3) This function does not need to be called by the application.
 *          It is called by dewarpaInsertRefModels(), which
 *          will destroy all invalid dewarps.  Consequently, to inspect
 *          an invalid dewarp model, it must be done before calling
 *          dewarpaInsertRefModels().
 */
l_int32
dewarpaSetValidModels(L_DEWARPA  *dewa,
                      l_int32     notests,
                      l_int32     debug)
{
l_int32    i, n, maxcurv, diffcurv, diffedge;
L_DEWARP  *dew;

    PROCNAME("dewarpaSetValidModels");

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

    n = dewa->maxpage + 1;
    for (i = 0; i < n; i++) {
        if ((dew = dewarpaGetDewarp(dewa, i)) == NULL)
            continue;

        if (debug) {
            if (dew->hasref == 1) {
                L_INFO("page %d: has only a ref model\n", procName, i);
            } else if (dew->vsuccess == 0) {
                L_INFO("page %d: no model successfully built\n",
                       procName, i);
            } else if (!notests) {
                maxcurv = L_MAX(L_ABS(dew->mincurv), L_ABS(dew->maxcurv));
                diffcurv = dew->maxcurv - dew->mincurv;
                if (dewa->useboth && !dew->hsuccess)
                    L_INFO("page %d: useboth, but no horiz disparity\n",
                               procName, i);
                if (maxcurv > dewa->max_linecurv)
                    L_INFO("page %d: max curvature %d > max_linecurv\n",
                                procName, i, diffcurv);
                if (diffcurv < dewa->min_diff_linecurv)
                    L_INFO("page %d: diff curv %d < min_diff_linecurv\n",
                                procName, i, diffcurv);
                if (diffcurv > dewa->max_diff_linecurv)
                    L_INFO("page %d: abs diff curv %d > max_diff_linecurv\n",
                                procName, i, diffcurv);
                if (dew->hsuccess) {
                    if (L_ABS(dew->leftslope) > dewa->max_edgeslope)
                        L_INFO("page %d: abs left slope %d > max_edgeslope\n",
                                    procName, i, dew->leftslope);
                    if (L_ABS(dew->rightslope) > dewa->max_edgeslope)
                        L_INFO("page %d: abs right slope %d > max_edgeslope\n",
                                    procName, i, dew->rightslope);
                    diffedge = L_ABS(dew->leftcurv - dew->rightcurv);
                    if (L_ABS(dew->leftcurv) > dewa->max_edgecurv)
                        L_INFO("page %d: left curvature %d > max_edgecurv\n",
                                    procName, i, dew->leftcurv);
                    if (L_ABS(dew->rightcurv) > dewa->max_edgecurv)
                        L_INFO("page %d: right curvature %d > max_edgecurv\n",
                               procName, i, dew->rightcurv);
                    if (diffedge > dewa->max_diff_edgecurv)
                        L_INFO("page %d: abs diff left-right curv %d > "
                               "max_diff_edgecurv\n", procName, i, diffedge);
                }
            }
        }

        dewarpaTestForValidModel(dewa, dew, notests);
    }

    return 0;
}
/*!
 *  dewarpShowResults()
 *
 *      Input:  dewa
 *              sarray (of indexed input images)
 *              boxa (crop boxes for input images; can be null)
 *              firstpage, lastpage
 *              fontdir (for text bitmap fonts)
 *              pdfout (filename)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) This generates a pdf of image pairs (before, after) for
 *          the designated set of input pages.
 *      (2) If the boxa exists, its elements are aligned with numbers
 *          in the filenames in @sa.  It is used to crop the input images.
 *          It is assumed that the dewa was generated from the cropped
 *          images.  No undercropping is applied before rendering.
 */
l_int32
dewarpShowResults(L_DEWARPA   *dewa,
                  SARRAY      *sa,
                  BOXA        *boxa,
                  l_int32      firstpage,
                  l_int32      lastpage,
                  const char  *fontdir,
                  const char  *pdfout)
{
char       bufstr[256];
char      *outpath;
l_int32    i, modelpage;
L_BMF     *bmf;
BOX       *box;
L_DEWARP  *dew;
PIX       *pixs, *pixc, *pixd, *pixt1, *pixt2;
PIXA      *pixa;

    PROCNAME("dewarpShowResults");

    if (!dewa)
        return ERROR_INT("dewa not defined", procName, 1);
    if (!sa)
        return ERROR_INT("sa not defined", procName, 1);
    if (!pdfout)
        return ERROR_INT("pdfout not defined", procName, 1);
    if (firstpage > lastpage)
        return ERROR_INT("invalid first/last page numbers", procName, 1);

    lept_rmdir("dewarp_pdfout");
    lept_mkdir("dewarp_pdfout");
    if ((bmf = bmfCreate(fontdir, 6)) == NULL)
        L_ERROR("bmf not made; page info not displayed", procName);

    fprintf(stderr, "Dewarping and generating s/by/s view\n");
    for (i = firstpage; i <= lastpage; i++) {
        if (i && (i % 10 == 0)) fprintf(stderr, ".. %d ", i);
        pixs = pixReadIndexed(sa, i);
        if (boxa) {
            box = boxaGetBox(boxa, i, L_CLONE);
            pixc = pixClipRectangle(pixs, box, NULL);
            boxDestroy(&box);
        }
        else
            pixc = pixClone(pixs);
        dew = dewarpaGetDewarp(dewa, i);
        pixd = NULL;
        if (dew) {
            dewarpaApplyDisparity(dewa, dew->pageno, pixc,
                                        GRAYIN_VALUE, 0, 0, &pixd, NULL);
            dewarpMinimize(dew);
        }
        pixa = pixaCreate(2);
        pixaAddPix(pixa, pixc, L_INSERT);
        if (pixd)
            pixaAddPix(pixa, pixd, L_INSERT);
        pixt1 = pixaDisplayTiledAndScaled(pixa, 32, 500, 2, 0, 35, 2);
        if (dew) {
            modelpage = (dew->hasref) ? dew->refpage : dew->pageno;
            snprintf(bufstr, sizeof(bufstr), "Page %d; using %d\n",
                     i, modelpage);
        }
        else
            snprintf(bufstr, sizeof(bufstr), "Page %d; no dewarp\n", i);
        pixt2 = pixAddSingleTextblock(pixt1, bmf, bufstr, 0x0000ff00,
                                      L_ADD_BELOW, 0);
        snprintf(bufstr, sizeof(bufstr), "/tmp/dewarp_pdfout/%05d", i);
        pixWrite(bufstr, pixt2, IFF_JFIF_JPEG);
        pixaDestroy(&pixa);
        pixDestroy(&pixs);
        pixDestroy(&pixt1);
        pixDestroy(&pixt2);
    }
    fprintf(stderr, "\n");

    fprintf(stderr, "Generating pdf of result\n");
    convertFilesToPdf("/tmp/dewarp_pdfout", NULL, 100, 1.0, L_JPEG_ENCODE,
                      0, "Dewarp sequence", pdfout);
    outpath = genPathname(pdfout, NULL);
    fprintf(stderr, "Output written to: %s\n", outpath);
    FREE(outpath);
    bmfDestroy(&bmf);
    return 0;
}
Beispiel #11
0
/*!
 *  dewarpaApplyDisparityBoxa()
 *
 *      Input:  dewa
 *              pageno (of page model to be used; may be a ref model)
 *              pixs (initial pix reference; for alignment and debugging)
 *              boxas (boxa to be mapped)
 *              mapdir (1 if mapping forward from original to dewarped;
 *                      0 if backward)
 *              x, y (origin for generation of disparity arrays with
 *                    respect to the source region)
 *              &boxad (<return> disparity corrected boxa)
 *              debugfile (use null to skip writing this)
 *      Return: 0 if OK, 1 on error (no models or ref models available)
 *
 *  Notes:
 *      (1) This applies the disparity arrays in one of two mapping directions
 *          to the specified boxa.  It can be used in the backward direction
 *          to locate a box in the original coordinates that would have
 *          been dewarped to to the specified image.
 *      (2) If there is no model for @pageno, this will use the model for
 *          'refpage' and put the result in the dew for @pageno.
 *      (3) This works with both stripped and full resolution page models.
 *          If the full res disparity array(s) are missing, they are remade.
 *      (4) If an error occurs, a copy of the input boxa is returned.
 */
l_int32
dewarpaApplyDisparityBoxa(L_DEWARPA   *dewa,
                          l_int32      pageno,
                          PIX         *pixs,
                          BOXA        *boxas,
                          l_int32      mapdir,
                          l_int32      x,
                          l_int32      y,
                          BOXA       **pboxad,
                          const char  *debugfile)
{
l_int32    debug_out;
L_DEWARP  *dew1, *dew;
BOXA      *boxav, *boxah;
PIX       *pixv, *pixh;

    PROCNAME("dewarpaApplyDisparityBoxa");

        /* Initialize the output with the input, so we'll have that
         * in case we can't apply the page model. */
    if (!pboxad)
        return ERROR_INT("&boxad not defined", procName, 1);
    *pboxad = boxaCopy(boxas, L_CLONE);

        /* Find the appropriate dew to use and fully populate its array(s) */
    if (dewarpaApplyInit(dewa, pageno, pixs, x, y, &dew, debugfile))
        return ERROR_INT("no model available", procName, 1);

        /* Correct for vertical disparity and save the result */
    if ((boxav = boxaApplyDisparity(dew, boxas, L_VERT, mapdir)) == NULL) {
        dewarpMinimize(dew);
        return ERROR_INT("boxa1 not made", procName, 1);
    }
    boxaDestroy(pboxad);
    *pboxad = boxav;
    pixv = NULL;
    pixh = NULL;
    if (debugfile && mapdir != 1)
        L_INFO("Reverse map direction; no debug output\n", procName);
    debug_out = debugfile && (mapdir == 1);
    if (debug_out) {
        PIX  *pix1;
        lept_rmdir("lept/dewboxa");  /* remove previous images */
        lept_mkdir("lept/dewboxa");
        pix1 = pixConvertTo32(pixs);
        pixRenderBoxaArb(pix1, boxas, 2, 255, 0, 0);
        pixWrite("/tmp/lept/dewboxa/01.png", pix1, IFF_PNG);
        pixDestroy(&pix1);
        pixv = pixApplyVertDisparity(dew, pixs, 255);
        pix1 = pixConvertTo32(pixv);
        pixRenderBoxaArb(pix1, boxav, 2, 0, 255, 0);
        pixWrite("/tmp/lept/dewboxa/02.png", pix1, IFF_PNG);
        pixDestroy(&pix1);
    }

        /* Optionally, correct for horizontal disparity */
    if (dewa->useboth && dew->hsuccess) {
        if (dew->hvalid == FALSE) {
            L_INFO("invalid horiz model for page %d\n", procName, pageno);
        } else {
            boxah = boxaApplyDisparity(dew, boxav, L_HORIZ, mapdir);
            if (!boxah) {
                L_ERROR("horiz disparity fails on page %d\n", procName, pageno);
            } else {
                boxaDestroy(pboxad);
                *pboxad = boxah;
                if (debug_out) {
                    PIX  *pix1;
                    pixh = pixApplyHorizDisparity(dew, pixv, 255);
                    pix1 = pixConvertTo32(pixh);
                    pixRenderBoxaArb(pix1, boxah, 2, 0, 0, 255);
                    pixWrite("/tmp/lept/dewboxa/03.png", pix1, IFF_PNG);
                    pixDestroy(&pixh);
                    pixDestroy(&pix1);
                }
            }
        }
    }

    if (debug_out) {
        pixDestroy(&pixv);
        dew1 = dewarpaGetDewarp(dewa, pageno);
        dewarpDebug(dew1, "lept/dewapply", 0);
        convertFilesToPdf("/tmp/lept/dewboxa", NULL, 135, 1.0, 0, 0,
                         "Dewarp Apply Disparity Boxa", debugfile);
        fprintf(stderr, "Dewarp Apply Disparity Boxa pdf file: %s\n",
                debugfile);
    }

        /* Get rid of the large full res disparity arrays */
    dewarpMinimize(dew);

    return 0;
}
Beispiel #12
0
/*!
 *  dewarpaApplyDisparity()
 *
 *      Input:  dewa
 *              pageno (of page model to be used; may be a ref model)
 *              pixs (image to be modified; can be 1, 8 or 32 bpp)
 *              grayin (gray value, from 0 to 255, for pixels brought in;
 *                      use -1 to use pixels on the boundary of pixs)
 *              x, y (origin for generation of disparity arrays)
 *              &pixd (<return> disparity corrected image)
 *              debugfile (use null to skip writing this)
 *      Return: 0 if OK, 1 on error (no models or ref models available)
 *
 *  Notes:
 *      (1) This applies the disparity arrays to the specified image.
 *      (2) Specify gray color for pixels brought in from the outside:
 *          0 is black, 255 is white.  Use -1 to select pixels from the
 *          boundary of the source image.
 *      (3) If the models and ref models have not been validated, this
 *          will do so by calling dewarpaInsertRefModels().
 *      (4) This works with both stripped and full resolution page models.
 *          If the full res disparity array(s) are missing, they are remade.
 *      (5) The caller must handle errors that are returned because there
 *          are no valid models or ref models for the page -- typically
 *          by using the input pixs.
 *      (6) If there is no model for @pageno, this will use the model for
 *          'refpage' and put the result in the dew for @pageno.
 *      (7) This populates the full resolution disparity arrays if
 *          necessary.  If x and/or y are positive, they are used,
 *          in conjunction with pixs, to determine the required
 *          slope-based extension of the full resolution disparity
 *          arrays in each direction.  When (x,y) == (0,0), all
 *          extension is to the right and down.  Nonzero values of (x,y)
 *          are useful for dewarping when pixs is deliberately undercropped.
 *      (8) Important: when applying disparity to a number of images,
 *          after calling this function and saving the resulting pixd,
 *          you should call dewarpMinimize(dew) on the dew for @pageno.
 *          This will remove pixs and pixd (or their clones) stored in dew,
 *          as well as the full resolution disparity arrays.  Together,
 *          these hold approximately 16 bytes for each pixel in pixs.
 */
l_int32
dewarpaApplyDisparity(L_DEWARPA   *dewa,
                      l_int32      pageno,
                      PIX         *pixs,
                      l_int32      grayin,
                      l_int32      x,
                      l_int32      y,
                      PIX        **ppixd,
                      const char  *debugfile)
{
L_DEWARP  *dew1, *dew;
PIX       *pixv, *pixh;

    PROCNAME("dewarpaApplyDisparity");

        /* Initialize the output with the input, so we'll have that
         * in case we can't apply the page model. */
    if (!ppixd)
        return ERROR_INT("&pixd not defined", procName, 1);
    *ppixd = pixClone(pixs);
    if (grayin > 255) {
        L_WARNING("invalid grayin = %d; clipping at 255\n", procName, grayin);
        grayin = 255;
    }

        /* Find the appropriate dew to use and fully populate its array(s) */
    if (dewarpaApplyInit(dewa, pageno, pixs, x, y, &dew, debugfile))
        return ERROR_INT("no model available", procName, 1);

        /* Correct for vertical disparity and save the result */
    if ((pixv = pixApplyVertDisparity(dew, pixs, grayin)) == NULL) {
        dewarpMinimize(dew);
        return ERROR_INT("pixv not made", procName, 1);
    }
    pixDestroy(ppixd);
    *ppixd = pixv;
    if (debugfile) {
        pixDisplayWithTitle(pixv, 300, 0, "pixv", 1);
        lept_rmdir("lept/dewapply");  /* remove previous images */
        lept_mkdir("lept/dewapply");
        pixWrite("/tmp/lept/dewapply/001.png", pixs, IFF_PNG);
        pixWrite("/tmp/lept/dewapply/002.png", pixv, IFF_PNG);
    }

        /* Optionally, correct for horizontal disparity */
    if (dewa->useboth && dew->hsuccess) {
        if (dew->hvalid == FALSE) {
            L_INFO("invalid horiz model for page %d\n", procName, pageno);
        } else {
            if ((pixh = pixApplyHorizDisparity(dew, pixv, grayin)) != NULL) {
                pixDestroy(ppixd);
                *ppixd = pixh;
                if (debugfile) {
                    pixDisplayWithTitle(pixh, 600, 0, "pixh", 1);
                    pixWrite("/tmp/lept/dewapply/003.png", pixh, IFF_PNG);
                }
            } else {
                L_ERROR("horiz disparity failed on page %d\n",
                        procName, pageno);
            }
        }
    }

    if (debugfile) {
        dew1 = dewarpaGetDewarp(dewa, pageno);
        dewarpDebug(dew1, "lept/dewapply", 0);
        convertFilesToPdf("/tmp/lept/dewapply", NULL, 135, 1.0, 0, 0,
                         "Dewarp Apply Disparity", debugfile);
        fprintf(stderr, "pdf file: %s\n", debugfile);
    }

        /* Get rid of the large full res disparity arrays */
    dewarpMinimize(dew);

    return 0;
}
Beispiel #13
0
l_int32 main(int    argc,
             char **argv)
{
L_DEWARP   *dew1, *dew2, *dew3;
L_DEWARPA  *dewa1, *dewa2, *dewa3;
PIX        *pixs, *pixn, *pixg, *pixb, *pixd;
PIX        *pixs2, *pixn2, *pixg2, *pixb2, *pixd2;
PIX        *pixd3, *pixc1, *pixc2;

/*    pixs = pixRead("1555-7.jpg"); */
    pixs = pixRead("cat-35.jpg");
    dewa1 = dewarpaCreate(40, 30, 1, 15, 10);
    dewarpaUseBothArrays(dewa1, 1);

        /* Normalize for varying background and binarize */
    pixn = pixBackgroundNormSimple(pixs, NULL, NULL);
    pixg = pixConvertRGBToGray(pixn, 0.5, 0.3, 0.2);
    pixb = pixThresholdToBinary(pixg, 130);

        /* Run the basic functions */
    dew1 = dewarpCreate(pixb, 35);
    dewarpaInsertDewarp(dewa1, dew1);
    dewarpBuildPageModel(dew1, "/tmp/dewarp_junk35.pdf");  /* debug output */
    dewarpPopulateFullRes(dew1, pixg, 0, 0);
    dewarpaApplyDisparity(dewa1, 35, pixg, 200, 0, 0, &pixd,
                          "/tmp/dewarp_debug_35.pdf");

        /* Normalize another image. */
/*    pixs2 = pixRead("1555-3.jpg"); */
    pixs2 = pixRead("cat-7.jpg");
    pixn2 = pixBackgroundNormSimple(pixs2, NULL, NULL);
    pixg2 = pixConvertRGBToGray(pixn2, 0.5, 0.3, 0.2);
    pixb2 = pixThresholdToBinary(pixg2, 130);

        /* Run the basic functions */
    dew2 = dewarpCreate(pixb2, 7);
    dewarpaInsertDewarp(dewa1, dew2);
    dewarpBuildPageModel(dew2, "/tmp/dewarp_junk7.pdf");
    dewarpaApplyDisparity(dewa1, 7, pixg, 200, 0, 0, &pixd2,
                          "/tmp/dewarp_debug_7.pdf");

        /* Serialize and deserialize dewarpa */
    dewarpaWrite("/tmp/dewarpa1.dewa", dewa1);
    dewa2 = dewarpaRead("/tmp/dewarpa1.dewa");
    dewarpaWrite("/tmp/dewarpa2.dewa", dewa2);
    dewa3 = dewarpaRead("/tmp/dewarpa2.dewa");
    dewarpDebug(dewa3->dewarp[7], "dew1", 7);
    dewarpaWrite("/tmp/dewarpa3.dewa", dewa3);

        /* Repopulate and show the vertical disparity arrays */
    dewarpPopulateFullRes(dew1, NULL, 0, 0);
    pixc1 = fpixRenderContours(dew1->fullvdispar, 2.0, 0.2);
    pixDisplay(pixc1, 1400, 900);
    dew3 = dewarpaGetDewarp(dewa2, 35);
    dewarpPopulateFullRes(dew3, pixs, 0, 0);
    pixc2 = fpixRenderContours(dew3->fullvdispar, 2.0, 0.2);
    pixDisplay(pixc2, 1400, 900);
    dewarpaApplyDisparity(dewa2, 35, pixb, 200, 0, 0, &pixd3,
                          "/tmp/dewarp_debug_35b.pdf");
    pixDisplay(pixd, 0, 1000);
    pixDisplay(pixd2, 600, 1000);
    pixDisplay(pixd3, 1200, 1000);
    pixDestroy(&pixd3);

    dewarpaDestroy(&dewa1);
    dewarpaDestroy(&dewa2);
    dewarpaDestroy(&dewa3);
    pixDestroy(&pixs);
    pixDestroy(&pixn);
    pixDestroy(&pixg);
    pixDestroy(&pixb);
    pixDestroy(&pixd);
    pixDestroy(&pixs2);
    pixDestroy(&pixn2);
    pixDestroy(&pixg2);
    pixDestroy(&pixb2);
    pixDestroy(&pixd2);
    pixDestroy(&pixc1);
    pixDestroy(&pixc2);
    return 0;
}