Leptonica 1.82.0
Image processing and image analysis suite
dewarp4.c
Go to the documentation of this file.
1/*====================================================================*
2 - Copyright (C) 2001 Leptonica. All rights reserved.
3 -
4 - Redistribution and use in source and binary forms, with or without
5 - modification, are permitted provided that the following conditions
6 - are met:
7 - 1. Redistributions of source code must retain the above copyright
8 - notice, this list of conditions and the following disclaimer.
9 - 2. Redistributions in binary form must reproduce the above
10 - copyright notice, this list of conditions and the following
11 - disclaimer in the documentation and/or other materials
12 - provided with the distribution.
13 -
14 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18 - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *====================================================================*/
26
57#ifdef HAVE_CONFIG_H
58#include <config_auto.h>
59#endif /* HAVE_CONFIG_H */
60
61#include <math.h>
62#include "allheaders.h"
63
64static l_int32 dewarpaTestForValidModel(L_DEWARPA *dewa, L_DEWARP *dew,
65 l_int32 notests);
66
67#ifndef NO_CONSOLE_IO
68#define DEBUG_INVALID_MODELS 0 /* set this to 1 for debugging */
69#endif /* !NO_CONSOLE_IO */
70
71 /* Special parameter value */
72static const l_int32 GrayInValue = 200;
73
74/*----------------------------------------------------------------------*
75 * Top-level single page dewarper *
76 *----------------------------------------------------------------------*/
99l_ok
101 l_int32 thresh,
102 l_int32 adaptive,
103 l_int32 useboth,
104 l_int32 check_columns,
105 PIX **ppixd,
106 L_DEWARPA **pdewa,
107 l_int32 debug)
108{
109L_DEWARPA *dewa;
110PIX *pixb;
111
112 PROCNAME("dewarpSinglePage");
113
114 if (!ppixd)
115 return ERROR_INT("&pixd not defined", procName, 1);
116 *ppixd = NULL;
117 if (pdewa) *pdewa = NULL;
118 if (!pixs)
119 return ERROR_INT("pixs not defined", procName, 1);
120
121 dewarpSinglePageInit(pixs, thresh, adaptive, useboth,
122 check_columns, &pixb, &dewa);
123 if (!pixb) {
124 dewarpaDestroy(&dewa);
125 return ERROR_INT("pixb not made", procName, 1);
126 }
127
128 dewarpSinglePageRun(pixs, pixb, dewa, ppixd, debug);
129
130 if (pdewa)
131 *pdewa = dewa;
132 else
133 dewarpaDestroy(&dewa);
134 pixDestroy(&pixb);
135 return 0;
136}
137
138
167l_ok
169 l_int32 thresh,
170 l_int32 adaptive,
171 l_int32 useboth,
172 l_int32 check_columns,
173 PIX **ppixb,
174 L_DEWARPA **pdewa)
175{
176PIX *pix1, *pix2;
177
178 PROCNAME("dewarpSinglePageInit");
179
180 if (ppixb) *ppixb = NULL;
181 if (pdewa) *pdewa = NULL;
182 if (!ppixb || !pdewa)
183 return ERROR_INT("&pixb and &dewa not both defined", procName, 1);
184 if (!pixs)
185 return ERROR_INT("pixs not defined", procName, 1);
186
187 /* Generate a binary image, if necessary */
188 if (pixGetDepth(pixs) > 1) {
189 if ((pix1 = pixConvertTo8(pixs, 0)) == NULL)
190 return ERROR_INT("pix1 not made", procName, 1);
191 if (adaptive)
192 pix2 = pixAdaptThresholdToBinary(pix1, NULL, 1.0);
193 else
194 pix2 = pixThresholdToBinary(pix1, thresh);
195 pixDestroy(&pix1);
196 if (!pix2)
197 return ERROR_INT("pix2 not made", procName, 1);
198 *ppixb = pix2;
199 } else {
200 *ppixb = pixClone(pixs);
201 }
202
203 *pdewa = dewarpaCreate(1, 0, 1, 0, -1);
204 dewarpaUseBothArrays(*pdewa, useboth);
205 dewarpaSetCheckColumns(*pdewa, check_columns);
206 return 0;
207}
208
209
229l_ok
231 PIX *pixb,
232 L_DEWARPA *dewa,
233 PIX **ppixd,
234 l_int32 debug)
235{
236const char *debugfile;
237l_int32 vsuccess, ret;
238L_DEWARP *dew;
239
240 PROCNAME("dewarpSinglePageRun");
241
242 if (!ppixd)
243 return ERROR_INT("&pixd not defined", procName, 1);
244 *ppixd = NULL;
245 if (!pixs)
246 return ERROR_INT("pixs not defined", procName, 1);
247 if (!pixb)
248 return ERROR_INT("pixb not defined", procName, 1);
249 if (!dewa)
250 return ERROR_INT("dewa not defined", procName, 1);
251
252 if (debug)
253 lept_mkdir("lept/dewarp");
254
255 /* Generate the page model */
256 dew = dewarpCreate(pixb, 0);
257 dewarpaInsertDewarp(dewa, dew);
258 debugfile = (debug) ? "/tmp/lept/dewarp/singlepage_model.pdf" : NULL;
259 dewarpBuildPageModel(dew, debugfile);
260 dewarpaModelStatus(dewa, 0, &vsuccess, NULL);
261 if (vsuccess == 0) {
262 L_ERROR("failure to build model for vertical disparity\n", procName);
263 *ppixd = pixCopy(NULL, pixs);
264 return 0;
265 }
266
267 /* Apply the page model */
268 debugfile = (debug) ? "/tmp/lept/dewarp/singlepage_apply.pdf" : NULL;
269 ret = dewarpaApplyDisparity(dewa, 0, pixs, 255, 0, 0, ppixd, debugfile);
270 if (ret)
271 L_ERROR("invalid model; failure to apply disparity\n", procName);
272 return 0;
273}
274
275
276/*----------------------------------------------------------------------*
277 * Operations on dewarpa *
278 *----------------------------------------------------------------------*/
295l_ok
297{
298l_int32 i;
299L_DEWARP *dew;
300NUMA *namodels, *napages;
301
302 PROCNAME("dewarpaListPages");
303
304 if (!dewa)
305 return ERROR_INT("dewa not defined", procName, 1);
306
307 numaDestroy(&dewa->namodels);
308 numaDestroy(&dewa->napages);
309 namodels = numaCreate(dewa->maxpage + 1);
310 napages = numaCreate(dewa->maxpage + 1);
311 dewa->namodels = namodels;
312 dewa->napages = napages;
313 for (i = 0; i <= dewa->maxpage; i++) {
314 if ((dew = dewarpaGetDewarp(dewa, i)) != NULL) {
315 if (dew->hasref == 0)
316 numaAddNumber(namodels, dew->pageno);
317 numaAddNumber(napages, dew->pageno);
318 }
319 }
320 return 0;
321}
322
323
347l_ok
349 l_int32 notests,
350 l_int32 debug)
351{
352l_int32 i, n, maxcurv, diffcurv, diffedge;
353L_DEWARP *dew;
354
355 PROCNAME("dewarpaSetValidModels");
356
357 if (!dewa)
358 return ERROR_INT("dewa not defined", procName, 1);
359
360 n = dewa->maxpage + 1;
361 for (i = 0; i < n; i++) {
362 if ((dew = dewarpaGetDewarp(dewa, i)) == NULL)
363 continue;
364
365 if (debug) {
366 if (dew->hasref == 1) {
367 L_INFO("page %d: has only a ref model\n", procName, i);
368 } else if (dew->vsuccess == 0) {
369 L_INFO("page %d: no model successfully built\n",
370 procName, i);
371 } else if (!notests) {
372 maxcurv = L_MAX(L_ABS(dew->mincurv), L_ABS(dew->maxcurv));
373 diffcurv = dew->maxcurv - dew->mincurv;
374 if (dewa->useboth && !dew->hsuccess)
375 L_INFO("page %d: useboth, but no horiz disparity\n",
376 procName, i);
377 if (maxcurv > dewa->max_linecurv)
378 L_INFO("page %d: max curvature %d > max_linecurv\n",
379 procName, i, diffcurv);
380 if (diffcurv < dewa->min_diff_linecurv)
381 L_INFO("page %d: diff curv %d < min_diff_linecurv\n",
382 procName, i, diffcurv);
383 if (diffcurv > dewa->max_diff_linecurv)
384 L_INFO("page %d: abs diff curv %d > max_diff_linecurv\n",
385 procName, i, diffcurv);
386 if (dew->hsuccess) {
387 if (L_ABS(dew->leftslope) > dewa->max_edgeslope)
388 L_INFO("page %d: abs left slope %d > max_edgeslope\n",
389 procName, i, dew->leftslope);
390 if (L_ABS(dew->rightslope) > dewa->max_edgeslope)
391 L_INFO("page %d: abs right slope %d > max_edgeslope\n",
392 procName, i, dew->rightslope);
393 diffedge = L_ABS(dew->leftcurv - dew->rightcurv);
394 if (L_ABS(dew->leftcurv) > dewa->max_edgecurv)
395 L_INFO("page %d: left curvature %d > max_edgecurv\n",
396 procName, i, dew->leftcurv);
397 if (L_ABS(dew->rightcurv) > dewa->max_edgecurv)
398 L_INFO("page %d: right curvature %d > max_edgecurv\n",
399 procName, i, dew->rightcurv);
400 if (diffedge > dewa->max_diff_edgecurv)
401 L_INFO("page %d: abs diff left-right curv %d > "
402 "max_diff_edgecurv\n", procName, i, diffedge);
403 }
404 }
405 }
406
407 dewarpaTestForValidModel(dewa, dew, notests);
408 }
409
410 return 0;
411}
412
413
453l_ok
455 l_int32 notests,
456 l_int32 debug)
457{
458l_int32 i, j, n, val, min, distdown, distup;
459L_DEWARP *dew;
460NUMA *na, *nah;
461
462 PROCNAME("dewarpaInsertRefModels");
463
464 if (!dewa)
465 return ERROR_INT("dewa not defined", procName, 1);
466 if (dewa->maxdist < 2)
467 L_INFO("maxdist < 2; no ref models can be used\n", procName);
468
469 /* Make an indicator numa for pages with valid models. */
470 dewarpaSetValidModels(dewa, notests, debug);
471 n = dewa->maxpage + 1;
472 na = numaMakeConstant(0, n);
473 for (i = 0; i < n; i++) {
474 dew = dewarpaGetDewarp(dewa, i);
475 if (dew && dew->vvalid)
476 numaReplaceNumber(na, i, 1);
477 }
478
479 /* Remove all existing ref models and restore models from cache */
481
482 /* Move invalid models to the cache, and insert reference dewarps
483 * for pages that need to borrow a model.
484 * First, try to find a valid model for each page. */
485 for (i = 0; i < n; i++) {
486 numaGetIValue(na, i, &val);
487 if (val == 1) continue; /* already has a valid model */
488 if ((dew = dewa->dewarp[i]) != NULL) { /* exists but is not valid; */
489 dewa->dewarpcache[i] = dew; /* move it to the cache */
490 dewa->dewarp[i] = NULL;
491 }
492 if (dewa->maxdist < 2) continue; /* can't use a ref model */
493 /* Look back for nearest model */
494 distdown = distup = dewa->maxdist + 1;
495 for (j = i - 2; j >= 0 && distdown > dewa->maxdist; j -= 2) {
496 numaGetIValue(na, j, &val);
497 if (val == 1) distdown = i - j;
498 }
499 /* Look ahead for nearest model */
500 for (j = i + 2; j < n && distup > dewa->maxdist; j += 2) {
501 numaGetIValue(na, j, &val);
502 if (val == 1) distup = j - i;
503 }
504 min = L_MIN(distdown, distup);
505 if (min > dewa->maxdist) continue; /* no valid model in range */
506 if (distdown <= distup)
507 dewarpaInsertDewarp(dewa, dewarpCreateRef(i, i - distdown));
508 else
509 dewarpaInsertDewarp(dewa, dewarpCreateRef(i, i + distup));
510 }
511 numaDestroy(&na);
512
513 /* If a valid model will do, we're finished. */
514 if (dewa->useboth == 0) {
515 dewa->modelsready = 1; /* validated */
516 return 0;
517 }
518
519 /* The request is useboth == 1. Now try to find an hvalid model */
520 nah = numaMakeConstant(0, n);
521 for (i = 0; i < n; i++) {
522 dew = dewarpaGetDewarp(dewa, i);
523 if (dew && dew->hvalid)
524 numaReplaceNumber(nah, i, 1);
525 }
526 for (i = 0; i < n; i++) {
527 numaGetIValue(nah, i, &val);
528 if (val == 1) continue; /* already has a hvalid model */
529 if (dewa->maxdist < 2) continue; /* can't use a ref model */
530 distdown = distup = 100000;
531 for (j = i - 2; j >= 0; j -= 2) { /* look back for nearest model */
532 numaGetIValue(nah, j, &val);
533 if (val == 1) {
534 distdown = i - j;
535 break;
536 }
537 }
538 for (j = i + 2; j < n; j += 2) { /* look ahead for nearest model */
539 numaGetIValue(nah, j, &val);
540 if (val == 1) {
541 distup = j - i;
542 break;
543 }
544 }
545 min = L_MIN(distdown, distup);
546 if (min > dewa->maxdist) continue; /* no hvalid model within range */
547
548 /* We can replace the existing valid model with an hvalid model.
549 * If it's not a reference, save it in the cache. */
550 if ((dew = dewarpaGetDewarp(dewa, i)) == NULL) {
551 L_ERROR("dew is null for page %d!\n", procName, i);
552 } else {
553 if (dew->hasref == 0) { /* not a ref model */
554 dewa->dewarpcache[i] = dew; /* move it to the cache */
555 dewa->dewarp[i] = NULL; /* must null the ptr */
556 }
557 }
558 if (distdown <= distup) /* insert the hvalid ref model */
559 dewarpaInsertDewarp(dewa, dewarpCreateRef(i, i - distdown));
560 else
561 dewarpaInsertDewarp(dewa, dewarpCreateRef(i, i + distup));
562 }
563 numaDestroy(&nah);
564
565 dewa->modelsready = 1; /* validated */
566 return 0;
567}
568
569
584l_ok
586{
587l_int32 i;
588L_DEWARP *dew;
589
590 PROCNAME("dewarpaStripRefModels");
591
592 if (!dewa)
593 return ERROR_INT("dewa not defined", procName, 1);
594
595 for (i = 0; i <= dewa->maxpage; i++) {
596 if ((dew = dewarpaGetDewarp(dewa, i)) != NULL) {
597 if (dew->hasref)
598 dewarpDestroy(&dewa->dewarp[i]);
599 }
600 }
601 dewa->modelsready = 0;
602
603 /* Regenerate the page lists */
604 dewarpaListPages(dewa);
605 return 0;
606}
607
608
625l_ok
627{
628l_int32 i;
629L_DEWARP *dew;
630
631 PROCNAME("dewarpaRestoreModels");
632
633 if (!dewa)
634 return ERROR_INT("dewa not defined", procName, 1);
635
636 /* Strip out ref models. Then only real models will be in the
637 * primary dewarp array. */
639
640 /* The cache holds only real models, which are not necessarily valid. */
641 for (i = 0; i <= dewa->maxpage; i++) {
642 if ((dew = dewa->dewarpcache[i]) != NULL) {
643 if (dewa->dewarp[i]) {
644 L_ERROR("dew in both cache and main array!: page %d\n",
645 procName, i);
646 } else {
647 dewa->dewarp[i] = dew;
648 dewa->dewarpcache[i] = NULL;
649 }
650 }
651 }
652 dewa->modelsready = 0; /* new ref models not yet inserted */
653
654 /* Regenerate the page lists */
655 dewarpaListPages(dewa);
656 return 0;
657}
658
659
660/*----------------------------------------------------------------------*
661 * Dewarp debugging output *
662 *----------------------------------------------------------------------*/
670l_ok
671dewarpaInfo(FILE *fp,
672 L_DEWARPA *dewa)
673{
674l_int32 i, n, pageno, nnone, nvsuccess, nvvalid, nhsuccess, nhvalid, nref;
675L_DEWARP *dew;
676
677 PROCNAME("dewarpaInfo");
678
679 if (!fp)
680 return ERROR_INT("dewa not defined", procName, 1);
681 if (!dewa)
682 return ERROR_INT("dewa not defined", procName, 1);
683
684 fprintf(fp, "\nDewarpaInfo: %p\n", dewa);
685 fprintf(fp, "nalloc = %d, maxpage = %d\n", dewa->nalloc, dewa->maxpage);
686 fprintf(fp, "sampling = %d, redfactor = %d, minlines = %d\n",
687 dewa->sampling, dewa->redfactor, dewa->minlines);
688 fprintf(fp, "maxdist = %d, useboth = %d\n",
689 dewa->maxdist, dewa->useboth);
690
691 dewarpaModelStats(dewa, &nnone, &nvsuccess, &nvvalid,
692 &nhsuccess, &nhvalid, &nref);
693 n = numaGetCount(dewa->napages);
694 lept_stderr("Total number of pages with a dew = %d\n", n);
695 lept_stderr("Number of pages without any models = %d\n", nnone);
696 lept_stderr("Number of pages with a vert model = %d\n", nvsuccess);
697 lept_stderr("Number of pages with a valid vert model = %d\n", nvvalid);
698 lept_stderr("Number of pages with both models = %d\n", nhsuccess);
699 lept_stderr("Number of pages with both models valid = %d\n", nhvalid);
700 lept_stderr("Number of pages with a ref model = %d\n", nref);
701
702 for (i = 0; i < n; i++) {
703 numaGetIValue(dewa->napages, i, &pageno);
704 if ((dew = dewarpaGetDewarp(dewa, pageno)) == NULL)
705 continue;
706 lept_stderr("Page: %d\n", dew->pageno);
707 lept_stderr(" hasref = %d, refpage = %d\n",
708 dew->hasref, dew->refpage);
709 lept_stderr(" nlines = %d\n", dew->nlines);
710 lept_stderr(" w = %d, h = %d, nx = %d, ny = %d\n",
711 dew->w, dew->h, dew->nx, dew->ny);
712 if (dew->sampvdispar)
713 lept_stderr(" Vertical disparity builds:\n"
714 " (min,max,abs-diff) line curvature = (%d,%d,%d)\n",
715 dew->mincurv, dew->maxcurv, dew->maxcurv - dew->mincurv);
716 if (dew->samphdispar)
717 lept_stderr(" Horizontal disparity builds:\n"
718 " left edge slope = %d, right edge slope = %d\n"
719 " (left,right,abs-diff) edge curvature = (%d,%d,%d)\n",
720 dew->leftslope, dew->rightslope, dew->leftcurv,
721 dew->rightcurv, L_ABS(dew->leftcurv - dew->rightcurv));
722 }
723 return 0;
724}
725
726
762l_ok
764 l_int32 *pnnone,
765 l_int32 *pnvsuccess,
766 l_int32 *pnvvalid,
767 l_int32 *pnhsuccess,
768 l_int32 *pnhvalid,
769 l_int32 *pnref)
770{
771l_int32 i, n, pageno, nnone, nvsuccess, nvvalid, nhsuccess, nhvalid, nref;
772L_DEWARP *dew;
773
774 PROCNAME("dewarpaModelStats");
775
776 if (!dewa)
777 return ERROR_INT("dewa not defined", procName, 1);
778
779 dewarpaListPages(dewa);
780 n = numaGetCount(dewa->napages);
781 nnone = nref = nvsuccess = nvvalid = nhsuccess = nhvalid = 0;
782 for (i = 0; i < n; i++) {
783 numaGetIValue(dewa->napages, i, &pageno);
784 dew = dewarpaGetDewarp(dewa, pageno);
785 if (!dew) {
786 nnone++;
787 continue;
788 }
789 if (dew->hasref == 1)
790 nref++;
791 if (dew->vsuccess == 1)
792 nvsuccess++;
793 if (dew->hsuccess == 1)
794 nhsuccess++;
795 dewarpaTestForValidModel(dewa, dew, 0);
796 if (dew->vvalid == 1)
797 nvvalid++;
798 if (dew->hvalid == 1)
799 nhvalid++;
800 }
801
802 if (pnnone) *pnnone = nnone;
803 if (pnref) *pnref = nref;
804 if (pnvsuccess) *pnvsuccess = nvsuccess;
805 if (pnvvalid) *pnvvalid = nvvalid;
806 if (pnhsuccess) *pnhsuccess = nhsuccess;
807 if (pnhvalid) *pnhvalid = nhvalid;
808 return 0;
809}
810
811
830static l_int32
832 L_DEWARP *dew,
833 l_int32 notests)
834{
835l_int32 maxcurv, diffcurv, diffedge;
836
837 PROCNAME("dewarpaTestForValidModel");
838
839 if (!dewa || !dew)
840 return ERROR_INT("dewa and dew not both defined", procName, 1);
841
842 if (notests) {
843 dew->vvalid = dew->vsuccess;
844 dew->hvalid = dew->hsuccess;
845 return 0;
846 }
847
848 /* No actual model was built */
849 if (dew->vsuccess == 0) return 0;
850
851 /* Was previously found not to have a valid model */
852 if (dew->hasref == 1) return 0;
853
854 /* vsuccess == 1; a vertical (line) model exists.
855 * First test that the vertical curvatures are within allowed
856 * bounds. Note that all curvatures are signed.*/
857 maxcurv = L_MAX(L_ABS(dew->mincurv), L_ABS(dew->maxcurv));
858 diffcurv = dew->maxcurv - dew->mincurv;
859 if (maxcurv <= dewa->max_linecurv &&
860 diffcurv >= dewa->min_diff_linecurv &&
861 diffcurv <= dewa->max_diff_linecurv) {
862 dew->vvalid = 1;
863 } else {
864 L_INFO("invalid vert model for page %d:\n", procName, dew->pageno);
865#if DEBUG_INVALID_MODELS
866 lept_stderr(" max line curv = %d, max allowed = %d\n",
867 maxcurv, dewa->max_linecurv);
868 lept_stderr(" diff line curv = %d, max allowed = %d\n",
869 diffcurv, dewa->max_diff_linecurv);
870#endif /* DEBUG_INVALID_MODELS */
871 }
872
873 /* If a horizontal (edge) model exists, test for validity. */
874 if (dew->hsuccess) {
875 diffedge = L_ABS(dew->leftcurv - dew->rightcurv);
876 if (L_ABS(dew->leftslope) <= dewa->max_edgeslope &&
877 L_ABS(dew->rightslope) <= dewa->max_edgeslope &&
878 L_ABS(dew->leftcurv) <= dewa->max_edgecurv &&
879 L_ABS(dew->rightcurv) <= dewa->max_edgecurv &&
880 diffedge <= dewa->max_diff_edgecurv) {
881 dew->hvalid = 1;
882 } else {
883 L_INFO("invalid horiz model for page %d:\n", procName, dew->pageno);
884#if DEBUG_INVALID_MODELS
885 lept_stderr(" left edge slope = %d, max allowed = %d\n",
886 dew->leftslope, dewa->max_edgeslope);
887 lept_stderr(" right edge slope = %d, max allowed = %d\n",
888 dew->rightslope, dewa->max_edgeslope);
889 lept_stderr(" left edge curv = %d, max allowed = %d\n",
890 dew->leftcurv, dewa->max_edgecurv);
891 lept_stderr(" right edge curv = %d, max allowed = %d\n",
892 dew->rightcurv, dewa->max_edgecurv);
893 lept_stderr(" diff edge curv = %d, max allowed = %d\n",
894 diffedge, dewa->max_diff_edgecurv);
895#endif /* DEBUG_INVALID_MODELS */
896 }
897 }
898
899 return 0;
900}
901
902
918l_ok
920 l_float32 scalefact,
921 l_int32 first,
922 l_int32 last)
923{
924char buf[256];
925l_int32 i, svd, shd;
926L_BMF *bmf;
927L_DEWARP *dew;
928PIX *pixv, *pixvs, *pixh, *pixhs, *pixt, *pixd;
929PIXA *pixa;
930
931 PROCNAME("dewarpaShowArrays");
932
933 if (!dewa)
934 return ERROR_INT("dew not defined", procName, 1);
935 if (first < 0 || first > dewa->maxpage)
936 return ERROR_INT("first out of bounds", procName, 1);
937 if (last <= 0 || last > dewa->maxpage) last = dewa->maxpage;
938 if (last < first)
939 return ERROR_INT("last < first", procName, 1);
940
941 lept_rmdir("lept/dewarp1"); /* temp directory for contour plots */
942 lept_mkdir("lept/dewarp1");
943 if ((bmf = bmfCreate(NULL, 8)) == NULL)
944 L_ERROR("bmf not made; page info not displayed", procName);
945
946 lept_stderr("Generating contour plots\n");
947 for (i = first; i <= last; i++) {
948 if (i && ((i % 10) == 0))
949 lept_stderr(" .. %d", i);
950 dew = dewarpaGetDewarp(dewa, i);
951 if (!dew) continue;
952 if (dew->hasref == 1) continue;
953 svd = shd = 0;
954 if (dew->sampvdispar) svd = 1;
955 if (dew->samphdispar) shd = 1;
956 if (!svd) {
957 L_ERROR("sampvdispar not made for page %d!\n", procName, i);
958 continue;
959 }
960
961 /* Generate contour plots at reduced resolution */
962 dewarpPopulateFullRes(dew, NULL, 0, 0);
963 pixv = fpixRenderContours(dew->fullvdispar, 3.0, 0.15);
964 pixvs = pixScaleBySampling(pixv, scalefact, scalefact);
965 pixDestroy(&pixv);
966 if (shd) {
967 pixh = fpixRenderContours(dew->fullhdispar, 3.0, 0.15);
968 pixhs = pixScaleBySampling(pixh, scalefact, scalefact);
969 pixDestroy(&pixh);
970 }
971 dewarpMinimize(dew);
972
973 /* Save side-by-side */
974 pixa = pixaCreate(2);
975 pixaAddPix(pixa, pixvs, L_INSERT);
976 if (shd)
977 pixaAddPix(pixa, pixhs, L_INSERT);
978 pixt = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 30, 2);
979 snprintf(buf, sizeof(buf), "Page %d", i);
980 pixd = pixAddSingleTextblock(pixt, bmf, buf, 0x0000ff00,
981 L_ADD_BELOW, NULL);
982 snprintf(buf, sizeof(buf), "/tmp/lept/dewarp1/arrays_%04d.png", i);
983 pixWriteDebug(buf, pixd, IFF_PNG);
984 pixaDestroy(&pixa);
985 pixDestroy(&pixt);
986 pixDestroy(&pixd);
987 }
988 bmfDestroy(&bmf);
989 lept_stderr("\n");
990
991 lept_stderr("Generating pdf of contour plots\n");
992 convertFilesToPdf("/tmp/lept/dewarp1", "arrays_", 90, 1.0, L_FLATE_ENCODE,
993 0, "Disparity arrays", "/tmp/lept/disparity_arrays.pdf");
994 lept_stderr("Output written to: /tmp/lept/disparity_arrays.pdf\n");
995 return 0;
996}
997
998
1014l_ok
1016 const char *subdirs,
1017 l_int32 index)
1018{
1019char fname[256];
1020char *outdir;
1021l_int32 svd, shd;
1022PIX *pixv, *pixh;
1023
1024 PROCNAME("dewarpDebug");
1025
1026 if (!dew)
1027 return ERROR_INT("dew not defined", procName, 1);
1028 if (!subdirs)
1029 return ERROR_INT("subdirs not defined", procName, 1);
1030
1031 lept_stderr("pageno = %d, hasref = %d, refpage = %d\n",
1032 dew->pageno, dew->hasref, dew->refpage);
1033 lept_stderr("sampling = %d, redfactor = %d, minlines = %d\n",
1034 dew->sampling, dew->redfactor, dew->minlines);
1035 svd = shd = 0;
1036 if (!dew->hasref) {
1037 if (dew->sampvdispar) svd = 1;
1038 if (dew->samphdispar) shd = 1;
1039 lept_stderr("sampv = %d, samph = %d\n", svd, shd);
1040 lept_stderr("w = %d, h = %d\n", dew->w, dew->h);
1041 lept_stderr("nx = %d, ny = %d\n", dew->nx, dew->ny);
1042 lept_stderr("nlines = %d\n", dew->nlines);
1043 if (svd) {
1044 lept_stderr("(min,max,abs-diff) line curvature = (%d,%d,%d)\n",
1045 dew->mincurv, dew->maxcurv, dew->maxcurv - dew->mincurv);
1046 }
1047 if (shd) {
1048 lept_stderr("(left edge slope = %d, right edge slope = %d\n",
1049 dew->leftslope, dew->rightslope);
1050 lept_stderr("(left,right,abs-diff) edge curvature = "
1051 "(%d,%d,%d)\n", dew->leftcurv, dew->rightcurv,
1052 L_ABS(dew->leftcurv - dew->rightcurv));
1053 }
1054 }
1055 if (!svd && !shd) {
1056 lept_stderr("No disparity arrays\n");
1057 return 0;
1058 }
1059
1060 dewarpPopulateFullRes(dew, NULL, 0, 0);
1061 lept_mkdir(subdirs);
1062 outdir = pathJoin("/tmp", subdirs);
1063 if (svd) {
1064 pixv = fpixRenderContours(dew->fullvdispar, 3.0, 0.15);
1065 snprintf(fname, sizeof(fname), "%s/pixv_%d.png", outdir, index);
1066 pixWriteDebug(fname, pixv, IFF_PNG);
1067 pixDestroy(&pixv);
1068 }
1069 if (shd) {
1070 pixh = fpixRenderContours(dew->fullhdispar, 3.0, 0.15);
1071 snprintf(fname, sizeof(fname), "%s/pixh_%d.png", outdir, index);
1072 pixWriteDebug(fname, pixh, IFF_PNG);
1073 pixDestroy(&pixh);
1074 }
1075 LEPT_FREE(outdir);
1076 return 0;
1077}
1078
1079
1101l_ok
1103 SARRAY *sa,
1104 BOXA *boxa,
1105 l_int32 firstpage,
1106 l_int32 lastpage,
1107 const char *pdfout)
1108{
1109char bufstr[256];
1110l_int32 i, modelpage;
1111L_BMF *bmf;
1112BOX *box;
1113L_DEWARP *dew;
1114PIX *pixs, *pixc, *pixd, *pixt1, *pixt2;
1115PIXA *pixa;
1116
1117 PROCNAME("dewarpShowResults");
1118
1119 if (!dewa)
1120 return ERROR_INT("dewa not defined", procName, 1);
1121 if (!sa)
1122 return ERROR_INT("sa not defined", procName, 1);
1123 if (!pdfout)
1124 return ERROR_INT("pdfout not defined", procName, 1);
1125 if (firstpage > lastpage)
1126 return ERROR_INT("invalid first/last page numbers", procName, 1);
1127
1128 lept_rmdir("lept/dewarp_pdfout");
1129 lept_mkdir("lept/dewarp_pdfout");
1130 bmf = bmfCreate(NULL, 6);
1131
1132 lept_stderr("Dewarping and generating s/by/s view\n");
1133 for (i = firstpage; i <= lastpage; i++) {
1134 if (i && (i % 10 == 0)) lept_stderr(".. %d ", i);
1135 pixs = pixReadIndexed(sa, i);
1136 if (boxa) {
1137 box = boxaGetBox(boxa, i, L_CLONE);
1138 pixc = pixClipRectangle(pixs, box, NULL);
1139 boxDestroy(&box);
1140 }
1141 else
1142 pixc = pixClone(pixs);
1143 dew = dewarpaGetDewarp(dewa, i);
1144 pixd = NULL;
1145 if (dew) {
1146 dewarpaApplyDisparity(dewa, dew->pageno, pixc,
1147 GrayInValue, 0, 0, &pixd, NULL);
1148 dewarpMinimize(dew);
1149 }
1150 pixa = pixaCreate(2);
1151 pixaAddPix(pixa, pixc, L_INSERT);
1152 if (pixd)
1153 pixaAddPix(pixa, pixd, L_INSERT);
1154 pixt1 = pixaDisplayTiledAndScaled(pixa, 32, 500, 2, 0, 35, 2);
1155 if (dew) {
1156 modelpage = (dew->hasref) ? dew->refpage : dew->pageno;
1157 snprintf(bufstr, sizeof(bufstr), "Page %d; using %d\n",
1158 i, modelpage);
1159 }
1160 else
1161 snprintf(bufstr, sizeof(bufstr), "Page %d; no dewarp\n", i);
1162 pixt2 = pixAddSingleTextblock(pixt1, bmf, bufstr, 0x0000ff00,
1163 L_ADD_BELOW, 0);
1164 snprintf(bufstr, sizeof(bufstr), "/tmp/lept/dewarp_pdfout/%05d", i);
1165 pixWriteDebug(bufstr, pixt2, IFF_JFIF_JPEG);
1166 pixaDestroy(&pixa);
1167 pixDestroy(&pixs);
1168 pixDestroy(&pixt1);
1169 pixDestroy(&pixt2);
1170 }
1171 lept_stderr("\n");
1172
1173 lept_stderr("Generating pdf of result\n");
1174 convertFilesToPdf("/tmp/lept/dewarp_pdfout", NULL, 100, 1.0, L_JPEG_ENCODE,
1175 0, "Dewarp sequence", pdfout);
1176 lept_stderr("Output written to: %s\n", pdfout);
1177 bmfDestroy(&bmf);
1178 return 0;
1179}
void bmfDestroy(L_BMF **pbmf)
bmfDestroy()
Definition: bmf.c:169
L_BMF * bmfCreate(const char *dir, l_int32 fontsize)
bmfCreate()
Definition: bmf.c:117
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:779
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:282
L_DEWARP * dewarpaGetDewarp(L_DEWARPA *dewa, l_int32 index)
dewarpaGetDewarp()
Definition: dewarp1.c:911
l_ok dewarpaUseBothArrays(L_DEWARPA *dewa, l_int32 useboth)
dewarpaUseBothArrays()
Definition: dewarp1.c:1044
L_DEWARP * dewarpCreateRef(l_int32 pageno, l_int32 refpage)
dewarpCreateRef()
Definition: dewarp1.c:498
void dewarpaDestroy(L_DEWARPA **pdewa)
dewarpaDestroy()
Definition: dewarp1.c:730
l_ok dewarpaInsertDewarp(L_DEWARPA *dewa, L_DEWARP *dew)
dewarpaInsertDewarp()
Definition: dewarp1.c:812
L_DEWARP * dewarpCreate(PIX *pixs, l_int32 pageno)
dewarpCreate()
Definition: dewarp1.c:459
void dewarpDestroy(L_DEWARP **pdew)
dewarpDestroy()
Definition: dewarp1.c:518
l_ok dewarpaSetCheckColumns(L_DEWARPA *dewa, l_int32 check_columns)
dewarpaSetCheckColumns()
Definition: dewarp1.c:1083
L_DEWARPA * dewarpaCreate(l_int32 nptrs, l_int32 sampling, l_int32 redfactor, l_int32 minlines, l_int32 maxdist)
dewarpaCreate()
Definition: dewarp1.c:580
l_ok dewarpBuildPageModel(L_DEWARP *dew, const char *debugfile)
dewarpBuildPageModel()
Definition: dewarp2.c:156
l_ok dewarpaModelStatus(L_DEWARPA *dewa, l_int32 pageno, l_int32 *pvsuccess, l_int32 *phsuccess)
dewarpaModelStatus()
Definition: dewarp2.c:1919
l_ok dewarpaApplyDisparity(L_DEWARPA *dewa, l_int32 pageno, PIX *pixs, l_int32 grayin, l_int32 x, l_int32 y, PIX **ppixd, const char *debugfile)
dewarpaApplyDisparity()
Definition: dewarp3.c:116
l_ok dewarpMinimize(L_DEWARP *dew)
dewarpMinimize()
Definition: dewarp3.c:731
l_ok dewarpPopulateFullRes(L_DEWARP *dew, PIX *pix, l_int32 x, l_int32 y)
dewarpPopulateFullRes()
Definition: dewarp3.c:787
l_ok dewarpaStripRefModels(L_DEWARPA *dewa)
dewarpaStripRefModels()
Definition: dewarp4.c:585
l_ok dewarpaInfo(FILE *fp, L_DEWARPA *dewa)
dewarpaInfo()
Definition: dewarp4.c:671
l_ok dewarpSinglePageRun(PIX *pixs, PIX *pixb, L_DEWARPA *dewa, PIX **ppixd, l_int32 debug)
dewarpSinglePageRun()
Definition: dewarp4.c:230
l_ok dewarpaShowArrays(L_DEWARPA *dewa, l_float32 scalefact, l_int32 first, l_int32 last)
dewarpaShowArrays()
Definition: dewarp4.c:919
l_ok dewarpaListPages(L_DEWARPA *dewa)
dewarpaListPages()
Definition: dewarp4.c:296
l_ok dewarpaSetValidModels(L_DEWARPA *dewa, l_int32 notests, l_int32 debug)
dewarpaSetValidModels()
Definition: dewarp4.c:348
l_ok dewarpDebug(L_DEWARP *dew, const char *subdirs, l_int32 index)
dewarpDebug()
Definition: dewarp4.c:1015
l_ok dewarpaModelStats(L_DEWARPA *dewa, l_int32 *pnnone, l_int32 *pnvsuccess, l_int32 *pnvvalid, l_int32 *pnhsuccess, l_int32 *pnhvalid, l_int32 *pnref)
dewarpaModelStats()
Definition: dewarp4.c:763
l_ok dewarpSinglePage(PIX *pixs, l_int32 thresh, l_int32 adaptive, l_int32 useboth, l_int32 check_columns, PIX **ppixd, L_DEWARPA **pdewa, l_int32 debug)
dewarpSinglePage()
Definition: dewarp4.c:100
l_ok dewarpaInsertRefModels(L_DEWARPA *dewa, l_int32 notests, l_int32 debug)
dewarpaInsertRefModels()
Definition: dewarp4.c:454
l_ok dewarpaRestoreModels(L_DEWARPA *dewa)
dewarpaRestoreModels()
Definition: dewarp4.c:626
l_ok dewarpSinglePageInit(PIX *pixs, l_int32 thresh, l_int32 adaptive, l_int32 useboth, l_int32 check_columns, PIX **ppixb, L_DEWARPA **pdewa)
dewarpSinglePageInit()
Definition: dewarp4.c:168
l_ok dewarpShowResults(L_DEWARPA *dewa, SARRAY *sa, BOXA *boxa, l_int32 firstpage, l_int32 lastpage, const char *pdfout)
dewarpShowResults()
Definition: dewarp4.c:1102
static l_int32 dewarpaTestForValidModel(L_DEWARPA *dewa, L_DEWARP *dew, l_int32 notests)
dewarpaTestForValidModel()
Definition: dewarp4.c:831
PIX * fpixRenderContours(FPIX *fpixs, l_float32 incr, l_float32 proxim)
fpixRenderContours()
Definition: graphics.c:2811
PIX * pixAdaptThresholdToBinary(PIX *pixs, PIX *pixm, l_float32 gamma)
pixAdaptThresholdToBinary()
Definition: grayquant.c:730
PIX * pixThresholdToBinary(PIX *pixs, l_int32 thresh)
pixThresholdToBinary()
Definition: grayquant.c:447
@ L_FLATE_ENCODE
Definition: imageio.h:161
@ L_JPEG_ENCODE
Definition: imageio.h:159
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:478
l_ok numaReplaceNumber(NUMA *na, l_int32 index, l_float32 val)
numaReplaceNumber()
Definition: numabasic.c:627
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:658
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:754
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
NUMA * numaMakeConstant(l_float32 val, l_int32 size)
numaMakeConstant()
Definition: numafunc1.c:851
l_ok convertFilesToPdf(const char *dirname, const char *substr, l_int32 res, l_float32 scalefactor, l_int32 type, l_int32 quality, const char *title, const char *fileout)
convertFilesToPdf()
Definition: pdfio1.c:253
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:1026
@ L_ADD_BELOW
Definition: pix.h:1210
@ L_CLONE
Definition: pix.h:713
@ L_INSERT
Definition: pix.h:711
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:506
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:412
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:167
PIX * pixaDisplayTiledAndScaled(PIXA *pixa, l_int32 outdepth, l_int32 tilewidth, l_int32 ncols, l_int32 background, l_int32 spacing, l_int32 border)
pixaDisplayTiledAndScaled()
Definition: pixafunc2.c:1045
PIX * pixaDisplayTiledInRows(PIXA *pixa, l_int32 outdepth, l_int32 maxwidth, l_float32 scalefactor, l_int32 background, l_int32 spacing, l_int32 border)
pixaDisplayTiledInRows()
Definition: pixafunc2.c:746
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3133
PIX * pixReadIndexed(SARRAY *sa, l_int32 index)
pixReadIndexed()
Definition: readfile.c:281
PIX * pixScaleBySampling(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleBySampling()
Definition: scale1.c:1338
Definition: pix.h:481
Definition: pix.h:492
Definition: bmf.h:47
l_int32 minlines
Definition: dewarp.h:168
struct FPix * fullvdispar
Definition: dewarp.h:158
l_int32 mincurv
Definition: dewarp.h:170
l_int32 pageno
Definition: dewarp.h:165
l_int32 vsuccess
Definition: dewarp.h:180
l_int32 hasref
Definition: dewarp.h:178
l_int32 h
Definition: dewarp.h:164
l_int32 sampling
Definition: dewarp.h:166
l_int32 hsuccess
Definition: dewarp.h:181
l_int32 leftcurv
Definition: dewarp.h:174
l_int32 vvalid
Definition: dewarp.h:183
l_int32 w
Definition: dewarp.h:163
l_int32 redfactor
Definition: dewarp.h:167
l_int32 nx
Definition: dewarp.h:176
l_int32 nlines
Definition: dewarp.h:169
l_int32 hvalid
Definition: dewarp.h:184
l_int32 maxcurv
Definition: dewarp.h:171
l_int32 refpage
Definition: dewarp.h:179
struct FPix * fullhdispar
Definition: dewarp.h:159
struct FPix * sampvdispar
Definition: dewarp.h:155
l_int32 ny
Definition: dewarp.h:177
struct FPix * samphdispar
Definition: dewarp.h:156
l_int32 rightcurv
Definition: dewarp.h:175
l_int32 leftslope
Definition: dewarp.h:172
l_int32 rightslope
Definition: dewarp.h:173
l_int32 min_diff_linecurv
Definition: dewarp.h:129
l_int32 maxdist
Definition: dewarp.h:126
struct L_Dewarp ** dewarp
Definition: dewarp.h:117
l_int32 max_diff_linecurv
Definition: dewarp.h:131
l_int32 sampling
Definition: dewarp.h:124
l_int32 max_edgeslope
Definition: dewarp.h:133
l_int32 maxpage
Definition: dewarp.h:116
l_int32 max_edgecurv
Definition: dewarp.h:135
struct L_Dewarp ** dewarpcache
Definition: dewarp.h:118
l_int32 minlines
Definition: dewarp.h:125
l_int32 nalloc
Definition: dewarp.h:115
struct Numa * namodels
Definition: dewarp.h:119
l_int32 max_diff_edgecurv
Definition: dewarp.h:137
l_int32 max_linecurv
Definition: dewarp.h:127
struct Numa * napages
Definition: dewarp.h:121
l_int32 redfactor
Definition: dewarp.h:123
l_int32 modelsready
Definition: dewarp.h:144
l_int32 useboth
Definition: dewarp.h:139
Definition: array.h:71
Definition: pix.h:139
Definition: pix.h:456
Definition: array.h:127
PIX * pixAddSingleTextblock(PIX *pixs, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 location, l_int32 *poverflow)
pixAddSingleTextblock()
Definition: textops.c:120
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
l_int32 lept_rmdir(const char *subdir)
lept_rmdir()
Definition: utils2.c:2295
char * pathJoin(const char *dir, const char *fname)
pathJoin()
Definition: utils2.c:2973
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:2218