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 
64 static 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 */
72 static const l_int32 GrayInValue = 200;
73 
74 /*----------------------------------------------------------------------*
75  * Top-level single page dewarper *
76  *----------------------------------------------------------------------*/
99 l_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 {
109 L_DEWARPA *dewa;
110 PIX *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) {
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
134  pixDestroy(&pixb);
135  return 0;
136 }
137 
138 
167 l_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 {
176 PIX *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 
229 l_ok
231  PIX *pixb,
232  L_DEWARPA *dewa,
233  PIX **ppixd,
234  l_int32 debug)
235 {
236 const char *debugfile;
237 l_int32 vsuccess, ret;
238 L_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);
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  *----------------------------------------------------------------------*/
295 l_ok
297 {
298 l_int32 i;
299 L_DEWARP *dew;
300 NUMA *namodels, *napages;
301 
302  PROCNAME("dewarpaListPages");
303 
304  if (!dewa)
305  return ERROR_INT("dewa not defined", procName, 1);
306 
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 
347 l_ok
349  l_int32 notests,
350  l_int32 debug)
351 {
352 l_int32 i, n, maxcurv, diffcurv, diffedge;
353 L_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 
453 l_ok
455  l_int32 notests,
456  l_int32 debug)
457 {
458 l_int32 i, j, n, val, min, distdown, distup;
459 L_DEWARP *dew;
460 NUMA *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 
584 l_ok
586 {
587 l_int32 i;
588 L_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 */
605  return 0;
606 }
607 
608 
625 l_ok
627 {
628 l_int32 i;
629 L_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 */
656  return 0;
657 }
658 
659 
660 /*----------------------------------------------------------------------*
661  * Dewarp debugging output *
662  *----------------------------------------------------------------------*/
670 l_ok
671 dewarpaInfo(FILE *fp,
672  L_DEWARPA *dewa)
673 {
674 l_int32 i, n, pageno, nnone, nvsuccess, nvvalid, nhsuccess, nhvalid, nref;
675 L_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",
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++) {
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 
762 l_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 {
771 l_int32 i, n, pageno, nnone, nvsuccess, nvvalid, nhsuccess, nhvalid, nref;
772 L_DEWARP *dew;
773 
774  PROCNAME("dewarpaModelStats");
775 
776  if (!dewa)
777  return ERROR_INT("dewa not defined", procName, 1);
778 
780  n = numaGetCount(dewa->napages);
781  nnone = nref = nvsuccess = nvvalid = nhsuccess = nhvalid = 0;
782  for (i = 0; i < n; i++) {
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++;
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 
830 static l_int32
832  L_DEWARP *dew,
833  l_int32 notests)
834 {
835 l_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",
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 
918 l_ok
920  l_float32 scalefact,
921  l_int32 first,
922  l_int32 last)
923 {
924 char buf[256];
925 l_int32 i, svd, shd;
926 L_BMF *bmf;
927 L_DEWARP *dew;
928 PIX *pixv, *pixvs, *pixh, *pixhs, *pixt, *pixd;
929 PIXA *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 
1014 l_ok
1016  const char *subdirs,
1017  l_int32 index)
1018 {
1019 char fname[256];
1020 char *outdir;
1021 l_int32 svd, shd;
1022 PIX *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 
1101 l_ok
1103  SARRAY *sa,
1104  BOXA *boxa,
1105  l_int32 firstpage,
1106  l_int32 lastpage,
1107  const char *pdfout)
1108 {
1109 char bufstr[256];
1110 l_int32 i, modelpage;
1111 L_BMF *bmf;
1112 BOX *box;
1113 L_DEWARP *dew;
1114 PIX *pixs, *pixc, *pixd, *pixt1, *pixt2;
1115 PIXA *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 }
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:169
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:230
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_int32 h
Definition: dewarp.h:164
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:2218
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:1102
Definition: pix.h:713
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:478
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:167
L_DEWARP * dewarpCreate(PIX *pixs, l_int32 pageno)
dewarpCreate()
Definition: dewarp1.c:459
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:116
PIX * pixReadIndexed(SARRAY *sa, l_int32 index)
pixReadIndexed()
Definition: readfile.c:281
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3133
l_int32 sampling
Definition: dewarp.h:166
NUMA * numaMakeConstant(l_float32 val, l_int32 size)
numaMakeConstant()
Definition: numafunc1.c:851
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
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:919
void dewarpDestroy(L_DEWARP **pdew)
dewarpDestroy()
Definition: dewarp1.c:518
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
l_int32 refpage
Definition: dewarp.h:179
PIX * pixThresholdToBinary(PIX *pixs, l_int32 thresh)
pixThresholdToBinary()
Definition: grayquant.c:447
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:168
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
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:1026
Definition: pix.h:491
l_int32 max_linecurv
Definition: dewarp.h:127
l_int32 pageno
Definition: dewarp.h:165
Definition: bmf.h:46
Definition: array.h:126
void dewarpaDestroy(L_DEWARPA **pdewa)
dewarpaDestroy()
Definition: dewarp1.c:730
struct L_Dewarpa * dewa
Definition: dewarp.h:153
l_ok dewarpBuildPageModel(L_DEWARP *dew, const char *debugfile)
dewarpBuildPageModel()
Definition: dewarp2.c:156
l_int32 useboth
Definition: dewarp.h:139
l_ok dewarpaListPages(L_DEWARPA *dewa)
dewarpaListPages()
Definition: dewarp4.c:296
struct Pix * pixs
Definition: dewarp.h:154
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:754
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:506
Definition: array.h:70
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:626
l_int32 minlines
Definition: dewarp.h:168
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:658
l_ok dewarpMinimize(L_DEWARP *dew)
dewarpMinimize()
Definition: dewarp3.c:731
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:763
l_ok dewarpaModelStatus(L_DEWARPA *dewa, l_int32 pageno, l_int32 *pvsuccess, l_int32 *phsuccess)
dewarpaModelStatus()
Definition: dewarp2.c:1919
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:746
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:787
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:580
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
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
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:779
Definition: pix.h:711
l_ok dewarpaStripRefModels(L_DEWARPA *dewa)
dewarpaStripRefModels()
Definition: dewarp4.c:585
l_int32 maxcurv
Definition: dewarp.h:171
Definition: pix.h:455
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
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:1044
PIX * pixAdaptThresholdToBinary(PIX *pixs, PIX *pixm, l_float32 gamma)
pixAdaptThresholdToBinary()
Definition: grayquant.c:730
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:812
char * pathJoin(const char *dir, const char *fname)
pathJoin()
Definition: utils2.c:2973
l_ok dewarpaSetValidModels(L_DEWARPA *dewa, l_int32 notests, l_int32 debug)
dewarpaSetValidModels()
Definition: dewarp4.c:348
struct FPix * fullvdispar
Definition: dewarp.h:158
l_ok dewarpaSetCheckColumns(L_DEWARPA *dewa, l_int32 check_columns)
dewarpaSetCheckColumns()
Definition: dewarp1.c:1083
Definition: pix.h:138
l_int32 redfactor
Definition: dewarp.h:123
static l_int32 dewarpaTestForValidModel(L_DEWARPA *dewa, L_DEWARP *dew, l_int32 notests)
dewarpaTestForValidModel()
Definition: dewarp4.c:831
l_ok numaReplaceNumber(NUMA *na, l_int32 index, l_float32 val)
numaReplaceNumber()
Definition: numabasic.c:627
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:282
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:2295
l_ok dewarpaInfo(FILE *fp, L_DEWARPA *dewa)
dewarpaInfo()
Definition: dewarp4.c:671
l_int32 w
Definition: dewarp.h:163
Definition: pix.h:480
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:412
PIX * pixAddSingleTextblock(PIX *pixs, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 location, l_int32 *poverflow)
pixAddSingleTextblock()
Definition: textops.c:120
l_ok dewarpaInsertRefModels(L_DEWARPA *dewa, l_int32 notests, l_int32 debug)
dewarpaInsertRefModels()
Definition: dewarp4.c:454
l_ok dewarpDebug(L_DEWARP *dew, const char *subdirs, l_int32 index)
dewarpDebug()
Definition: dewarp4.c:1015
L_DEWARP * dewarpCreateRef(l_int32 pageno, l_int32 refpage)
dewarpCreateRef()
Definition: dewarp1.c:498
L_DEWARP * dewarpaGetDewarp(L_DEWARPA *dewa, l_int32 index)
dewarpaGetDewarp()
Definition: dewarp1.c:911
PIX * fpixRenderContours(FPIX *fpixs, l_float32 incr, l_float32 proxim)
fpixRenderContours()
Definition: graphics.c:2811
L_BMF * bmfCreate(const char *dir, l_int32 fontsize)
bmfCreate()
Definition: bmf.c:117