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