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  *   label_reg.c
29  *
30  *    Regression test for earthmover distance and these labelling operations:
31  *         Connected component labelling
32  *         Connected component area labelling
33  *         Color coded transform of 1 bpp images
34  */
35 
36 #include "allheaders.h"
37 
38 void FindEMD(PIX *pix1, PIX *pix2, l_float32 *pdistr, l_float32 *pdistg,
39              l_float32 *pdistb);
40 
main(int argc,char ** argv)41 l_int32 main(int    argc,
42              char **argv)
43 {
44 l_float32     dist, distr, distg, distb;
45 NUMA         *na1, *na2;
46 PIX          *pix1, *pix2, *pix3, *pix4, *pix5, *pix6;
47 L_REGPARAMS  *rp;
48 
49     if (regTestSetup(argc, argv, &rp))
50         return 1;
51 
52         /* Test earthmover distance: extreme example */
53     fprintf(stderr, "Test earthmover distance\n");
54     na1 = numaMakeConstant(0, 201);
55     na2 = numaMakeConstant(0, 201);
56     numaSetValue(na1, 0, 100);
57     numaSetValue(na2, 200, 100);
58     numaEarthMoverDistance(na1, na2, &dist);
59     regTestCompareValues(rp, 200.0, dist, 0.0001);  /* 0 */
60     numaDestroy(&na1);
61     numaDestroy(&na2);
62 
63         /* Test connected component labelling */
64     fprintf(stderr, "Test c.c. labelling\n");
65     pix1 = pixRead("feyn-fract.tif");
66     pix2 = pixConnCompTransform(pix1, 8, 8);
67     regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 1 */
68     pixDisplayWithTitle(pix2, 0, 0, NULL, rp->display);
69     pix3 = pixConnCompTransform(pix1, 8, 16);
70     pix4 = pixConvert16To8(pix3, L_LS_BYTE);
71     regTestCompareSimilarPix(rp, pix2, pix4, 3, 0.001, 0);  /* 2 */
72     pix5 = pixConnCompTransform(pix1, 8, 32);
73     pix6 = pixConvert32To8(pix5, L_LS_TWO_BYTES, L_LS_BYTE);
74     regTestCompareSimilarPix(rp, pix2, pix6, 3, 0.001, 0);  /* 3 */
75     pixDestroy(&pix2);
76     pixDestroy(&pix3);
77     pixDestroy(&pix4);
78     pixDestroy(&pix5);
79     pixDestroy(&pix6);
80 
81         /* Test connected component area labelling */
82     fprintf(stderr, "Test c.c. area labelling\n");
83     pix2 = pixConnCompAreaTransform(pix1, 8);
84     pix3 = pixConvert32To8(pix2, L_LS_TWO_BYTES, L_CLIP_TO_FF);
85     regTestWritePixAndCheck(rp, pix3, IFF_PNG);  /* 4 */
86     pixDisplayWithTitle(pix3, 0, 350, NULL, rp->display);
87     pixMultConstantGray(pix2, 0.3);
88     pix4 = pixConvert32To8(pix2, L_LS_TWO_BYTES, L_CLIP_TO_FF);
89     regTestWritePixAndCheck(rp, pix4, IFF_PNG);  /* 5 */
90     pixDisplayWithTitle(pix4, 0, 700, NULL, rp->display);
91     pixDestroy(&pix1);
92     pixDestroy(&pix2);
93     pixDestroy(&pix3);
94     pixDestroy(&pix4);
95 
96         /* Test color transform: 4-fold symmetry */
97     fprintf(stderr, "Test color transform: 4-fold symmetry\n");
98     pix1 = pixRead("form1.tif");
99     pix2 = pixRotateOrth(pix1, 1);
100     pix3 = pixRotateOrth(pix1, 2);
101     pix4 = pixRotateOrth(pix1, 3);
102     pix5 = pixLocToColorTransform(pix1);
103     regTestWritePixAndCheck(rp, pix5, IFF_PNG);  /* 6 */
104     pix6 = pixLocToColorTransform(pix2);
105     regTestWritePixAndCheck(rp, pix6, IFF_PNG);  /* 7 */
106     FindEMD(pix5, pix6, &distr, &distg, &distb);
107     regTestCompareValues(rp, 0.12, distr, 0.01);  /* 8 */
108     regTestCompareValues(rp, 0.00, distg, 0.01);  /* 9 */
109     regTestCompareValues(rp, 0.00, distb, 0.01);  /* 10 */
110     fprintf(stderr, "90 deg rotation: dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n",
111             distr, distg, distb);
112     pixDestroy(&pix6);
113     pix6 = pixLocToColorTransform(pix3);
114     regTestWritePixAndCheck(rp, pix6, IFF_PNG);  /* 11 */
115     FindEMD(pix5, pix6, &distr, &distg, &distb);
116     regTestCompareValues(rp, 0.12, distr, 0.01);  /* 12 */
117     regTestCompareValues(rp, 0.09, distg, 0.01);  /* 13 */
118     regTestCompareValues(rp, 0.00, distb, 0.01);  /* 14 */
119     fprintf(stderr, "180 deg rotation: dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n",
120             distr, distg, distb);
121     pixDestroy(&pix6);
122     pix6 = pixLocToColorTransform(pix4);
123     regTestWritePixAndCheck(rp, pix6, IFF_PNG);  /* 15 */
124     FindEMD(pix5, pix6, &distr, &distg, &distb);
125     regTestCompareValues(rp, 0.00, distr, 0.01);  /* 16 */
126     regTestCompareValues(rp, 0.09, distg, 0.01);  /* 17 */
127     regTestCompareValues(rp, 0.00, distb, 0.01);  /* 18 */
128     fprintf(stderr, "270 deg rotation: dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n",
129             distr, distg, distb);
130     pixDestroy(&pix1);
131     pixDestroy(&pix2);
132     pixDestroy(&pix3);
133     pixDestroy(&pix4);
134     pixDestroy(&pix5);
135     pixDestroy(&pix6);
136 
137         /* Test color transform: same form with translation */
138     fprintf(stderr, "Test color transform with translation\n");
139     pix1 = pixRead("form1.tif");
140     pix2 = pixLocToColorTransform(pix1);
141     pixDisplayWithTitle(pix2, 0, 0, NULL, rp->display);
142     pixTranslate(pix1, pix1, 10, 10, L_BRING_IN_WHITE);
143     pix3 = pixLocToColorTransform(pix1);
144     regTestWritePixAndCheck(rp, pix3, IFF_PNG);  /* 19 */
145     pixDisplayWithTitle(pix3, 470, 0, NULL, rp->display);
146     FindEMD(pix2, pix3, &distr, &distg, &distb);
147     regTestCompareValues(rp, 1.76, distr, 0.01);  /* 20 */
148     regTestCompareValues(rp, 2.65, distg, 0.01);  /* 21 */
149     regTestCompareValues(rp, 2.03, distb, 0.01);  /* 22 */
150     fprintf(stderr, "Translation dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n",
151             distr, distg, distb);
152     pixDestroy(&pix1);
153     pixDestroy(&pix2);
154     pixDestroy(&pix3);
155 
156         /* Test color transform: same form with small rotation */
157     fprintf(stderr, "Test color transform with small rotation\n");
158     pix1 = pixRead("form1.tif");
159     pix2 = pixLocToColorTransform(pix1);
160     pixRotateShearCenterIP(pix1, 0.1, L_BRING_IN_WHITE);
161     pix3 = pixLocToColorTransform(pix1);
162     regTestWritePixAndCheck(rp, pix3, IFF_PNG);  /* 23 */
163     pixDisplayWithTitle(pix3, 880, 0, NULL, rp->display);
164     FindEMD(pix2, pix3, &distr, &distg, &distb);
165     regTestCompareValues(rp, 1.50, distr, 0.01);  /* 24 */
166     regTestCompareValues(rp, 1.71, distg, 0.01);  /* 25 */
167     regTestCompareValues(rp, 1.42, distb, 0.01);  /* 26 */
168     fprintf(stderr, "Rotation dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n",
169             distr, distg, distb);
170     pixDestroy(&pix1);
171     pixDestroy(&pix2);
172     pixDestroy(&pix3);
173 
174         /* Test color transform: 2 different forms */
175     fprintf(stderr, "Test color transform (2 forms)\n");
176     pix1 = pixRead("form1.tif");
177     pix2 = pixLocToColorTransform(pix1);
178     pixDisplayWithTitle(pix2, 0, 600, NULL, rp->display);
179     pix3 = pixRead("form2.tif");
180     pix4 = pixLocToColorTransform(pix3);
181     regTestWritePixAndCheck(rp, pix4, IFF_PNG);  /* 27 */
182     pixDisplayWithTitle(pix4, 470, 600, NULL, rp->display);
183     FindEMD(pix2, pix4, &distr, &distg, &distb);
184     regTestCompareValues(rp, 6.10, distr, 0.02);  /* 28 */
185     regTestCompareValues(rp, 11.13, distg, 0.01);  /* 29 */
186     regTestCompareValues(rp, 10.53, distb, 0.01);  /* 30 */
187     fprintf(stderr, "Different forms: dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n",
188             distr, distg, distb);
189     pixDestroy(&pix1);
190     pixDestroy(&pix2);
191     pixDestroy(&pix3);
192     pixDestroy(&pix4);
193 
194     return regTestCleanup(rp);
195 }
196 
197 
FindEMD(PIX * pix1,PIX * pix2,l_float32 * pdistr,l_float32 * pdistg,l_float32 * pdistb)198 void FindEMD(PIX *pix1, PIX *pix2,
199              l_float32 *pdistr, l_float32 *pdistg, l_float32 *pdistb)
200 {
201 NUMA  *nar1, *nar2, *nag1, *nag2, *nab1, *nab2;
202 
203     pixGetColorHistogram(pix1, 1, &nar1, &nag1, &nab1);
204     pixGetColorHistogram(pix2, 1, &nar2, &nag2, &nab2);
205     numaEarthMoverDistance(nar1, nar2, pdistr);
206     numaEarthMoverDistance(nag1, nag2, pdistg);
207     numaEarthMoverDistance(nab1, nab2, pdistb);
208     numaDestroy(&nar1);
209     numaDestroy(&nar2);
210     numaDestroy(&nag1);
211     numaDestroy(&nag2);
212     numaDestroy(&nab1);
213     numaDestroy(&nab2);
214     return;
215 }
216 
217