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  * numa_reg2.c
29  *
30  *   Tests:
31  *     * numa windowed stats
32  *     * numa extraction from pix on a line
33  *     * pixel averages and variances
34  */
35 
36 #include <math.h>
37 #ifndef  _WIN32
38 #include <unistd.h>
39 #else
40 #include <windows.h>   /* for Sleep() */
41 #endif  /* _WIN32 */
42 #include "allheaders.h"
43 
44 #define   DO_ALL     1
45 
46 
main(int argc,char ** argv)47 int main(int    argc,
48          char **argv)
49 {
50 l_int32      i, j;
51 l_int32      w, h, bw, bh, wpls, rval, gval, bval, same;
52 l_uint32     pixel;
53 l_uint32    *lines, *datas;
54 l_float32    sum1, sum2, ave1, ave2, ave3, ave4, diff1, diff2;
55 l_float32    var1, var2, var3;
56 BOX         *box1, *box2;
57 NUMA        *na, *na1, *na2, *na3, *na4;
58 PIX         *pix, *pixs, *pix1, *pix2, *pix3, *pix4, *pix5, *pixg, *pixd;
59 PIXA        *pixa;
60 static char  mainName[] = "numa2_reg";
61 
62     if (argc != 1)
63         return ERROR_INT(" Syntax:  numa2_reg", mainName, 1);
64 
65     setLeptDebugOK(1);
66     lept_mkdir("lept/numa2");
67 
68     /* -------------------------------------------------------------------*
69      *                         Numa-windowed stats                        *
70      * -------------------------------------------------------------------*/
71 #if  DO_ALL
72     na = numaRead("lyra.5.na");
73     numaWindowedStats(na, 5, &na1, &na2, &na3, &na4);
74     gplotSimple1(na, GPLOT_PNG, "/tmp/lept/numa2/lyra6", "Original");
75     gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/numa2/lyra7", "Mean");
76     gplotSimple1(na2, GPLOT_PNG, "/tmp/lept/numa2/lyra8", "Mean Square");
77     gplotSimple1(na3, GPLOT_PNG, "/tmp/lept/numa2/lyra9", "Variance");
78     gplotSimple1(na4, GPLOT_PNG, "/tmp/lept/numa2/lyra10", "RMS Difference");
79     pixa = pixaCreate(5);
80     pix1 = pixRead("/tmp/lept/numa2/lyra6.png");
81     pix2 = pixRead("/tmp/lept/numa2/lyra7.png");
82     pix3 = pixRead("/tmp/lept/numa2/lyra8.png");
83     pix4 = pixRead("/tmp/lept/numa2/lyra9.png");
84     pix5 = pixRead("/tmp/lept/numa2/lyra10.png");
85     pixaAddPix(pixa, pix1, L_INSERT);
86     pixaAddPix(pixa, pix2, L_INSERT);
87     pixaAddPix(pixa, pix3, L_INSERT);
88     pixaAddPix(pixa, pix4, L_INSERT);
89     pixaAddPix(pixa, pix5, L_INSERT);
90     pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2);
91     pixDisplay(pixd, 100, 0);
92     pixWrite("/tmp/lept/numa2/window.png", pixd, IFF_PNG);
93     pixDestroy(&pixd);
94     pixaDestroy(&pixa);
95     numaDestroy(&na);
96     numaDestroy(&na1);
97     numaDestroy(&na2);
98     numaDestroy(&na3);
99     numaDestroy(&na4);
100 #endif
101 
102     /* -------------------------------------------------------------------*
103      *                        Extraction on a line                        *
104      * -------------------------------------------------------------------*/
105 #if  DO_ALL
106         /* First, make a pretty image */
107     w = h = 200;
108     pixs = pixCreate(w, h, 32);
109     wpls = pixGetWpl(pixs);
110     datas = pixGetData(pixs);
111     for (i = 0; i < 200; i++) {
112         lines = datas + i * wpls;
113         for (j = 0; j < 200; j++) {
114             rval = (l_int32)((255. * j) / w + (255. * i) / h);
115             gval = (l_int32)((255. * 2 * j) / w + (255. * 2 * i) / h) % 255;
116             bval = (l_int32)((255. * 4 * j) / w + (255. * 4 * i) / h) % 255;
117             composeRGBPixel(rval, gval, bval, &pixel);
118             lines[j] = pixel;
119         }
120     }
121     pixg = pixConvertTo8(pixs, 0);  /* and a grayscale version */
122     pixWrite("/tmp/lept/numa_pixg.png", pixg, IFF_PNG);
123     pixDisplay(pixg, 450, 100);
124 
125     na1 = pixExtractOnLine(pixg, 20, 20, 180, 20, 1);
126     na2 = pixExtractOnLine(pixg, 40, 30, 40, 170, 1);
127     na3 = pixExtractOnLine(pixg, 20, 170, 180, 30, 1);
128     na4 = pixExtractOnLine(pixg, 20, 190, 180, 10, 1);
129     gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/numa2/ext1", "Horizontal");
130     gplotSimple1(na2, GPLOT_PNG, "/tmp/lept/numa2/ext2", "Vertical");
131     gplotSimple1(na3, GPLOT_PNG, "/tmp/lept/numa2/ext3",
132                 "Slightly more horizontal than vertical");
133     gplotSimple1(na4, GPLOT_PNG, "/tmp/lept/numa2/ext4",
134                 "Slightly more vertical than horizontal");
135     pixa = pixaCreate(4);
136     pix1 = pixRead("/tmp/lept/numa2/ext1.png");
137     pix2 = pixRead("/tmp/lept/numa2/ext2.png");
138     pix3 = pixRead("/tmp/lept/numa2/ext3.png");
139     pix4 = pixRead("/tmp/lept/numa2/ext4.png");
140     pixaAddPix(pixa, pix1, L_INSERT);
141     pixaAddPix(pixa, pix2, L_INSERT);
142     pixaAddPix(pixa, pix3, L_INSERT);
143     pixaAddPix(pixa, pix4, L_INSERT);
144     pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2);
145     pixDisplay(pixd, 100, 450);
146     pixWrite("/tmp/lept/numa2/extract.png", pixd, IFF_PNG);
147     pixDestroy(&pixd);
148     pixaDestroy(&pixa);
149     pixDestroy(&pixg);
150     numaDestroy(&na1);
151     numaDestroy(&na2);
152     numaDestroy(&na3);
153     numaDestroy(&na4);
154 #endif
155 
156     /* -------------------------------------------------------------------*
157      *                     Row and column pixel sums                      *
158      * -------------------------------------------------------------------*/
159 #if  DO_ALL
160         /* Sum by columns in two halves (left and right) */
161     pixs = pixRead("test8.jpg");
162     pixGetDimensions(pixs, &w, &h, NULL);
163     box1 = boxCreate(0, 0, w / 2, h);
164     box2 = boxCreate(w / 2, 0, w - 2 / 2, h);
165     na1 = pixAverageByColumn(pixs, box1, L_BLACK_IS_MAX);
166     na2 = pixAverageByColumn(pixs, box2, L_BLACK_IS_MAX);
167     numaJoin(na1, na2, 0, -1);
168     na3 = pixAverageByColumn(pixs, NULL, L_BLACK_IS_MAX);
169     numaSimilar(na1, na3, 0.0, &same);
170     if (same)
171         fprintf(stderr, "Same for columns\n");
172     else
173         fprintf(stderr, "Error for columns\n");
174     pix = pixConvertTo32(pixs);
175     pixRenderPlotFromNumaGen(&pix, na3, L_HORIZONTAL_LINE, 3, h / 2, 80, 1,
176                              0xff000000);
177     pixRenderPlotFromNuma(&pix, na3, L_PLOT_AT_BOT, 3, 80, 0xff000000);
178     boxDestroy(&box1);
179     boxDestroy(&box2);
180     numaDestroy(&na1);
181     numaDestroy(&na2);
182     numaDestroy(&na3);
183 
184         /* Sum by rows in two halves (top and bottom) */
185     box1 = boxCreate(0, 0, w, h / 2);
186     box2 = boxCreate(0, h / 2, w, h - h / 2);
187     na1 = pixAverageByRow(pixs, box1, L_WHITE_IS_MAX);
188     na2 = pixAverageByRow(pixs, box2, L_WHITE_IS_MAX);
189     numaJoin(na1, na2, 0, -1);
190     na3 = pixAverageByRow(pixs, NULL, L_WHITE_IS_MAX);
191     numaSimilar(na1, na3, 0.0, &same);
192     if (same)
193         fprintf(stderr, "Same for rows\n");
194     else
195         fprintf(stderr, "Error for rows\n");
196     pixRenderPlotFromNumaGen(&pix, na3, L_VERTICAL_LINE, 3, w / 2, 80, 1,
197                              0x00ff0000);
198     pixRenderPlotFromNuma(&pix, na3, L_PLOT_AT_RIGHT, 3, 80, 0x00ff0000);
199     pixDisplay(pix, 500, 200);
200     boxDestroy(&box1);
201     boxDestroy(&box2);
202     numaDestroy(&na1);
203     numaDestroy(&na2);
204     numaDestroy(&na3);
205     pixDestroy(&pix);
206 
207         /* Average left by rows; right by columns; compare totals */
208     box1 = boxCreate(0, 0, w / 2, h);
209     box2 = boxCreate(w / 2, 0, w - 2 / 2, h);
210     na1 = pixAverageByRow(pixs, box1, L_WHITE_IS_MAX);
211     na2 = pixAverageByColumn(pixs, box2, L_WHITE_IS_MAX);
212     numaGetSum(na1, &sum1);  /* sum of averages of left box */
213     numaGetSum(na2, &sum2);  /* sum of averages of right box */
214     ave1 = sum1 / h;
215     ave2 = 2.0 * sum2 / w;
216     ave3 = 0.5 * (ave1 + ave2);  /* average over both halves */
217     fprintf(stderr, "ave1 = %8.4f\n", sum1 / h);
218     fprintf(stderr, "ave2 = %8.4f\n", 2.0 * sum2 / w);
219     pixAverageInRect(pixs, NULL, &ave4);  /* entire image */
220     diff1 = ave4 - ave3;
221     diff2 = w * h * ave4 - (0.5 * w * sum1 + h * sum2);
222     if (diff1 < 0.001)
223         fprintf(stderr, "Average diffs are correct\n");
224     else
225         fprintf(stderr, "Average diffs are wrong: diff1 = %7.5f\n", diff1);
226     if (diff2 < 20)  /* float-to-integer roundoff */
227         fprintf(stderr, "Pixel sums are correct\n");
228     else
229         fprintf(stderr, "Pixel sums are in error: diff = %7.0f\n", diff2);
230 
231         /* Variance left and right halves.  Variance doesn't average
232          * in a simple way, unlike pixel sums. */
233     pixVarianceInRect(pixs, box1, &var1);  /* entire image */
234     pixVarianceInRect(pixs, box2, &var2);  /* entire image */
235     pixVarianceInRect(pixs, NULL, &var3);  /* entire image */
236     fprintf(stderr, "0.5 * (var1 + var2) = %7.3f, var3 = %7.3f\n",
237             0.5 * (var1 + var2), var3);
238     boxDestroy(&box1);
239     boxDestroy(&box2);
240     numaDestroy(&na1);
241     numaDestroy(&na2);
242 #endif
243 
244     /* -------------------------------------------------------------------*
245      *                     Row and column variances                       *
246      * -------------------------------------------------------------------*/
247 #if  DO_ALL
248 
249         /* Display variance by rows and columns */
250     box1 = boxCreate(415, 0, 130, 425);
251     boxGetGeometry(box1, NULL, NULL, &bw, &bh);
252     na1 = pixVarianceByRow(pixs, box1);
253     na2 = pixVarianceByColumn(pixs, box1);
254     pix = pixConvertTo32(pixs);
255     pix1 = pixCopy(NULL, pix);
256     pixRenderPlotFromNumaGen(&pix, na1, L_VERTICAL_LINE, 3, 415, 100, 1,
257                              0xff000000);
258     pixRenderPlotFromNumaGen(&pix, na2, L_HORIZONTAL_LINE, 3, bh / 2, 100, 1,
259                           0x00ff0000);
260     pixRenderPlotFromNuma(&pix1, na1, L_PLOT_AT_LEFT, 3, 60, 0x00ff0000);
261     pixRenderPlotFromNuma(&pix1, na1, L_PLOT_AT_MID_VERT, 3, 60, 0x0000ff00);
262     pixRenderPlotFromNuma(&pix1, na1, L_PLOT_AT_RIGHT, 3, 60, 0xff000000);
263     pixRenderPlotFromNuma(&pix1, na2, L_PLOT_AT_TOP, 3, 60, 0x0000ff00);
264     pixRenderPlotFromNuma(&pix1, na2, L_PLOT_AT_MID_HORIZ, 3, 60, 0xff000000);
265     pixRenderPlotFromNuma(&pix1, na2, L_PLOT_AT_BOT, 3, 60, 0x00ff0000);
266     pixDisplay(pix, 500, 900);
267     pixDisplay(pix1, 500, 1000);
268     boxDestroy(&box1);
269     numaDestroy(&na1);
270     numaDestroy(&na2);
271     pixDestroy(&pix);
272     pixDestroy(&pix1);
273     pixDestroy(&pixs);
274 
275         /* Again on a different image */
276     pix1 = pixRead("boxedpage.jpg");
277     pix2 = pixConvertTo8(pix1, 0);
278     pixGetDimensions(pix2, &w, &h, NULL);
279     na1 = pixVarianceByRow(pix2, NULL);
280     pix3 = pixConvertTo32(pix1);
281     pixRenderPlotFromNumaGen(&pix3, na1, L_VERTICAL_LINE, 3, 0, 70, 1,
282                              0xff000000);
283     na2 = pixVarianceByColumn(pix2, NULL);
284     pixRenderPlotFromNumaGen(&pix3, na2, L_HORIZONTAL_LINE, 3, bh - 1, 70, 1,
285                              0x00ff0000);
286     pixDisplay(pix3, 1000, 0);
287     numaDestroy(&na1);
288     numaDestroy(&na2);
289     pixDestroy(&pix3);
290 
291         /* Again, with an erosion */
292     pix3 = pixErodeGray(pix2, 3, 21);
293     pixDisplay(pix3, 1400, 0);
294     na1 = pixVarianceByRow(pix3, NULL);
295     pix4 = pixConvertTo32(pix1);
296     pixRenderPlotFromNumaGen(&pix4, na1, L_VERTICAL_LINE, 3, 30, 70, 1,
297                              0xff000000);
298     na2 = pixVarianceByColumn(pix3, NULL);
299     pixRenderPlotFromNumaGen(&pix4, na2, L_HORIZONTAL_LINE, 3, bh - 1, 70, 1,
300                              0x00ff0000);
301     pixDisplay(pix4, 1000, 550);
302     numaDestroy(&na1);
303     numaDestroy(&na2);
304     pixDestroy(&pix1);
305     pixDestroy(&pix2);
306     pixDestroy(&pix3);
307     pixDestroy(&pix4);
308 #endif
309 
310     /* -------------------------------------------------------------------*
311      *                    Windowed variance along a line                  *
312      * -------------------------------------------------------------------*/
313 #if  DO_ALL
314     pix1 = pixRead("boxedpage.jpg");
315     pix2 = pixConvertTo8(pix1, 0);
316     pixGetDimensions(pix2, &w, &h, NULL);
317     pix3 = pixCopy(NULL, pix1);
318 
319         /* Plot along horizontal line */
320     pixWindowedVarianceOnLine(pix2, L_HORIZONTAL_LINE, h / 2 - 30, 0,
321                               w, 5, &na1);
322     pixRenderPlotFromNumaGen(&pix1, na1, L_HORIZONTAL_LINE, 3, h / 2 - 30,
323                              80, 1, 0xff000000);
324     pixRenderPlotFromNuma(&pix3, na1, L_PLOT_AT_TOP, 3, 60, 0x00ff0000);
325     pixRenderPlotFromNuma(&pix3, na1, L_PLOT_AT_BOT, 3, 60, 0x0000ff00);
326 
327         /* Plot along vertical line */
328     pixWindowedVarianceOnLine(pix2, L_VERTICAL_LINE, 0.78 * w, 0,
329                               h, 5, &na2);
330     pixRenderPlotFromNumaGen(&pix1, na2, L_VERTICAL_LINE, 3, 0.78 * w, 60,
331                              1, 0x00ff0000);
332     pixRenderPlotFromNuma(&pix3, na2, L_PLOT_AT_LEFT, 3, 60, 0xff000000);
333     pixRenderPlotFromNuma(&pix3, na2, L_PLOT_AT_RIGHT, 3, 60, 0x00ff0000);
334     pixDisplay(pix1, 1000, 1000);
335     pixDisplay(pix3, 1500, 1000);
336     pixDestroy(&pix1);
337     pixDestroy(&pix2);
338     pixDestroy(&pix3);
339     numaDestroy(&na1);
340     numaDestroy(&na2);
341 #endif
342     return 0;
343 }
344