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 * jbclass_reg.c
29 *
30 * Regression test for
31 * jbCorrelation
32 * jbRankhaus
33 */
34
35 #include "allheaders.h"
36
37 /* Choose one of these */
38 #define COMPONENTS JB_CONN_COMPS
39 /* #define COMPONENTS JB_CHARACTERS */
40 /* #define COMPONENTS JB_WORDS */
41
42 static PIXA *PixaOutlineTemplates(PIXA *pixas, NUMA *na);
43
44
main(int argc,char ** argv)45 int main(int argc,
46 char **argv)
47 {
48 l_int32 i, w, h;
49 BOX *box;
50 JBDATA *data;
51 JBCLASSER *classer;
52 NUMA *na;
53 SARRAY *sa;
54 PIX *pix1, *pix2;
55 PIXA *pixa1, *pixa2;
56 L_REGPARAMS *rp;
57
58 if (regTestSetup(argc, argv, &rp))
59 return 1;
60
61 lept_mkdir("lept/class");
62
63 /* Set up the input data */
64 pix1 = pixRead("pageseg1.tif");
65 pixGetDimensions(pix1, &w, &h, NULL);
66 box = boxCreate(0, 0, w, h / 2);
67 pix2 = pixClipRectangle(pix1, box, NULL);
68 pixWrite("/tmp/lept/class/pix1.tif", pix2, IFF_TIFF_G4);
69 pixDestroy(&pix1);
70 pixDestroy(&pix2);
71 pix1 = pixRead("pageseg4.tif");
72 pix2 = pixClipRectangle(pix1, box, NULL);
73 pixWrite("/tmp/lept/class/pix2.tif", pix2, IFF_TIFF_G4);
74 pixDestroy(&pix1);
75 pixDestroy(&pix2);
76 boxDestroy(&box);
77 sa = sarrayCreate(2);
78 sarrayAddString(sa, (char *)"/tmp/lept/class/pix1.tif", L_COPY);
79 sarrayAddString(sa, (char *)"/tmp/lept/class/pix2.tif", L_COPY);
80
81 /*--------------------------------------------------------------*/
82
83 /* Run the correlation-based classifier */
84 classer = jbCorrelationInit(COMPONENTS, 0, 0, 0.8, 0.6);
85 jbAddPages(classer, sa);
86
87 /* Save and write out the result */
88 data = jbDataSave(classer);
89 jbDataWrite("/tmp/lept/class/corr", data);
90 fprintf(stderr, "Number of classes: %d\n", classer->nclass);
91
92 pix1 = pixRead("/tmp/lept/class/corr.templates.png");
93 regTestWritePixAndCheck(rp, pix1, IFF_TIFF_G4); /* 0 */
94 pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display);
95 pixDestroy(&pix1);
96
97 /* Render the pages from the classifier data.
98 * Use debugflag == FALSE to omit outlines of each component. */
99 pixa1 = jbDataRender(data, FALSE);
100 for (i = 0; i < 2; i++) {
101 pix1 = pixaGetPix(pixa1, i, L_CLONE);
102 regTestWritePixAndCheck(rp, pix1, IFF_TIFF_G4); /* 1, 2 */
103 pixDestroy(&pix1);
104 }
105 pixaDestroy(&pixa1);
106
107 /* Display all instances, organized by template */
108 pixa1 = pixaaFlattenToPixa(classer->pixaa, &na, L_CLONE);
109 pixa2 = PixaOutlineTemplates(pixa1, na);
110 pix1 = pixaDisplayTiledInColumns(pixa2, 40, 1.0, 10, 0);
111 regTestWritePixAndCheck(rp, pix1, IFF_TIFF_G4); /* 3 */
112 pixDestroy(&pix1);
113 pixaDestroy(&pixa1);
114 pixaDestroy(&pixa2);
115 numaDestroy(&na);
116 jbClasserDestroy(&classer);
117 jbDataDestroy(&data);
118
119 /*--------------------------------------------------------------*/
120
121 lept_mkdir("lept/class2");
122
123 /* Run the rank hausdorff-based classifier */
124 classer = jbRankHausInit(COMPONENTS, 0, 0, 2, 0.97);
125 jbAddPages(classer, sa);
126
127 /* Save and write out the result */
128 data = jbDataSave(classer);
129 jbDataWrite("/tmp/lept/class2/haus", data);
130 fprintf(stderr, "Number of classes: %d\n", classer->nclass);
131
132 pix1 = pixRead("/tmp/lept/class2/haus.templates.png");
133 regTestWritePixAndCheck(rp, pix1, IFF_TIFF_G4); /* 4 */
134 pixDisplayWithTitle(pix1, 200, 0, NULL, rp->display);
135 pixDestroy(&pix1);
136
137 /* Render the pages from the classifier data.
138 * Use debugflag == FALSE to omit outlines of each component. */
139 pixa1 = jbDataRender(data, FALSE);
140 for (i = 0; i < 2; i++) {
141 pix1 = pixaGetPix(pixa1, i, L_CLONE);
142 regTestWritePixAndCheck(rp, pix1, IFF_TIFF_G4); /* 5, 6 */
143 pixDestroy(&pix1);
144 }
145 pixaDestroy(&pixa1);
146
147 /* Display all instances, organized by template */
148 pixa1 = pixaaFlattenToPixa(classer->pixaa, &na, L_CLONE);
149 pixa2 = PixaOutlineTemplates(pixa1, na);
150 pix1 = pixaDisplayTiledInColumns(pixa2, 40, 1.0, 10, 0);
151 regTestWritePixAndCheck(rp, pix1, IFF_TIFF_G4); /* 7 */
152 pixDestroy(&pix1);
153 pixaDestroy(&pixa1);
154 pixaDestroy(&pixa2);
155 numaDestroy(&na);
156 jbClasserDestroy(&classer);
157 jbDataDestroy(&data);
158
159 /*--------------------------------------------------------------*/
160
161 sarrayDestroy(&sa);
162 return regTestCleanup(rp);
163 }
164
165
166 static PIXA *
PixaOutlineTemplates(PIXA * pixas,NUMA * na)167 PixaOutlineTemplates(PIXA *pixas,
168 NUMA *na)
169 {
170 l_int32 i, n, val, prev, curr;
171 NUMA *nai;
172 PIX *pix1, *pix2, *pix3;
173 PIXA *pixad;
174
175 /* Make an indicator array with a 1 for each template image */
176 n = numaGetCount(na);
177 nai = numaCreate(n);
178 prev = -1;
179 for (i = 0; i < n; i++) {
180 numaGetIValue(na, i, &curr);
181 if (curr != prev) { /* index change */
182 prev = curr;
183 numaAddNumber(nai, 1);
184 } else {
185 numaAddNumber(nai, 0);
186 }
187 }
188
189 /* Add a boundary of 3 white and 1 black pixels to templates */
190 pixad = pixaCreate(n);
191 for (i = 0; i < n; i++) {
192 pix1 = pixaGetPix(pixas, i, L_CLONE);
193 numaGetIValue(nai, i, &val);
194 if (val == 0) {
195 pixaAddPix(pixad, pix1, L_INSERT);
196 } else {
197 pix2 = pixAddBorder(pix1, 3, 0);
198 pix3 = pixAddBorder(pix2, 1, 1);
199 pixaAddPix(pixad, pix3, L_INSERT);
200 pixDestroy(&pix1);
201 pixDestroy(&pix2);
202 }
203 }
204
205 numaDestroy(&nai);
206 return pixad;
207 }
208