Leptonica  1.77.0
Image processing and image analysis suite
sel2.c
Go to the documentation of this file.
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 
61 #include <math.h>
62 #include "allheaders.h"
63 
64 static const l_int32 L_BUF_SIZE = 512;
65 
66  /* Linear brick sel sizes, including all those that are required
67  * for decomposable sels up to size 63. */
68 static const l_int32 num_linear = 25;
69 static const l_int32 basic_linear[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
70  12, 13, 14, 15, 20, 21, 25, 30, 31, 35, 40, 41, 45, 50, 51};
71 
72 
73 /* ------------------------------------------------------------------- *
74  * Basic brick structuring elements *
75  * ------------------------------------------------------------------- */
91 SELA *
93 {
94 char name[L_BUF_SIZE];
95 l_int32 i, size;
96 SEL *sel;
97 
98  PROCNAME("selaAddBasic");
99 
100  if (!sela) {
101  if ((sela = selaCreate(0)) == NULL)
102  return (SELA *)ERROR_PTR("sela not made", procName, NULL);
103  }
104 
105  /*--------------------------------------------------------------*
106  * Linear horizontal and vertical sels *
107  *--------------------------------------------------------------*/
108  for (i = 0; i < num_linear; i++) {
109  size = basic_linear[i];
110  sel = selCreateBrick(1, size, 0, size / 2, 1);
111  snprintf(name, L_BUF_SIZE, "sel_%dh", size);
112  selaAddSel(sela, sel, name, 0);
113  }
114  for (i = 0; i < num_linear; i++) {
115  size = basic_linear[i];
116  sel = selCreateBrick(size, 1, size / 2, 0, 1);
117  snprintf(name, L_BUF_SIZE, "sel_%dv", size);
118  selaAddSel(sela, sel, name, 0);
119  }
120 
121  /*-----------------------------------------------------------*
122  * 2-d Bricks *
123  *-----------------------------------------------------------*/
124  for (i = 2; i <= 5; i++) {
125  sel = selCreateBrick(i, i, i / 2, i / 2, 1);
126  snprintf(name, L_BUF_SIZE, "sel_%d", i);
127  selaAddSel(sela, sel, name, 0);
128  }
129 
130  /*-----------------------------------------------------------*
131  * Diagonals *
132  *-----------------------------------------------------------*/
133  /* 0c 1
134  1 0 */
135  sel = selCreateBrick(2, 2, 0, 0, 1);
136  selSetElement(sel, 0, 0, 0);
137  selSetElement(sel, 1, 1, 0);
138  selaAddSel(sela, sel, "sel_2dp", 0);
139 
140  /* 1c 0
141  0 1 */
142  sel = selCreateBrick(2, 2, 0, 0, 1);
143  selSetElement(sel, 0, 1, 0);
144  selSetElement(sel, 1, 0, 0);
145  selaAddSel(sela, sel, "sel_2dm", 0);
146 
147  /* Diagonal, slope +, size 5 */
148  sel = selCreate(5, 5, "sel_5dp");
149  selSetOrigin(sel, 2, 2);
150  selSetElement(sel, 0, 4, 1);
151  selSetElement(sel, 1, 3, 1);
152  selSetElement(sel, 2, 2, 1);
153  selSetElement(sel, 3, 1, 1);
154  selSetElement(sel, 4, 0, 1);
155  selaAddSel(sela, sel, "sel_5dp", 0);
156 
157  /* Diagonal, slope -, size 5 */
158  sel = selCreate(5, 5, "sel_5dm");
159  selSetOrigin(sel, 2, 2);
160  selSetElement(sel, 0, 0, 1);
161  selSetElement(sel, 1, 1, 1);
162  selSetElement(sel, 2, 2, 1);
163  selSetElement(sel, 3, 3, 1);
164  selSetElement(sel, 4, 4, 1);
165  selaAddSel(sela, sel, "sel_5dm", 0);
166 
167  return sela;
168 }
169 
170 
171 /* ------------------------------------------------------------------- *
172  * Simple hit-miss structuring elements *
173  * ------------------------------------------------------------------- */
180 SELA *
182 {
183 SEL *sel;
184 
185  PROCNAME("selaAddHitMiss");
186 
187  if (!sela) {
188  if ((sela = selaCreate(0)) == NULL)
189  return (SELA *)ERROR_PTR("sela not made", procName, NULL);
190  }
191 
192 #if 0 /* use just for testing */
193  sel = selCreateBrick(3, 3, 1, 1, 2);
194  selaAddSel(sela, sel, "sel_bad", 0);
195 #endif
196 
197 
198  /*--------------------------------------------------------------*
199  * Isolated foreground pixel *
200  *--------------------------------------------------------------*/
201  sel = selCreateBrick(3, 3, 1, 1, SEL_MISS);
202  selSetElement(sel, 1, 1, SEL_HIT);
203  selaAddSel(sela, sel, "sel_3hm", 0);
204 
205  /*--------------------------------------------------------------*
206  * Horizontal and vertical edges *
207  *--------------------------------------------------------------*/
208  sel = selCreateBrick(2, 3, 0, 1, SEL_HIT);
209  selSetElement(sel, 1, 0, SEL_MISS);
210  selSetElement(sel, 1, 1, SEL_MISS);
211  selSetElement(sel, 1, 2, SEL_MISS);
212  selaAddSel(sela, sel, "sel_3de", 0);
213 
214  sel = selCreateBrick(2, 3, 1, 1, SEL_HIT);
215  selSetElement(sel, 0, 0, SEL_MISS);
216  selSetElement(sel, 0, 1, SEL_MISS);
217  selSetElement(sel, 0, 2, SEL_MISS);
218  selaAddSel(sela, sel, "sel_3ue", 0);
219 
220  sel = selCreateBrick(3, 2, 1, 0, SEL_HIT);
221  selSetElement(sel, 0, 1, SEL_MISS);
222  selSetElement(sel, 1, 1, SEL_MISS);
223  selSetElement(sel, 2, 1, SEL_MISS);
224  selaAddSel(sela, sel, "sel_3re", 0);
225 
226  sel = selCreateBrick(3, 2, 1, 1, SEL_HIT);
227  selSetElement(sel, 0, 0, SEL_MISS);
228  selSetElement(sel, 1, 0, SEL_MISS);
229  selSetElement(sel, 2, 0, SEL_MISS);
230  selaAddSel(sela, sel, "sel_3le", 0);
231 
232  /*--------------------------------------------------------------*
233  * Slanted edge *
234  *--------------------------------------------------------------*/
235  sel = selCreateBrick(13, 6, 6, 2, SEL_DONT_CARE);
236  selSetElement(sel, 0, 3, SEL_MISS);
237  selSetElement(sel, 0, 5, SEL_HIT);
238  selSetElement(sel, 4, 2, SEL_MISS);
239  selSetElement(sel, 4, 4, SEL_HIT);
240  selSetElement(sel, 8, 1, SEL_MISS);
241  selSetElement(sel, 8, 3, SEL_HIT);
242  selSetElement(sel, 12, 0, SEL_MISS);
243  selSetElement(sel, 12, 2, SEL_HIT);
244  selaAddSel(sela, sel, "sel_sl1", 0);
245 
246  /*--------------------------------------------------------------*
247  * Corners *
248  * This allows for up to 3 missing edge pixels at the corner *
249  *--------------------------------------------------------------*/
250  sel = selCreateBrick(4, 4, 1, 1, SEL_MISS);
251  selSetElement(sel, 1, 1, SEL_DONT_CARE);
252  selSetElement(sel, 1, 2, SEL_DONT_CARE);
253  selSetElement(sel, 2, 1, SEL_DONT_CARE);
254  selSetElement(sel, 1, 3, SEL_HIT);
255  selSetElement(sel, 2, 2, SEL_HIT);
256  selSetElement(sel, 2, 3, SEL_HIT);
257  selSetElement(sel, 3, 1, SEL_HIT);
258  selSetElement(sel, 3, 2, SEL_HIT);
259  selSetElement(sel, 3, 3, SEL_HIT);
260  selaAddSel(sela, sel, "sel_ulc", 0);
261 
262  sel = selCreateBrick(4, 4, 1, 2, SEL_MISS);
263  selSetElement(sel, 1, 1, SEL_DONT_CARE);
264  selSetElement(sel, 1, 2, SEL_DONT_CARE);
265  selSetElement(sel, 2, 2, SEL_DONT_CARE);
266  selSetElement(sel, 1, 0, SEL_HIT);
267  selSetElement(sel, 2, 0, SEL_HIT);
268  selSetElement(sel, 2, 1, SEL_HIT);
269  selSetElement(sel, 3, 0, SEL_HIT);
270  selSetElement(sel, 3, 1, SEL_HIT);
271  selSetElement(sel, 3, 2, SEL_HIT);
272  selaAddSel(sela, sel, "sel_urc", 0);
273 
274  sel = selCreateBrick(4, 4, 2, 1, SEL_MISS);
275  selSetElement(sel, 1, 1, SEL_DONT_CARE);
276  selSetElement(sel, 2, 1, SEL_DONT_CARE);
277  selSetElement(sel, 2, 2, SEL_DONT_CARE);
278  selSetElement(sel, 0, 1, SEL_HIT);
279  selSetElement(sel, 0, 2, SEL_HIT);
280  selSetElement(sel, 0, 3, SEL_HIT);
281  selSetElement(sel, 1, 2, SEL_HIT);
282  selSetElement(sel, 1, 3, SEL_HIT);
283  selSetElement(sel, 2, 3, SEL_HIT);
284  selaAddSel(sela, sel, "sel_llc", 0);
285 
286  sel = selCreateBrick(4, 4, 2, 2, SEL_MISS);
287  selSetElement(sel, 1, 2, SEL_DONT_CARE);
288  selSetElement(sel, 2, 1, SEL_DONT_CARE);
289  selSetElement(sel, 2, 2, SEL_DONT_CARE);
290  selSetElement(sel, 0, 0, SEL_HIT);
291  selSetElement(sel, 0, 1, SEL_HIT);
292  selSetElement(sel, 0, 2, SEL_HIT);
293  selSetElement(sel, 1, 0, SEL_HIT);
294  selSetElement(sel, 1, 1, SEL_HIT);
295  selSetElement(sel, 2, 0, SEL_HIT);
296  selaAddSel(sela, sel, "sel_lrc", 0);
297 
298  return sela;
299 }
300 
301 
302 /* ------------------------------------------------------------------- *
303  * Structuring elements for comparing with DWA operations *
304  * ------------------------------------------------------------------- */
318 SELA *
320 {
321 char name[L_BUF_SIZE];
322 l_int32 i;
323 SEL *sel;
324 
325  PROCNAME("selaAddDwaLinear");
326 
327  if (!sela) {
328  if ((sela = selaCreate(0)) == NULL)
329  return (SELA *)ERROR_PTR("sela not made", procName, NULL);
330  }
331 
332  for (i = 2; i < 64; i++) {
333  sel = selCreateBrick(1, i, 0, i / 2, 1);
334  snprintf(name, L_BUF_SIZE, "sel_%dh", i);
335  selaAddSel(sela, sel, name, 0);
336  }
337  for (i = 2; i < 64; i++) {
338  sel = selCreateBrick(i, 1, i / 2, 0, 1);
339  snprintf(name, L_BUF_SIZE, "sel_%dv", i);
340  selaAddSel(sela, sel, name, 0);
341  }
342  return sela;
343 }
344 
345 
360 SELA *
362 {
363 char name[L_BUF_SIZE];
364 l_int32 i, f1, f2, prevsize, size;
365 SEL *selh, *selv;
366 
367  PROCNAME("selaAddDwaCombs");
368 
369  if (!sela) {
370  if ((sela = selaCreate(0)) == NULL)
371  return (SELA *)ERROR_PTR("sela not made", procName, NULL);
372  }
373 
374  prevsize = 0;
375  for (i = 4; i < 64; i++) {
376  selectComposableSizes(i, &f1, &f2);
377  size = f1 * f2;
378  if (size == prevsize)
379  continue;
380  selectComposableSels(i, L_HORIZ, NULL, &selh);
381  selectComposableSels(i, L_VERT, NULL, &selv);
382  snprintf(name, L_BUF_SIZE, "sel_comb_%dh", size);
383  selaAddSel(sela, selh, name, 0);
384  snprintf(name, L_BUF_SIZE, "sel_comb_%dv", size);
385  selaAddSel(sela, selv, name, 0);
386  prevsize = size;
387  }
388 
389  return sela;
390 }
391 
392 
393 /* ------------------------------------------------------------------- *
394  * Structuring elements for the intersection of lines *
395  * ------------------------------------------------------------------- */
422 SELA *
424  l_float32 hlsize,
425  l_float32 mdist,
426  l_int32 norient,
427  l_int32 debugflag)
428 {
429 char name[L_BUF_SIZE];
430 l_int32 i, j, w, xc, yc;
431 l_float64 pi, halfpi, radincr, radang;
432 l_float64 angle;
433 PIX *pixc, *pixm, *pixt;
434 PIXA *pixa;
435 PTA *pta1, *pta2, *pta3, *pta4;
436 SEL *sel;
437 
438  PROCNAME("selaAddCrossJunctions");
439 
440  if (hlsize <= 0)
441  return (SELA *)ERROR_PTR("hlsize not > 0", procName, NULL);
442  if (norient < 1 || norient > 8)
443  return (SELA *)ERROR_PTR("norient not in [1, ... 8]", procName, NULL);
444 
445  if (!sela) {
446  if ((sela = selaCreate(0)) == NULL)
447  return (SELA *)ERROR_PTR("sela not made", procName, NULL);
448  }
449 
450  pi = 3.1415926535;
451  halfpi = 3.1415926535 / 2.0;
452  radincr = halfpi / (l_float64)norient;
453  w = (l_int32)(2.2 * (L_MAX(hlsize, mdist) + 0.5));
454  if (w % 2 == 0)
455  w++;
456  xc = w / 2;
457  yc = w / 2;
458 
459  pixa = pixaCreate(norient);
460  for (i = 0; i < norient; i++) {
461 
462  /* Set the don't cares */
463  pixc = pixCreate(w, w, 32);
464  pixSetAll(pixc);
465 
466  /* Add the green lines of hits */
467  pixm = pixCreate(w, w, 1);
468  radang = (l_float32)i * radincr;
469  pta1 = generatePtaLineFromPt(xc, yc, hlsize + 1, radang);
470  pta2 = generatePtaLineFromPt(xc, yc, hlsize + 1, radang + halfpi);
471  pta3 = generatePtaLineFromPt(xc, yc, hlsize + 1, radang + pi);
472  pta4 = generatePtaLineFromPt(xc, yc, hlsize + 1, radang + pi + halfpi);
473  ptaJoin(pta1, pta2, 0, -1);
474  ptaJoin(pta1, pta3, 0, -1);
475  ptaJoin(pta1, pta4, 0, -1);
476  pixRenderPta(pixm, pta1, L_SET_PIXELS);
477  pixPaintThroughMask(pixc, pixm, 0, 0, 0x00ff0000);
478  ptaDestroy(&pta1);
479  ptaDestroy(&pta2);
480  ptaDestroy(&pta3);
481  ptaDestroy(&pta4);
482 
483  /* Add red misses between the lines */
484  for (j = 0; j < 4; j++) {
485  angle = radang + (j - 0.5) * halfpi;
486  pixSetPixel(pixc, xc + (l_int32)(mdist * cos(angle)),
487  yc + (l_int32)(mdist * sin(angle)), 0xff000000);
488  }
489 
490  /* Add dark green for origin */
491  pixSetPixel(pixc, xc, yc, 0x00550000);
492 
493  /* Generate the sel */
494  sel = selCreateFromColorPix(pixc, NULL);
495  snprintf(name, sizeof(name), "sel_cross_%d", i);
496  selaAddSel(sela, sel, name, 0);
497 
498  if (debugflag) {
499  pixt = pixScaleBySampling(pixc, 10.0, 10.0);
500  pixaAddPix(pixa, pixt, L_INSERT);
501  }
502  pixDestroy(&pixm);
503  pixDestroy(&pixc);
504  }
505 
506  if (debugflag) {
507  l_int32 w;
508  lept_mkdir("lept/sel");
509  pixaGetPixDimensions(pixa, 0, &w, NULL, NULL);
510  pixt = pixaDisplayTiledAndScaled(pixa, 32, w, 1, 0, 10, 2);
511  pixWriteDebug("/tmp/lept/sel/xsel1.png", pixt, IFF_PNG);
512  pixDisplay(pixt, 0, 100);
513  pixDestroy(&pixt);
514  pixt = selaDisplayInPix(sela, 15, 2, 20, 1);
515  pixWriteDebug("/tmp/lept/sel/xsel2.png", pixt, IFF_PNG);
516  pixDisplay(pixt, 500, 100);
517  pixDestroy(&pixt);
518  selaWriteStream(stderr, sela);
519  }
520  pixaDestroy(&pixa);
521 
522  return sela;
523 }
524 
525 
547 SELA *
549  l_float32 hlsize,
550  l_float32 mdist,
551  l_int32 norient,
552  l_int32 debugflag)
553 {
554 char name[L_BUF_SIZE];
555 l_int32 i, j, k, w, xc, yc;
556 l_float64 pi, halfpi, radincr, jang, radang;
557 l_float64 angle[3], dist[3];
558 PIX *pixc, *pixm, *pixt;
559 PIXA *pixa;
560 PTA *pta1, *pta2, *pta3;
561 SEL *sel;
562 
563  PROCNAME("selaAddTJunctions");
564 
565  if (hlsize <= 2)
566  return (SELA *)ERROR_PTR("hlsizel not > 1", procName, NULL);
567  if (norient < 1 || norient > 8)
568  return (SELA *)ERROR_PTR("norient not in [1, ... 8]", procName, NULL);
569 
570  if (!sela) {
571  if ((sela = selaCreate(0)) == NULL)
572  return (SELA *)ERROR_PTR("sela not made", procName, NULL);
573  }
574 
575  pi = 3.1415926535;
576  halfpi = 3.1415926535 / 2.0;
577  radincr = halfpi / (l_float32)norient;
578  w = (l_int32)(2.4 * (L_MAX(hlsize, mdist) + 0.5));
579  if (w % 2 == 0)
580  w++;
581  xc = w / 2;
582  yc = w / 2;
583 
584  pixa = pixaCreate(4 * norient);
585  for (i = 0; i < norient; i++) {
586  for (j = 0; j < 4; j++) { /* 4 orthogonal orientations */
587  jang = (l_float32)j * halfpi;
588 
589  /* Set the don't cares */
590  pixc = pixCreate(w, w, 32);
591  pixSetAll(pixc);
592 
593  /* Add the green lines of hits */
594  pixm = pixCreate(w, w, 1);
595  radang = (l_float32)i * radincr;
596  pta1 = generatePtaLineFromPt(xc, yc, hlsize + 1, jang + radang);
597  pta2 = generatePtaLineFromPt(xc, yc, hlsize + 1,
598  jang + radang + halfpi);
599  pta3 = generatePtaLineFromPt(xc, yc, hlsize + 1,
600  jang + radang + pi);
601  ptaJoin(pta1, pta2, 0, -1);
602  ptaJoin(pta1, pta3, 0, -1);
603  pixRenderPta(pixm, pta1, L_SET_PIXELS);
604  pixPaintThroughMask(pixc, pixm, 0, 0, 0x00ff0000);
605  ptaDestroy(&pta1);
606  ptaDestroy(&pta2);
607  ptaDestroy(&pta3);
608 
609  /* Add red misses between the lines */
610  angle[0] = radang + jang - halfpi;
611  angle[1] = radang + jang + 0.5 * halfpi;
612  angle[2] = radang + jang + 1.5 * halfpi;
613  dist[0] = 0.8 * mdist;
614  dist[1] = dist[2] = mdist;
615  for (k = 0; k < 3; k++) {
616  pixSetPixel(pixc, xc + (l_int32)(dist[k] * cos(angle[k])),
617  yc + (l_int32)(dist[k] * sin(angle[k])),
618  0xff000000);
619  }
620 
621  /* Add dark green for origin */
622  pixSetPixel(pixc, xc, yc, 0x00550000);
623 
624  /* Generate the sel */
625  sel = selCreateFromColorPix(pixc, NULL);
626  snprintf(name, sizeof(name), "sel_cross_%d", 4 * i + j);
627  selaAddSel(sela, sel, name, 0);
628 
629  if (debugflag) {
630  pixt = pixScaleBySampling(pixc, 10.0, 10.0);
631  pixaAddPix(pixa, pixt, L_INSERT);
632  }
633  pixDestroy(&pixm);
634  pixDestroy(&pixc);
635  }
636  }
637 
638  if (debugflag) {
639  l_int32 w;
640  lept_mkdir("lept/sel");
641  pixaGetPixDimensions(pixa, 0, &w, NULL, NULL);
642  pixt = pixaDisplayTiledAndScaled(pixa, 32, w, 4, 0, 10, 2);
643  pixWriteDebug("/tmp/lept/sel/tsel1.png", pixt, IFF_PNG);
644  pixDisplay(pixt, 0, 100);
645  pixDestroy(&pixt);
646  pixt = selaDisplayInPix(sela, 15, 2, 20, 4);
647  pixWriteDebug("/tmp/lept/sel/tsel2.png", pixt, IFF_PNG);
648  pixDisplay(pixt, 500, 100);
649  pixDestroy(&pixt);
650  selaWriteStream(stderr, sela);
651  }
652  pixaDestroy(&pixa);
653 
654  return sela;
655 }
656 
657 
658 /* -------------------------------------------------------------------------- *
659  * Structuring elements for connectivity-preserving thinning operations *
660  * -------------------------------------------------------------------------- */
661 
662  /* ------------------------------------------------------------
663  * These sels (and their rotated counterparts) are the useful
664  * 3x3 Sels for thinning. The notation is based on
665  * "Connectivity-preserving morphological image transformations,"
666  * a version of which can be found at
667  * http://www.leptonica.com/papers/conn.pdf
668  * ------------------------------------------------------------ */
669 
670  /* Sels for 4-connected thinning */
671 static const char *sel_4_1 = " x"
672  "oCx"
673  " x";
674 static const char *sel_4_2 = " x"
675  "oCx"
676  " o ";
677 static const char *sel_4_3 = " o "
678  "oCx"
679  " x";
680 static const char *sel_4_4 = " o "
681  "oCx"
682  " o ";
683 static const char *sel_4_5 = " ox"
684  "oCx"
685  " o ";
686 static const char *sel_4_6 = " o "
687  "oCx"
688  " ox";
689 static const char *sel_4_7 = " xx"
690  "oCx"
691  " o ";
692 static const char *sel_4_8 = " x"
693  "oCx"
694  "o x";
695 static const char *sel_4_9 = "o x"
696  "oCx"
697  " x";
698 
699  /* Sels for 8-connected thinning */
700 static const char *sel_8_1 = " x "
701  "oCx"
702  " x ";
703 static const char *sel_8_2 = " x "
704  "oCx"
705  "o ";
706 static const char *sel_8_3 = "o "
707  "oCx"
708  " x ";
709 static const char *sel_8_4 = "o "
710  "oCx"
711  "o ";
712 static const char *sel_8_5 = "o x"
713  "oCx"
714  "o ";
715 static const char *sel_8_6 = "o "
716  "oCx"
717  "o x";
718 static const char *sel_8_7 = " x "
719  "oCx"
720  "oo ";
721 static const char *sel_8_8 = " x "
722  "oCx"
723  "ox ";
724 static const char *sel_8_9 = "ox "
725  "oCx"
726  " x ";
727 
728  /* Sels for both 4 and 8-connected thinning */
729 static const char *sel_48_1 = " xx"
730  "oCx"
731  "oo ";
732 static const char *sel_48_2 = "o x"
733  "oCx"
734  "o x";
735 
736 
748 SELA *
750 {
751 SEL *sel;
752 
753  if (!sela) sela = selaCreate(9);
754 
755  sel = selCreateFromString(sel_4_1, 3, 3, "sel_4_1");
756  selaAddSel(sela, sel, NULL, 0);
757  sel = selCreateFromString(sel_4_2, 3, 3, "sel_4_2");
758  selaAddSel(sela, sel, NULL, 0);
759  sel = selCreateFromString(sel_4_3, 3, 3, "sel_4_3");
760  selaAddSel(sela, sel, NULL, 0);
761  sel = selCreateFromString(sel_4_4, 3, 3, "sel_4_4");
762  selaAddSel(sela, sel, NULL, 0);
763  sel = selCreateFromString(sel_4_5, 3, 3, "sel_4_5");
764  selaAddSel(sela, sel, NULL, 0);
765  sel = selCreateFromString(sel_4_6, 3, 3, "sel_4_6");
766  selaAddSel(sela, sel, NULL, 0);
767  sel = selCreateFromString(sel_4_7, 3, 3, "sel_4_7");
768  selaAddSel(sela, sel, NULL, 0);
769  sel = selCreateFromString(sel_4_8, 3, 3, "sel_4_8");
770  selaAddSel(sela, sel, NULL, 0);
771  sel = selCreateFromString(sel_4_9, 3, 3, "sel_4_9");
772  selaAddSel(sela, sel, NULL, 0);
773 
774  return sela;
775 }
776 
777 
789 SELA *
791 {
792 SEL *sel;
793 
794  if (!sela) sela = selaCreate(9);
795 
796  sel = selCreateFromString(sel_8_1, 3, 3, "sel_8_1");
797  selaAddSel(sela, sel, NULL, 0);
798  sel = selCreateFromString(sel_8_2, 3, 3, "sel_8_2");
799  selaAddSel(sela, sel, NULL, 0);
800  sel = selCreateFromString(sel_8_3, 3, 3, "sel_8_3");
801  selaAddSel(sela, sel, NULL, 0);
802  sel = selCreateFromString(sel_8_4, 3, 3, "sel_8_4");
803  selaAddSel(sela, sel, NULL, 0);
804  sel = selCreateFromString(sel_8_5, 3, 3, "sel_8_5");
805  selaAddSel(sela, sel, NULL, 0);
806  sel = selCreateFromString(sel_8_6, 3, 3, "sel_8_6");
807  selaAddSel(sela, sel, NULL, 0);
808  sel = selCreateFromString(sel_8_7, 3, 3, "sel_8_7");
809  selaAddSel(sela, sel, NULL, 0);
810  sel = selCreateFromString(sel_8_8, 3, 3, "sel_8_8");
811  selaAddSel(sela, sel, NULL, 0);
812  sel = selCreateFromString(sel_8_9, 3, 3, "sel_8_9");
813  selaAddSel(sela, sel, NULL, 0);
814 
815  return sela;
816 }
817 
818 
830 SELA *
832 {
833 SEL *sel;
834 
835  if (!sela) sela = selaCreate(2);
836 
837  sel = selCreateFromString(sel_48_1, 3, 3, "sel_48_1");
838  selaAddSel(sela, sel, NULL, 0);
839  sel = selCreateFromString(sel_48_2, 3, 3, "sel_48_2");
840  selaAddSel(sela, sel, NULL, 0);
841 
842  return sela;
843 }
844 
l_ok selSetOrigin(SEL *sel, l_int32 cy, l_int32 cx)
selSetOrigin()
Definition: sel1.c:880
l_ok selectComposableSizes(l_int32 size, l_int32 *pfactor1, l_int32 *pfactor2)
selectComposableSizes()
Definition: morph.c:1092
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:1944
Definition: pix.h:717
SEL * selCreateFromColorPix(PIX *pixs, const char *selname)
Definition: sel1.c:2109
PTA * generatePtaLineFromPt(l_int32 x, l_int32 y, l_float64 length, l_float64 radang)
generatePtaLineFromPt()
Definition: graphics.c:897
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:163
l_ok pixRenderPta(PIX *pix, PTA *pta, l_int32 op)
pixRenderPta()
Definition: graphics.c:1254
SELA * sela4ccThin(SELA *sela)
sela4ccThin()
Definition: sel2.c:749
SELA * selaAddCrossJunctions(SELA *sela, l_float32 hlsize, l_float32 mdist, l_int32 norient, l_int32 debugflag)
selaAddCrossJunctions()
Definition: sel2.c:423
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:302
l_ok pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:741
l_ok selaWriteStream(FILE *fp, SELA *sela)
selaWriteStream()
Definition: sel1.c:1493
PIX * pixScaleBySampling(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleBySampling()
Definition: scale1.c:1338
l_ok ptaJoin(PTA *ptad, PTA *ptas, l_int32 istart, l_int32 iend)
ptaJoin()
Definition: ptafunc1.c:164
l_ok pixPaintThroughMask(PIX *pixd, PIX *pixm, l_int32 x, l_int32 y, l_uint32 val)
pixPaintThroughMask()
Definition: pix3.c:618
SELA * sela8ccThin(SELA *sela)
sela8ccThin()
Definition: sel2.c:790
SELA * selaAddTJunctions(SELA *sela, l_float32 hlsize, l_float32 mdist, l_int32 norient, l_int32 debugflag)
selaAddTJunctions()
Definition: sel2.c:548
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:503
SELA * selaAddDwaCombs(SELA *sela)
selaAddDwaCombs()
Definition: sel2.c:361
l_ok pixSetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 val)
pixSetPixel()
Definition: pix2.c:253
SELA * selaAddHitMiss(SELA *sela)
selaAddHitMiss()
Definition: sel2.c:181
SEL * selCreate(l_int32 height, l_int32 width, const char *name)
selCreate()
Definition: sel1.c:306
SEL * selCreateBrick(l_int32 h, l_int32 w, l_int32 cy, l_int32 cx, l_int32 type)
selCreateBrick()
Definition: sel1.c:418
PIX * pixaDisplayTiledAndScaled(PIXA *pixa, l_int32 outdepth, l_int32 tilewidth, l_int32 ncols, l_int32 background, l_int32 spacing, l_int32 border)
pixaDisplayTiledAndScaled()
Definition: pixafunc2.c:1137
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
Definition: pix.h:454
SELA * selaCreate(l_int32 n)
selaCreate()
Definition: sel1.c:239
l_ok selaAddSel(SELA *sela, SEL *sel, const char *selname, l_int32 copyflag)
selaAddSel()
Definition: sel1.c:566
SELA * selaAddBasic(SELA *sela)
selaAddBasic()
Definition: sel2.c:92
SELA * sela4and8ccThin(SELA *sela)
sela4and8ccThin()
Definition: sel2.c:831
SELA * selaAddDwaLinear(SELA *sela)
selaAddDwaLinear()
Definition: sel2.c:319
Definition: pix.h:134
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:192
l_ok pixaGetPixDimensions(PIXA *pixa, l_int32 index, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixaGetPixDimensions()
Definition: pixabasic.c:707
Definition: morph.h:74
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:408
PIX * selaDisplayInPix(SELA *sela, l_int32 size, l_int32 gthick, l_int32 spacing, l_int32 ncols)
selaDisplayInPix()
Definition: sel1.c:2318
Definition: pix.h:517
l_ok selSetElement(SEL *sel, l_int32 row, l_int32 col, l_int32 type)
selSetElement()
Definition: sel1.c:821
static const l_int32 L_BUF_SIZE
Definition: classapp.c:55
SEL * selCreateFromString(const char *text, l_int32 h, l_int32 w, const char *name)
selCreateFromString()
Definition: sel1.c:1616