Leptonica  1.77.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 #include <math.h>
58 #include "allheaders.h"
59 
60 static l_int32 dewarpaTestForValidModel(L_DEWARPA *dewa, L_DEWARP *dew,
61  l_int32 notests);
62 
63 #ifndef NO_CONSOLE_IO
64 #define DEBUG_INVALID_MODELS 0 /* set this to 1 for debugging */
65 #endif /* !NO_CONSOLE_IO */
66 
67  /* Special parameter values */
68 static const l_int32 GRAYIN_VALUE = 200;
69 
70 
71 /*----------------------------------------------------------------------*
72  * Top-level single page dewarper *
73  *----------------------------------------------------------------------*/
96 l_ok
98  l_int32 thresh,
99  l_int32 adaptive,
100  l_int32 useboth,
101  l_int32 check_columns,
102  PIX **ppixd,
103  L_DEWARPA **pdewa,
104  l_int32 debug)
105 {
106 L_DEWARPA *dewa;
107 PIX *pixb;
108 
109  PROCNAME("dewarpSinglePage");
110 
111  if (!ppixd)
112  return ERROR_INT("&pixd not defined", procName, 1);
113  *ppixd = NULL;
114  if (pdewa) *pdewa = NULL;
115  if (!pixs)
116  return ERROR_INT("pixs not defined", procName, 1);
117 
118  dewarpSinglePageInit(pixs, thresh, adaptive, useboth,
119  check_columns, &pixb, &dewa);
120  if (!pixb) {
122  return ERROR_INT("pixb not made", procName, 1);
123  }
124 
125  dewarpSinglePageRun(pixs, pixb, dewa, ppixd, debug);
126 
127  if (pdewa)
128  *pdewa = dewa;
129  else
131  pixDestroy(&pixb);
132  return 0;
133 }
134 
135 
164 l_ok
166  l_int32 thresh,
167  l_int32 adaptive,
168  l_int32 useboth,
169  l_int32 check_columns,
170  PIX **ppixb,
171  L_DEWARPA **pdewa)
172 {
173 PIX *pix1;
174 
175  PROCNAME("dewarpSinglePageInit");
176 
177  if (ppixb) *ppixb = NULL;
178  if (pdewa) *pdewa = NULL;
179  if (!ppixb || !pdewa)
180  return ERROR_INT("&pixb and &dewa not both defined", procName, 1);
181  if (!pixs)
182  return ERROR_INT("pixs not defined", procName, 1);
183 
184  *pdewa = dewarpaCreate(1, 0, 1, 0, -1);
185  dewarpaUseBothArrays(*pdewa, useboth);
186  dewarpaSetCheckColumns(*pdewa, check_columns);
187 
188  /* Generate a binary image, if necessary */
189  if (pixGetDepth(pixs) > 1) {
190  pix1 = pixConvertTo8(pixs, 0);
191  if (adaptive)
192  *ppixb = pixAdaptThresholdToBinary(pix1, NULL, 1.0);
193  else
194  *ppixb = pixThresholdToBinary(pix1, thresh);
195  pixDestroy(&pix1);
196  } else {
197  *ppixb = pixClone(pixs);
198  }
199  return 0;
200 }
201 
202 
222 l_ok
224  PIX *pixb,
225  L_DEWARPA *dewa,
226  PIX **ppixd,
227  l_int32 debug)
228 {
229 const char *debugfile;
230 l_int32 vsuccess, ret;
231 L_DEWARP *dew;
232 
233  PROCNAME("dewarpSinglePageRun");
234 
235  if (!ppixd)
236  return ERROR_INT("&pixd not defined", procName, 1);
237  *ppixd = NULL;
238  if (!pixs)
239  return ERROR_INT("pixs not defined", procName, 1);
240  if (!pixb)
241  return ERROR_INT("pixb not defined", procName, 1);
242  if (!dewa)
243  return ERROR_INT("dewa not defined", procName, 1);
244 
245  if (debug)
246  lept_mkdir("lept/dewarp");
247 
248  /* Generate the page model */
249  dew = dewarpCreate(pixb, 0);
251  debugfile = (debug) ? "/tmp/lept/dewarp/singlepage_model.pdf" : NULL;
252  dewarpBuildPageModel(dew, debugfile);
253  dewarpaModelStatus(dewa, 0, &vsuccess, NULL);
254  if (vsuccess == 0) {
255  L_ERROR("failure to build model for vertical disparity\n", procName);
256  *ppixd = pixCopy(NULL, pixs);
257  return 0;
258  }
259 
260  /* Apply the page model */
261  debugfile = (debug) ? "/tmp/lept/dewarp/singlepage_apply.pdf" : NULL;
262  ret = dewarpaApplyDisparity(dewa, 0, pixs, 255, 0, 0, ppixd, debugfile);
263  if (ret)
264  L_ERROR("invalid model; failure to apply disparity\n", procName);
265  return 0;
266 }
267 
268 
269 /*----------------------------------------------------------------------*
270  * Operations on dewarpa *
271  *----------------------------------------------------------------------*/
288 l_ok
290 {
291 l_int32 i;
292 L_DEWARP *dew;
293 NUMA *namodels, *napages;
294 
295  PROCNAME("dewarpaListPages");
296 
297  if (!dewa)
298  return ERROR_INT("dewa not defined", procName, 1);
299 
302  namodels = numaCreate(dewa->maxpage + 1);
303  napages = numaCreate(dewa->maxpage + 1);
304  dewa->namodels = namodels;
305  dewa->napages = napages;
306  for (i = 0; i <= dewa->maxpage; i++) {
307  if ((dew = dewarpaGetDewarp(dewa, i)) != NULL) {
308  if (dew->hasref == 0)
309  numaAddNumber(namodels, dew->pageno);
310  numaAddNumber(napages, dew->pageno);
311  }
312  }
313  return 0;
314 }
315 
316 
340 l_ok
342  l_int32 notests,
343  l_int32 debug)
344 {
345 l_int32 i, n, maxcurv, diffcurv, diffedge;
346 L_DEWARP *dew;
347 
348  PROCNAME("dewarpaSetValidModels");
349 
350  if (!dewa)
351  return ERROR_INT("dewa not defined", procName, 1);
352 
353  n = dewa->maxpage + 1;
354  for (i = 0; i < n; i++) {
355  if ((dew = dewarpaGetDewarp(dewa, i)) == NULL)
356  continue;
357 
358  if (debug) {
359  if (dew->hasref == 1) {
360  L_INFO("page %d: has only a ref model\n", procName, i);
361  } else if (dew->vsuccess == 0) {
362  L_INFO("page %d: no model successfully built\n",
363  procName, i);
364  } else if (!notests) {
365  maxcurv = L_MAX(L_ABS(dew->mincurv), L_ABS(dew->maxcurv));
366  diffcurv = dew->maxcurv - dew->mincurv;
367  if (dewa->useboth && !dew->hsuccess)
368  L_INFO("page %d: useboth, but no horiz disparity\n",
369  procName, i);
370  if (maxcurv > dewa->max_linecurv)
371  L_INFO("page %d: max curvature %d > max_linecurv\n",
372  procName, i, diffcurv);
373  if (diffcurv < dewa->min_diff_linecurv)
374  L_INFO("page %d: diff curv %d < min_diff_linecurv\n",
375  procName, i, diffcurv);
376  if (diffcurv > dewa->max_diff_linecurv)
377  L_INFO("page %d: abs diff curv %d > max_diff_linecurv\n",
378  procName, i, diffcurv);
379  if (dew->hsuccess) {
380  if (L_ABS(dew->leftslope) > dewa->max_edgeslope)
381  L_INFO("page %d: abs left slope %d > max_edgeslope\n",
382  procName, i, dew->leftslope);
383  if (L_ABS(dew->rightslope) > dewa->max_edgeslope)
384  L_INFO("page %d: abs right slope %d > max_edgeslope\n",
385  procName, i, dew->rightslope);
386  diffedge = L_ABS(dew->leftcurv - dew->rightcurv);
387  if (L_ABS(dew->leftcurv) > dewa->max_edgecurv)
388  L_INFO("page %d: left curvature %d > max_edgecurv\n",
389  procName, i, dew->leftcurv);
390  if (L_ABS(dew->rightcurv) > dewa->max_edgecurv)
391  L_INFO("page %d: right curvature %d > max_edgecurv\n",
392  procName, i, dew->rightcurv);
393  if (diffedge > dewa->max_diff_edgecurv)
394  L_INFO("page %d: abs diff left-right curv %d > "
395  "max_diff_edgecurv\n", procName, i, diffedge);
396  }
397  }
398  }
399 
400  dewarpaTestForValidModel(dewa, dew, notests);
401  }
402 
403  return 0;
404 }
405 
406 
446 l_ok
448  l_int32 notests,
449  l_int32 debug)
450 {
451 l_int32 i, j, n, val, min, distdown, distup;
452 L_DEWARP *dew;
453 NUMA *na, *nah;
454 
455  PROCNAME("dewarpaInsertRefModels");
456 
457  if (!dewa)
458  return ERROR_INT("dewa not defined", procName, 1);
459  if (dewa->maxdist < 2)
460  L_INFO("maxdist < 2; no ref models can be used\n", procName);
461 
462  /* Make an indicator numa for pages with valid models. */
463  dewarpaSetValidModels(dewa, notests, debug);
464  n = dewa->maxpage + 1;
465  na = numaMakeConstant(0, n);
466  for (i = 0; i < n; i++) {
467  dew = dewarpaGetDewarp(dewa, i);
468  if (dew && dew->vvalid)
469  numaReplaceNumber(na, i, 1);
470  }
471 
472  /* Remove all existing ref models and restore models from cache */
474 
475  /* Move invalid models to the cache, and insert reference dewarps
476  * for pages that need to borrow a model.
477  * First, try to find a valid model for each page. */
478  for (i = 0; i < n; i++) {
479  numaGetIValue(na, i, &val);
480  if (val == 1) continue; /* already has a valid model */
481  if ((dew = dewa->dewarp[i]) != NULL) { /* exists but is not valid; */
482  dewa->dewarpcache[i] = dew; /* move it to the cache */
483  dewa->dewarp[i] = NULL;
484  }
485  if (dewa->maxdist < 2) continue; /* can't use a ref model */
486  /* Look back for nearest model */
487  distdown = distup = dewa->maxdist + 1;
488  for (j = i - 2; j >= 0 && distdown > dewa->maxdist; j -= 2) {
489  numaGetIValue(na, j, &val);
490  if (val == 1) distdown = i - j;
491  }
492  /* Look ahead for nearest model */
493  for (j = i + 2; j < n && distup > dewa->maxdist; j += 2) {
494  numaGetIValue(na, j, &val);
495  if (val == 1) distup = j - i;
496  }
497  min = L_MIN(distdown, distup);
498  if (min > dewa->maxdist) continue; /* no valid model in range */
499  if (distdown <= distup)
500  dewarpaInsertDewarp(dewa, dewarpCreateRef(i, i - distdown));
501  else
502  dewarpaInsertDewarp(dewa, dewarpCreateRef(i, i + distup));
503  }
504  numaDestroy(&na);
505 
506  /* If a valid model will do, we're finished. */
507  if (dewa->useboth == 0) {
508  dewa->modelsready = 1; /* validated */
509  return 0;
510  }
511 
512  /* The request is useboth == 1. Now try to find an hvalid model */
513  nah = numaMakeConstant(0, n);
514  for (i = 0; i < n; i++) {
515  dew = dewarpaGetDewarp(dewa, i);
516  if (dew && dew->hvalid)
517  numaReplaceNumber(nah, i, 1);
518  }
519  for (i = 0; i < n; i++) {
520  numaGetIValue(nah, i, &val);
521  if (val == 1) continue; /* already has a hvalid model */
522  if (dewa->maxdist < 2) continue; /* can't use a ref model */
523  distdown = distup = 100000;
524  for (j = i - 2; j >= 0; j -= 2) { /* look back for nearest model */
525  numaGetIValue(nah, j, &val);
526  if (val == 1) {
527  distdown = i - j;
528  break;
529  }
530  }
531  for (j = i + 2; j < n; j += 2) { /* look ahead for nearest model */
532  numaGetIValue(nah, j, &val);
533  if (val == 1) {
534  distup = j - i;
535  break;
536  }
537  }
538  min = L_MIN(distdown, distup);
539  if (min > dewa->maxdist) continue; /* no hvalid model within range */
540 
541  /* We can replace the existing valid model with an hvalid model.
542  * If it's not a reference, save it in the cache. */
543  if ((dew = dewarpaGetDewarp(dewa, i)) == NULL) {
544  L_ERROR("dew is null for page %d!\n", procName, i);
545  } else {
546  if (dew->hasref == 0) { /* not a ref model */
547  dewa->dewarpcache[i] = dew; /* move it to the cache */
548  dewa->dewarp[i] = NULL; /* must null the ptr */
549  }
550  }
551  if (distdown <= distup) /* insert the hvalid ref model */
552  dewarpaInsertDewarp(dewa, dewarpCreateRef(i, i - distdown));
553  else
554  dewarpaInsertDewarp(dewa, dewarpCreateRef(i, i + distup));
555  }
556  numaDestroy(&nah);
557 
558  dewa->modelsready = 1; /* validated */
559  return 0;
560 }
561 
562 
577 l_ok
579 {
580 l_int32 i;
581 L_DEWARP *dew;
582 
583  PROCNAME("dewarpaStripRefModels");
584 
585  if (!dewa)
586  return ERROR_INT("dewa not defined", procName, 1);
587 
588  for (i = 0; i <= dewa->maxpage; i++) {
589  if ((dew = dewarpaGetDewarp(dewa, i)) != NULL) {
590  if (dew->hasref)
591  dewarpDestroy(&dewa->dewarp[i]);
592  }
593  }
594  dewa->modelsready = 0;
595 
596  /* Regenerate the page lists */
598  return 0;
599 }
600 
601 
618 l_ok
620 {
621 l_int32 i;
622 L_DEWARP *dew;
623 
624  PROCNAME("dewarpaRestoreModels");
625 
626  if (!dewa)
627  return ERROR_INT("dewa not defined", procName, 1);
628 
629  /* Strip out ref models. Then only real models will be in the
630  * primary dewarp array. */
632 
633  /* The cache holds only real models, which are not necessarily valid. */
634  for (i = 0; i <= dewa->maxpage; i++) {
635  if ((dew = dewa->dewarpcache[i]) != NULL) {
636  if (dewa->dewarp[i]) {
637  L_ERROR("dew in both cache and main array!: page %d\n",
638  procName, i);
639  } else {
640  dewa->dewarp[i] = dew;
641  dewa->dewarpcache[i] = NULL;
642  }
643  }
644  }
645  dewa->modelsready = 0; /* new ref models not yet inserted */
646 
647  /* Regenerate the page lists */
649  return 0;
650 }
651 
652 
653 /*----------------------------------------------------------------------*
654  * Dewarp debugging output *
655  *----------------------------------------------------------------------*/
663 l_ok
664 dewarpaInfo(FILE *fp,
665  L_DEWARPA *dewa)
666 {
667 l_int32 i, n, pageno, nnone, nvsuccess, nvvalid, nhsuccess, nhvalid, nref;
668 L_DEWARP *dew;
669 
670  PROCNAME("dewarpaInfo");
671 
672  if (!fp)
673  return ERROR_INT("dewa not defined", procName, 1);
674  if (!dewa)
675  return ERROR_INT("dewa not defined", procName, 1);
676 
677  fprintf(fp, "\nDewarpaInfo: %p\n", dewa);
678  fprintf(fp, "nalloc = %d, maxpage = %d\n", dewa->nalloc, dewa->maxpage);
679  fprintf(fp, "sampling = %d, redfactor = %d, minlines = %d\n",
681  fprintf(fp, "maxdist = %d, useboth = %d\n",
682  dewa->maxdist, dewa->useboth);
683 
684  dewarpaModelStats(dewa, &nnone, &nvsuccess, &nvvalid,
685  &nhsuccess, &nhvalid, &nref);
686  n = numaGetCount(dewa->napages);
687  fprintf(stderr, "Total number of pages with a dew = %d\n", n);
688  fprintf(stderr, "Number of pages without any models = %d\n", nnone);
689  fprintf(stderr, "Number of pages with a vert model = %d\n", nvsuccess);
690  fprintf(stderr, "Number of pages with a valid vert model = %d\n", nvvalid);
691  fprintf(stderr, "Number of pages with both models = %d\n", nhsuccess);
692  fprintf(stderr, "Number of pages with both models valid = %d\n", nhvalid);
693  fprintf(stderr, "Number of pages with a ref model = %d\n", nref);
694 
695  for (i = 0; i < n; i++) {
697  if ((dew = dewarpaGetDewarp(dewa, pageno)) == NULL)
698  continue;
699  fprintf(stderr, "Page: %d\n", dew->pageno);
700  fprintf(stderr, " hasref = %d, refpage = %d\n",
701  dew->hasref, dew->refpage);
702  fprintf(stderr, " nlines = %d\n", dew->nlines);
703  fprintf(stderr, " w = %d, h = %d, nx = %d, ny = %d\n",
704  dew->w, dew->h, dew->nx, dew->ny);
705  if (dew->sampvdispar)
706  fprintf(stderr, " Vertical disparity builds:\n"
707  " (min,max,abs-diff) line curvature = (%d,%d,%d)\n",
708  dew->mincurv, dew->maxcurv, dew->maxcurv - dew->mincurv);
709  if (dew->samphdispar)
710  fprintf(stderr, " Horizontal disparity builds:\n"
711  " left edge slope = %d, right edge slope = %d\n"
712  " (left,right,abs-diff) edge curvature = (%d,%d,%d)\n",
713  dew->leftslope, dew->rightslope, dew->leftcurv,
714  dew->rightcurv, L_ABS(dew->leftcurv - dew->rightcurv));
715  }
716  return 0;
717 }
718 
719 
755 l_ok
757  l_int32 *pnnone,
758  l_int32 *pnvsuccess,
759  l_int32 *pnvvalid,
760  l_int32 *pnhsuccess,
761  l_int32 *pnhvalid,
762  l_int32 *pnref)
763 {
764 l_int32 i, n, pageno, nnone, nvsuccess, nvvalid, nhsuccess, nhvalid, nref;
765 L_DEWARP *dew;
766 
767  PROCNAME("dewarpaModelStats");
768 
769  if (!dewa)
770  return ERROR_INT("dewa not defined", procName, 1);
771 
773  n = numaGetCount(dewa->napages);
774  nnone = nref = nvsuccess = nvvalid = nhsuccess = nhvalid = 0;
775  for (i = 0; i < n; i++) {
777  dew = dewarpaGetDewarp(dewa, pageno);
778  if (!dew) {
779  nnone++;
780  continue;
781  }
782  if (dew->hasref == 1)
783  nref++;
784  if (dew->vsuccess == 1)
785  nvsuccess++;
786  if (dew->hsuccess == 1)
787  nhsuccess++;
789  if (dew->vvalid == 1)
790  nvvalid++;
791  if (dew->hvalid == 1)
792  nhvalid++;
793  }
794 
795  if (pnnone) *pnnone = nnone;
796  if (pnref) *pnref = nref;
797  if (pnvsuccess) *pnvsuccess = nvsuccess;
798  if (pnvvalid) *pnvvalid = nvvalid;
799  if (pnhsuccess) *pnhsuccess = nhsuccess;
800  if (pnhvalid) *pnhvalid = nhvalid;
801  return 0;
802 }
803 
804 
823 static l_int32
825  L_DEWARP *dew,
826  l_int32 notests)
827 {
828 l_int32 maxcurv, diffcurv, diffedge;
829 
830  PROCNAME("dewarpaTestForValidModel");
831 
832  if (!dewa || !dew)
833  return ERROR_INT("dewa and dew not both defined", procName, 1);
834 
835  if (notests) {
836  dew->vvalid = dew->vsuccess;
837  dew->hvalid = dew->hsuccess;
838  return 0;
839  }
840 
841  /* No actual model was built */
842  if (dew->vsuccess == 0) return 0;
843 
844  /* Was previously found not to have a valid model */
845  if (dew->hasref == 1) return 0;
846 
847  /* vsuccess == 1; a vertical (line) model exists.
848  * First test that the vertical curvatures are within allowed
849  * bounds. Note that all curvatures are signed.*/
850  maxcurv = L_MAX(L_ABS(dew->mincurv), L_ABS(dew->maxcurv));
851  diffcurv = dew->maxcurv - dew->mincurv;
852  if (maxcurv <= dewa->max_linecurv &&
853  diffcurv >= dewa->min_diff_linecurv &&
854  diffcurv <= dewa->max_diff_linecurv) {
855  dew->vvalid = 1;
856  } else {
857  L_INFO("invalid vert model for page %d:\n", procName, dew->pageno);
858 #if DEBUG_INVALID_MODELS
859  fprintf(stderr, " max line curv = %d, max allowed = %d\n",
861  fprintf(stderr, " diff line curv = %d, max allowed = %d\n",
862  diffcurv, dewa->max_diff_linecurv);
863 #endif /* DEBUG_INVALID_MODELS */
864  }
865 
866  /* If a horizontal (edge) model exists, test for validity. */
867  if (dew->hsuccess) {
868  diffedge = L_ABS(dew->leftcurv - dew->rightcurv);
869  if (L_ABS(dew->leftslope) <= dewa->max_edgeslope &&
870  L_ABS(dew->rightslope) <= dewa->max_edgeslope &&
871  L_ABS(dew->leftcurv) <= dewa->max_edgecurv &&
872  L_ABS(dew->rightcurv) <= dewa->max_edgecurv &&
873  diffedge <= dewa->max_diff_edgecurv) {
874  dew->hvalid = 1;
875  } else {
876  L_INFO("invalid horiz model for page %d:\n", procName, dew->pageno);
877 #if DEBUG_INVALID_MODELS
878  fprintf(stderr, " left edge slope = %d, max allowed = %d\n",
879  dew->leftslope, dewa->max_edgeslope);
880  fprintf(stderr, " right edge slope = %d, max allowed = %d\n",
881  dew->rightslope, dewa->max_edgeslope);
882  fprintf(stderr, " left edge curv = %d, max allowed = %d\n",
883  dew->leftcurv, dewa->max_edgecurv);
884  fprintf(stderr, " right edge curv = %d, max allowed = %d\n",
885  dew->rightcurv, dewa->max_edgecurv);
886  fprintf(stderr, " diff edge curv = %d, max allowed = %d\n",
887  diffedge, dewa->max_diff_edgecurv);
888 #endif /* DEBUG_INVALID_MODELS */
889  }
890  }
891 
892  return 0;
893 }
894 
895 
911 l_ok
913  l_float32 scalefact,
914  l_int32 first,
915  l_int32 last)
916 {
917 char buf[256];
918 l_int32 i, svd, shd;
919 L_BMF *bmf;
920 L_DEWARP *dew;
921 PIX *pixv, *pixvs, *pixh, *pixhs, *pixt, *pixd;
922 PIXA *pixa;
923 
924  PROCNAME("dewarpaShowArrays");
925 
926  if (!dewa)
927  return ERROR_INT("dew not defined", procName, 1);
928  if (first < 0 || first > dewa->maxpage)
929  return ERROR_INT("first out of bounds", procName, 1);
930  if (last <= 0 || last > dewa->maxpage) last = dewa->maxpage;
931  if (last < first)
932  return ERROR_INT("last < first", procName, 1);
933 
934  lept_rmdir("lept/dewarp1"); /* temp directory for contour plots */
935  lept_mkdir("lept/dewarp1");
936  if ((bmf = bmfCreate(NULL, 8)) == NULL)
937  L_ERROR("bmf not made; page info not displayed", procName);
938 
939  fprintf(stderr, "Generating contour plots\n");
940  for (i = first; i <= last; i++) {
941  if (i && ((i % 10) == 0))
942  fprintf(stderr, " .. %d", i);
943  dew = dewarpaGetDewarp(dewa, i);
944  if (!dew) continue;
945  if (dew->hasref == 1) continue;
946  svd = shd = 0;
947  if (dew->sampvdispar) svd = 1;
948  if (dew->samphdispar) shd = 1;
949  if (!svd) {
950  L_ERROR("sampvdispar not made for page %d!\n", procName, i);
951  continue;
952  }
953 
954  /* Generate contour plots at reduced resolution */
955  dewarpPopulateFullRes(dew, NULL, 0, 0);
956  pixv = fpixRenderContours(dew->fullvdispar, 3.0, 0.15);
957  pixvs = pixScaleBySampling(pixv, scalefact, scalefact);
958  pixDestroy(&pixv);
959  if (shd) {
960  pixh = fpixRenderContours(dew->fullhdispar, 3.0, 0.15);
961  pixhs = pixScaleBySampling(pixh, scalefact, scalefact);
962  pixDestroy(&pixh);
963  }
964  dewarpMinimize(dew);
965 
966  /* Save side-by-side */
967  pixa = pixaCreate(2);
968  pixaAddPix(pixa, pixvs, L_INSERT);
969  if (shd)
970  pixaAddPix(pixa, pixhs, L_INSERT);
971  pixt = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 30, 2);
972  snprintf(buf, sizeof(buf), "Page %d", i);
973  pixd = pixAddSingleTextblock(pixt, bmf, buf, 0x0000ff00,
974  L_ADD_BELOW, NULL);
975  snprintf(buf, sizeof(buf), "/tmp/lept/dewarp1/arrays_%04d.png", i);
976  pixWriteDebug(buf, pixd, IFF_PNG);
977  pixaDestroy(&pixa);
978  pixDestroy(&pixt);
979  pixDestroy(&pixd);
980  }
981  bmfDestroy(&bmf);
982  fprintf(stderr, "\n");
983 
984  fprintf(stderr, "Generating pdf of contour plots\n");
985  convertFilesToPdf("/tmp/lept/dewarp1", "arrays_", 90, 1.0, L_FLATE_ENCODE,
986  0, "Disparity arrays", "/tmp/lept/disparity_arrays.pdf");
987  fprintf(stderr, "Output written to: /tmp/lept/disparity_arrays.pdf\n");
988  return 0;
989 }
990 
991 
1007 l_ok
1009  const char *subdirs,
1010  l_int32 index)
1011 {
1012 char fname[256];
1013 char *outdir;
1014 l_int32 svd, shd;
1015 PIX *pixv, *pixh;
1016 
1017  PROCNAME("dewarpDebug");
1018 
1019  if (!dew)
1020  return ERROR_INT("dew not defined", procName, 1);
1021  if (!subdirs)
1022  return ERROR_INT("subdirs not defined", procName, 1);
1023 
1024  fprintf(stderr, "pageno = %d, hasref = %d, refpage = %d\n",
1025  dew->pageno, dew->hasref, dew->refpage);
1026  fprintf(stderr, "sampling = %d, redfactor = %d, minlines = %d\n",
1027  dew->sampling, dew->redfactor, dew->minlines);
1028  svd = shd = 0;
1029  if (!dew->hasref) {
1030  if (dew->sampvdispar) svd = 1;
1031  if (dew->samphdispar) shd = 1;
1032  fprintf(stderr, "sampv = %d, samph = %d\n", svd, shd);
1033  fprintf(stderr, "w = %d, h = %d\n", dew->w, dew->h);
1034  fprintf(stderr, "nx = %d, ny = %d\n", dew->nx, dew->ny);
1035  fprintf(stderr, "nlines = %d\n", dew->nlines);
1036  if (svd) {
1037  fprintf(stderr, "(min,max,abs-diff) line curvature = (%d,%d,%d)\n",
1038  dew->mincurv, dew->maxcurv, dew->maxcurv - dew->mincurv);
1039  }
1040  if (shd) {
1041  fprintf(stderr, "(left edge slope = %d, right edge slope = %d\n",
1042  dew->leftslope, dew->rightslope);
1043  fprintf(stderr, "(left,right,abs-diff) edge curvature = "
1044  "(%d,%d,%d)\n", dew->leftcurv, dew->rightcurv,
1045  L_ABS(dew->leftcurv - dew->rightcurv));
1046  }
1047  }
1048  if (!svd && !shd) {
1049  fprintf(stderr, "No disparity arrays\n");
1050  return 0;
1051  }
1052 
1053  dewarpPopulateFullRes(dew, NULL, 0, 0);
1054  lept_mkdir(subdirs);
1055  outdir = pathJoin("/tmp", subdirs);
1056  if (svd) {
1057  pixv = fpixRenderContours(dew->fullvdispar, 3.0, 0.15);
1058  snprintf(fname, sizeof(fname), "%s/pixv_%d.png", outdir, index);
1059  pixWriteDebug(fname, pixv, IFF_PNG);
1060  pixDestroy(&pixv);
1061  }
1062  if (shd) {
1063  pixh = fpixRenderContours(dew->fullhdispar, 3.0, 0.15);
1064  snprintf(fname, sizeof(fname), "%s/pixh_%d.png", outdir, index);
1065  pixWriteDebug(fname, pixh, IFF_PNG);
1066  pixDestroy(&pixh);
1067  }
1068  LEPT_FREE(outdir);
1069  return 0;
1070 }
1071 
1072 
1093 l_ok
1095  SARRAY *sa,
1096  BOXA *boxa,
1097  l_int32 firstpage,
1098  l_int32 lastpage,
1099  const char *pdfout)
1100 {
1101 char bufstr[256];
1102 l_int32 i, modelpage;
1103 L_BMF *bmf;
1104 BOX *box;
1105 L_DEWARP *dew;
1106 PIX *pixs, *pixc, *pixd, *pixt1, *pixt2;
1107 PIXA *pixa;
1108 
1109  PROCNAME("dewarpShowResults");
1110 
1111  if (!dewa)
1112  return ERROR_INT("dewa not defined", procName, 1);
1113  if (!sa)
1114  return ERROR_INT("sa not defined", procName, 1);
1115  if (!pdfout)
1116  return ERROR_INT("pdfout not defined", procName, 1);
1117  if (firstpage > lastpage)
1118  return ERROR_INT("invalid first/last page numbers", procName, 1);
1119 
1120  lept_rmdir("lept/dewarp_pdfout");
1121  lept_mkdir("lept/dewarp_pdfout");
1122  bmf = bmfCreate(NULL, 6);
1123 
1124  fprintf(stderr, "Dewarping and generating s/by/s view\n");
1125  for (i = firstpage; i <= lastpage; i++) {
1126  if (i && (i % 10 == 0)) fprintf(stderr, ".. %d ", i);
1127  pixs = pixReadIndexed(sa, i);
1128  if (boxa) {
1129  box = boxaGetBox(boxa, i, L_CLONE);
1130  pixc = pixClipRectangle(pixs, box, NULL);
1131  boxDestroy(&box);
1132  }
1133  else
1134  pixc = pixClone(pixs);
1135  dew = dewarpaGetDewarp(dewa, i);
1136  pixd = NULL;
1137  if (dew) {
1138  dewarpaApplyDisparity(dewa, dew->pageno, pixc,
1139  GRAYIN_VALUE, 0, 0, &pixd, NULL);
1140  dewarpMinimize(dew);
1141  }
1142  pixa = pixaCreate(2);
1143  pixaAddPix(pixa, pixc, L_INSERT);
1144  if (pixd)
1145  pixaAddPix(pixa, pixd, L_INSERT);
1146  pixt1 = pixaDisplayTiledAndScaled(pixa, 32, 500, 2, 0, 35, 2);
1147  if (dew) {
1148  modelpage = (dew->hasref) ? dew->refpage : dew->pageno;
1149  snprintf(bufstr, sizeof(bufstr), "Page %d; using %d\n",
1150  i, modelpage);
1151  }
1152  else
1153  snprintf(bufstr, sizeof(bufstr), "Page %d; no dewarp\n", i);
1154  pixt2 = pixAddSingleTextblock(pixt1, bmf, bufstr, 0x0000ff00,
1155  L_ADD_BELOW, 0);
1156  snprintf(bufstr, sizeof(bufstr), "/tmp/lept/dewarp_pdfout/%05d", i);
1157  pixWriteDebug(bufstr, pixt2, IFF_JFIF_JPEG);
1158  pixaDestroy(&pixa);
1159  pixDestroy(&pixs);
1160  pixDestroy(&pixt1);
1161  pixDestroy(&pixt2);
1162  }
1163  fprintf(stderr, "\n");
1164 
1165  fprintf(stderr, "Generating pdf of result\n");
1166  convertFilesToPdf("/tmp/lept/dewarp_pdfout", NULL, 100, 1.0, L_JPEG_ENCODE,
1167  0, "Dewarp sequence", pdfout);
1168  fprintf(stderr, "Output written to: %s\n", pdfout);
1169  bmfDestroy(&bmf);
1170  return 0;
1171 }
struct FPix * sampvdispar
Definition: dewarp.h:155
l_int32 maxdist
Definition: dewarp.h:126
l_int32 nlines
Definition: dewarp.h:169
struct L_Dewarp ** dewarp
Definition: dewarp.h:117
l_int32 max_edgeslope
Definition: dewarp.h:133
struct Numa * napages
Definition: dewarp.h:121
struct L_Dewarp ** dewarpcache
Definition: dewarp.h:118
struct FPix * samphdispar
Definition: dewarp.h:156
void bmfDestroy(L_BMF **pbmf)
bmfDestroy()
Definition: bmf.c:166
l_int32 minlines
Definition: dewarp.h:125
l_int32 debug
Definition: dewarp.h:187
l_ok dewarpSinglePageRun(PIX *pixs, PIX *pixb, L_DEWARPA *dewa, PIX **ppixd, l_int32 debug)
dewarpSinglePageRun()
Definition: dewarp4.c:223
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:97
l_int32 h
Definition: dewarp.h:164
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:1944
Definition: pix.h:717
l_int32 max_diff_linecurv
Definition: dewarp.h:131
l_int32 ny
Definition: dewarp.h:177
l_ok dewarpShowResults(L_DEWARPA *dewa, SARRAY *sa, BOXA *boxa, l_int32 firstpage, l_int32 lastpage, const char *pdfout)
dewarpShowResults()
Definition: dewarp4.c:1094
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:473
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:163
L_DEWARP * dewarpCreate(PIX *pixs, l_int32 pageno)
dewarpCreate()
Definition: dewarp1.c:446
l_int32 max_diff_edgecurv
Definition: dewarp.h:137
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:114
PIX * pixReadIndexed(SARRAY *sa, l_int32 index)
pixReadIndexed()
Definition: readfile.c:277
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3041
l_int32 sampling
Definition: dewarp.h:166
NUMA * numaMakeConstant(l_float32 val, l_int32 size)
numaMakeConstant()
Definition: numafunc1.c:781
l_int32 leftcurv
Definition: dewarp.h:174
l_ok dewarpaShowArrays(L_DEWARPA *dewa, l_float32 scalefact, l_int32 first, l_int32 last)
dewarpaShowArrays()
Definition: dewarp4.c:912
void dewarpDestroy(L_DEWARP **pdew)
dewarpDestroy()
Definition: dewarp1.c:509
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:187
l_int32 refpage
Definition: dewarp.h:179
PIX * pixThresholdToBinary(PIX *pixs, l_int32 thresh)
pixThresholdToBinary()
Definition: grayquant.c:443
PIX * pixScaleBySampling(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleBySampling()
Definition: scale1.c:1338
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:165
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:239
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:1020
Definition: pix.h:492
l_int32 max_linecurv
Definition: dewarp.h:127
l_int32 pageno
Definition: dewarp.h:165
Definition: bmf.h:45
Definition: array.h:116
void dewarpaDestroy(L_DEWARPA **pdewa)
dewarpaDestroy()
Definition: dewarp1.c:722
struct L_Dewarpa * dewa
Definition: dewarp.h:153
l_ok dewarpBuildPageModel(L_DEWARP *dew, const char *debugfile)
dewarpBuildPageModel()
Definition: dewarp2.c:148
l_int32 useboth
Definition: dewarp.h:139
l_ok dewarpaListPages(L_DEWARPA *dewa)
dewarpaListPages()
Definition: dewarp4.c:289
struct Pix * pixs
Definition: dewarp.h:154
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:727
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:503
Definition: array.h:59
l_int32 min_diff_linecurv
Definition: dewarp.h:129
l_int32 redfactor
Definition: dewarp.h:167
l_ok dewarpaRestoreModels(L_DEWARPA *dewa)
dewarpaRestoreModels()
Definition: dewarp4.c:619
l_int32 minlines
Definition: dewarp.h:168
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:631
l_ok dewarpMinimize(L_DEWARP *dew)
dewarpMinimize()
Definition: dewarp3.c:729
l_int32 nalloc
Definition: dewarp.h:115
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:756
l_ok dewarpaModelStatus(L_DEWARPA *dewa, l_int32 pageno, l_int32 *pvsuccess, l_int32 *phsuccess)
dewarpaModelStatus()
Definition: dewarp2.c:1790
l_int32 sampling
Definition: dewarp.h:124
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:836
l_int32 modelsready
Definition: dewarp.h:144
l_int32 maxpage
Definition: dewarp.h:116
l_int32 mincurv
Definition: dewarp.h:170
l_ok dewarpPopulateFullRes(L_DEWARP *dew, PIX *pix, l_int32 x, l_int32 y)
dewarpPopulateFullRes()
Definition: dewarp3.c:785
l_int32 vvalid
Definition: dewarp.h:183
l_int32 rightcurv
Definition: dewarp.h:175
struct Numa * namodels
Definition: dewarp.h:119
L_DEWARPA * dewarpaCreate(l_int32 nptrs, l_int32 sampling, l_int32 redfactor, l_int32 minlines, l_int32 maxdist)
dewarpaCreate()
Definition: dewarp1.c:572
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:515
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:1137
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:763
l_ok dewarpaStripRefModels(L_DEWARPA *dewa)
dewarpaStripRefModels()
Definition: dewarp4.c:578
l_int32 maxcurv
Definition: dewarp.h:171
Definition: pix.h:454
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:360
l_int32 vsuccess
Definition: dewarp.h:180
l_int32 max_edgecurv
Definition: dewarp.h:135
l_int32 hsuccess
Definition: dewarp.h:181
l_ok dewarpaUseBothArrays(L_DEWARPA *dewa, l_int32 useboth)
dewarpaUseBothArrays()
Definition: dewarp1.c:1030
PIX * pixAdaptThresholdToBinary(PIX *pixs, PIX *pixm, l_float32 gamma)
pixAdaptThresholdToBinary()
Definition: grayquant.c:726
l_int32 hvalid
Definition: dewarp.h:184
l_int32 leftslope
Definition: dewarp.h:172
l_ok dewarpaInsertDewarp(L_DEWARPA *dewa, L_DEWARP *dew)
dewarpaInsertDewarp()
Definition: dewarp1.c:805
char * pathJoin(const char *dir, const char *fname)
pathJoin()
Definition: utils2.c:2686
l_ok dewarpaSetValidModels(L_DEWARPA *dewa, l_int32 notests, l_int32 debug)
dewarpaSetValidModels()
Definition: dewarp4.c:341
struct FPix * fullvdispar
Definition: dewarp.h:158
l_ok dewarpaSetCheckColumns(L_DEWARPA *dewa, l_int32 check_columns)
dewarpaSetCheckColumns()
Definition: dewarp1.c:1069
Definition: pix.h:134
l_int32 redfactor
Definition: dewarp.h:123
static l_int32 dewarpaTestForValidModel(L_DEWARPA *dewa, L_DEWARP *dew, l_int32 notests)
dewarpaTestForValidModel()
Definition: dewarp4.c:824
Definition: pix.h:719
PIX * pixCopy(PIX *pixd, PIX *pixs)
pixCopy()
Definition: pix1.c:628
l_ok numaReplaceNumber(NUMA *na, l_int32 index, l_float32 val)
numaReplaceNumber()
Definition: numabasic.c:602
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:278
l_int32 rightslope
Definition: dewarp.h:173
struct FPix * fullhdispar
Definition: dewarp.h:159
l_int32 nx
Definition: dewarp.h:176
l_int32 hasref
Definition: dewarp.h:178
l_int32 lept_rmdir(const char *subdir)
lept_rmdir()
Definition: utils2.c:2021
l_ok dewarpaInfo(FILE *fp, L_DEWARPA *dewa)
dewarpaInfo()
Definition: dewarp4.c:664
l_int32 w
Definition: dewarp.h:163
Definition: pix.h:480
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:408
PIX * pixAddSingleTextblock(PIX *pixs, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 location, l_int32 *poverflow)
pixAddSingleTextblock()
Definition: textops.c:115
l_ok dewarpaInsertRefModels(L_DEWARPA *dewa, l_int32 notests, l_int32 debug)
dewarpaInsertRefModels()
Definition: dewarp4.c:447
l_ok dewarpDebug(L_DEWARP *dew, const char *subdirs, l_int32 index)
dewarpDebug()
Definition: dewarp4.c:1008
L_DEWARP * dewarpCreateRef(l_int32 pageno, l_int32 refpage)
dewarpCreateRef()
Definition: dewarp1.c:486
L_DEWARP * dewarpaGetDewarp(L_DEWARPA *dewa, l_int32 index)
dewarpaGetDewarp()
Definition: dewarp1.c:902
PIX * fpixRenderContours(FPIX *fpixs, l_float32 incr, l_float32 proxim)
fpixRenderContours()
Definition: graphics.c:2783
L_BMF * bmfCreate(const char *dir, l_int32 fontsize)
bmfCreate()
Definition: bmf.c:114