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