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
27 /*
28 * dewarptest3.c
29 *
30 * This exercise functions in dewarp.c for dewarping based on lines
31 * of horizontal text, showing results for different interpolations
32 * (quadratic, cubic, quartic).
33 *
34 * Inspection of the output pdf shows that using LS fitting beyond
35 * quadratic has a tendency to overfit. So we choose to use
36 * quadratic LSF for the textlines.
37 */
38
39 #include "allheaders.h"
40
main(int argc,char ** argv)41 l_int32 main(int argc,
42 char **argv)
43 {
44 l_int32 i, n;
45 l_float32 a, b, c, d, e;
46 NUMA *nax, *nafit;
47 PIX *pixs, *pixn, *pixg, *pixb, *pixt1, *pixt2;
48 PIXA *pixa;
49 PTA *pta, *ptad;
50 PTAA *ptaa1, *ptaa2;
51
52 setLeptDebugOK(1);
53 lept_mkdir("lept");
54
55 pixs = pixRead("cat.035.jpg");
56 /* pixs = pixRead("zanotti-78.jpg"); */
57
58 /* Normalize for varying background and binarize */
59 pixn = pixBackgroundNormSimple(pixs, NULL, NULL);
60 pixg = pixConvertRGBToGray(pixn, 0.5, 0.3, 0.2);
61 pixb = pixThresholdToBinary(pixg, 130);
62 pixDestroy(&pixn);
63 pixDestroy(&pixg);
64
65 /* Get the textline centers */
66 pixa = pixaCreate(6);
67 ptaa1 = dewarpGetTextlineCenters(pixb, 0);
68 pixt1 = pixCreateTemplate(pixs);
69 pixSetAll(pixt1);
70 pixt2 = pixDisplayPtaa(pixt1, ptaa1);
71 pixWrite("/tmp/lept/textline1.png", pixt2, IFF_PNG);
72 pixDisplayWithTitle(pixt2, 0, 100, "textline centers 1", 1);
73 pixaAddPix(pixa, pixt2, L_INSERT);
74 pixDestroy(&pixt1);
75
76 /* Remove short lines */
77 fprintf(stderr, "Num all lines = %d\n", ptaaGetCount(ptaa1));
78 ptaa2 = dewarpRemoveShortLines(pixb, ptaa1, 0.8, 0);
79 pixt1 = pixCreateTemplate(pixs);
80 pixSetAll(pixt1);
81 pixt2 = pixDisplayPtaa(pixt1, ptaa2);
82 pixWrite("/tmp/lept/textline2.png", pixt2, IFF_PNG);
83 pixDisplayWithTitle(pixt2, 300, 100, "textline centers 2", 1);
84 pixaAddPix(pixa, pixt2, L_INSERT);
85 pixDestroy(&pixt1);
86 n = ptaaGetCount(ptaa2);
87 fprintf(stderr, "Num long lines = %d\n", n);
88 ptaaDestroy(&ptaa1);
89 pixDestroy(&pixb);
90
91 /* Long lines over input image */
92 pixt1 = pixCopy(NULL, pixs);
93 pixt2 = pixDisplayPtaa(pixt1, ptaa2);
94 pixWrite("/tmp/lept/textline3.png", pixt2, IFF_PNG);
95 pixDisplayWithTitle(pixt2, 600, 100, "textline centers 3", 1);
96 pixaAddPix(pixa, pixt2, L_INSERT);
97 pixDestroy(&pixt1);
98
99 /* Quadratic fit to curve */
100 pixt1 = pixCopy(NULL, pixs);
101 for (i = 0; i < n; i++) {
102 pta = ptaaGetPta(ptaa2, i, L_CLONE);
103 ptaGetArrays(pta, &nax, NULL);
104 ptaGetQuadraticLSF(pta, &a, &b, &c, &nafit);
105 fprintf(stderr, "Quadratic: a = %10.6f, b = %7.3f, c = %7.3f\n",
106 a, b, c);
107 ptad = ptaCreateFromNuma(nax, nafit);
108 pixDisplayPta(pixt1, pixt1, ptad);
109 ptaDestroy(&pta);
110 ptaDestroy(&ptad);
111 numaDestroy(&nax);
112 numaDestroy(&nafit);
113 }
114 pixWrite("/tmp/lept/textline4.png", pixt1, IFF_PNG);
115 pixDisplayWithTitle(pixt1, 900, 100, "textline centers 4", 1);
116 pixaAddPix(pixa, pixt1, L_INSERT);
117
118 /* Cubic fit to curve */
119 pixt1 = pixCopy(NULL, pixs);
120 for (i = 0; i < n; i++) {
121 pta = ptaaGetPta(ptaa2, i, L_CLONE);
122 ptaGetArrays(pta, &nax, NULL);
123 ptaGetCubicLSF(pta, &a, &b, &c, &d, &nafit);
124 fprintf(stderr, "Cubic: a = %10.6f, b = %10.6f, c = %7.3f, d = %7.3f\n",
125 a, b, c, d);
126 ptad = ptaCreateFromNuma(nax, nafit);
127 pixDisplayPta(pixt1, pixt1, ptad);
128 ptaDestroy(&pta);
129 ptaDestroy(&ptad);
130 numaDestroy(&nax);
131 numaDestroy(&nafit);
132 }
133 pixWrite("/tmp/lept/textline5.png", pixt1, IFF_PNG);
134 pixDisplayWithTitle(pixt1, 1200, 100, "textline centers 5", 1);
135 pixaAddPix(pixa, pixt1, L_INSERT);
136
137 /* Quartic fit to curve */
138 pixt1 = pixCopy(NULL, pixs);
139 for (i = 0; i < n; i++) {
140 pta = ptaaGetPta(ptaa2, i, L_CLONE);
141 ptaGetArrays(pta, &nax, NULL);
142 ptaGetQuarticLSF(pta, &a, &b, &c, &d, &e, &nafit);
143 fprintf(stderr,
144 "Quartic: a = %7.3f, b = %7.3f, c = %9.5f, d = %7.3f, e = %7.3f\n",
145 a, b, c, d, e);
146 ptad = ptaCreateFromNuma(nax, nafit);
147 pixDisplayPta(pixt1, pixt1, ptad);
148 ptaDestroy(&pta);
149 ptaDestroy(&ptad);
150 numaDestroy(&nax);
151 numaDestroy(&nafit);
152 }
153 pixWrite("/tmp/lept/textline6.png", pixt1, IFF_PNG);
154 pixDisplayWithTitle(pixt1, 1500, 100, "textline centers 6", 1);
155 pixaAddPix(pixa, pixt1, L_INSERT);
156
157 pixaConvertToPdf(pixa, 300, 0.5, L_JPEG_ENCODE, 75,
158 "LS fittings to textlines",
159 "/tmp/lept/dewarp_fittings.pdf");
160 pixaDestroy(&pixa);
161 pixDestroy(&pixs);
162 ptaaDestroy(&ptaa2);
163 return 0;
164 }
165