Leptonica 1.82.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
64#ifdef HAVE_CONFIG_H
65#include <config_auto.h>
66#endif /* HAVE_CONFIG_H */
67
68#include <math.h>
69#include "allheaders.h"
70
71#define L_BUF_SIZE 512
72
73 /* Linear brick sel sizes, including all those that are required
74 * for decomposable sels up to size 63. */
75static const l_int32 num_linear = 25;
76static const l_int32 basic_linear[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
77 12, 13, 14, 15, 20, 21, 25, 30, 31, 35, 40, 41, 45, 50, 51};
78
79
80/* ------------------------------------------------------------------- *
81 * Basic brick structuring elements *
82 * ------------------------------------------------------------------- */
98SELA *
100{
101char name[L_BUF_SIZE];
102l_int32 i, size;
103SEL *sel;
104
105 PROCNAME("selaAddBasic");
106
107 if (!sela) {
108 if ((sela = selaCreate(0)) == NULL)
109 return (SELA *)ERROR_PTR("sela not made", procName, NULL);
110 }
111
112 /*--------------------------------------------------------------*
113 * Linear horizontal and vertical sels *
114 *--------------------------------------------------------------*/
115 for (i = 0; i < num_linear; i++) {
116 size = basic_linear[i];
117 sel = selCreateBrick(1, size, 0, size / 2, 1);
118 snprintf(name, L_BUF_SIZE, "sel_%dh", size);
119 selaAddSel(sela, sel, name, 0);
120 }
121 for (i = 0; i < num_linear; i++) {
122 size = basic_linear[i];
123 sel = selCreateBrick(size, 1, size / 2, 0, 1);
124 snprintf(name, L_BUF_SIZE, "sel_%dv", size);
125 selaAddSel(sela, sel, name, 0);
126 }
127
128 /*-----------------------------------------------------------*
129 * 2-d Bricks *
130 *-----------------------------------------------------------*/
131 for (i = 2; i <= 5; i++) {
132 sel = selCreateBrick(i, i, i / 2, i / 2, 1);
133 snprintf(name, L_BUF_SIZE, "sel_%d", i);
134 selaAddSel(sela, sel, name, 0);
135 }
136
137 /*-----------------------------------------------------------*
138 * Diagonals *
139 *-----------------------------------------------------------*/
140 /* 0c 1
141 1 0 */
142 sel = selCreateBrick(2, 2, 0, 0, 1);
143 selSetElement(sel, 0, 0, 0);
144 selSetElement(sel, 1, 1, 0);
145 selaAddSel(sela, sel, "sel_2dp", 0);
146
147 /* 1c 0
148 0 1 */
149 sel = selCreateBrick(2, 2, 0, 0, 1);
150 selSetElement(sel, 0, 1, 0);
151 selSetElement(sel, 1, 0, 0);
152 selaAddSel(sela, sel, "sel_2dm", 0);
153
154 /* Diagonal, slope +, size 5 */
155 sel = selCreate(5, 5, "sel_5dp");
156 selSetOrigin(sel, 2, 2);
157 selSetElement(sel, 0, 4, 1);
158 selSetElement(sel, 1, 3, 1);
159 selSetElement(sel, 2, 2, 1);
160 selSetElement(sel, 3, 1, 1);
161 selSetElement(sel, 4, 0, 1);
162 selaAddSel(sela, sel, "sel_5dp", 0);
163
164 /* Diagonal, slope -, size 5 */
165 sel = selCreate(5, 5, "sel_5dm");
166 selSetOrigin(sel, 2, 2);
167 selSetElement(sel, 0, 0, 1);
168 selSetElement(sel, 1, 1, 1);
169 selSetElement(sel, 2, 2, 1);
170 selSetElement(sel, 3, 3, 1);
171 selSetElement(sel, 4, 4, 1);
172 selaAddSel(sela, sel, "sel_5dm", 0);
173
174 return sela;
175}
176
177
178/* ------------------------------------------------------------------- *
179 * Simple hit-miss structuring elements *
180 * ------------------------------------------------------------------- */
187SELA *
189{
190SEL *sel;
191
192 PROCNAME("selaAddHitMiss");
193
194 if (!sela) {
195 if ((sela = selaCreate(0)) == NULL)
196 return (SELA *)ERROR_PTR("sela not made", procName, NULL);
197 }
198
199#if 0 /* use just for testing */
200 sel = selCreateBrick(3, 3, 1, 1, 2);
201 selaAddSel(sela, sel, "sel_bad", 0);
202#endif
203
204
205 /*--------------------------------------------------------------*
206 * Isolated foreground pixel *
207 *--------------------------------------------------------------*/
208 sel = selCreateBrick(3, 3, 1, 1, SEL_MISS);
209 selSetElement(sel, 1, 1, SEL_HIT);
210 selaAddSel(sela, sel, "sel_3hm", 0);
211
212 /*--------------------------------------------------------------*
213 * Horizontal and vertical edges *
214 *--------------------------------------------------------------*/
215 sel = selCreateBrick(2, 3, 0, 1, SEL_HIT);
216 selSetElement(sel, 1, 0, SEL_MISS);
217 selSetElement(sel, 1, 1, SEL_MISS);
218 selSetElement(sel, 1, 2, SEL_MISS);
219 selaAddSel(sela, sel, "sel_3de", 0);
220
221 sel = selCreateBrick(2, 3, 1, 1, SEL_HIT);
222 selSetElement(sel, 0, 0, SEL_MISS);
223 selSetElement(sel, 0, 1, SEL_MISS);
224 selSetElement(sel, 0, 2, SEL_MISS);
225 selaAddSel(sela, sel, "sel_3ue", 0);
226
227 sel = selCreateBrick(3, 2, 1, 0, SEL_HIT);
228 selSetElement(sel, 0, 1, SEL_MISS);
229 selSetElement(sel, 1, 1, SEL_MISS);
230 selSetElement(sel, 2, 1, SEL_MISS);
231 selaAddSel(sela, sel, "sel_3re", 0);
232
233 sel = selCreateBrick(3, 2, 1, 1, SEL_HIT);
234 selSetElement(sel, 0, 0, SEL_MISS);
235 selSetElement(sel, 1, 0, SEL_MISS);
236 selSetElement(sel, 2, 0, SEL_MISS);
237 selaAddSel(sela, sel, "sel_3le", 0);
238
239 /*--------------------------------------------------------------*
240 * Slanted edge *
241 *--------------------------------------------------------------*/
242 sel = selCreateBrick(13, 6, 6, 2, SEL_DONT_CARE);
243 selSetElement(sel, 0, 3, SEL_MISS);
244 selSetElement(sel, 0, 5, SEL_HIT);
245 selSetElement(sel, 4, 2, SEL_MISS);
246 selSetElement(sel, 4, 4, SEL_HIT);
247 selSetElement(sel, 8, 1, SEL_MISS);
248 selSetElement(sel, 8, 3, SEL_HIT);
249 selSetElement(sel, 12, 0, SEL_MISS);
250 selSetElement(sel, 12, 2, SEL_HIT);
251 selaAddSel(sela, sel, "sel_sl1", 0);
252
253 /*--------------------------------------------------------------*
254 * Corners *
255 * This allows for up to 3 missing edge pixels at the corner *
256 *--------------------------------------------------------------*/
257 sel = selCreateBrick(4, 4, 1, 1, SEL_MISS);
258 selSetElement(sel, 1, 1, SEL_DONT_CARE);
259 selSetElement(sel, 1, 2, SEL_DONT_CARE);
260 selSetElement(sel, 2, 1, SEL_DONT_CARE);
261 selSetElement(sel, 1, 3, SEL_HIT);
262 selSetElement(sel, 2, 2, SEL_HIT);
263 selSetElement(sel, 2, 3, SEL_HIT);
264 selSetElement(sel, 3, 1, SEL_HIT);
265 selSetElement(sel, 3, 2, SEL_HIT);
266 selSetElement(sel, 3, 3, SEL_HIT);
267 selaAddSel(sela, sel, "sel_ulc", 0);
268
269 sel = selCreateBrick(4, 4, 1, 2, SEL_MISS);
270 selSetElement(sel, 1, 1, SEL_DONT_CARE);
271 selSetElement(sel, 1, 2, SEL_DONT_CARE);
272 selSetElement(sel, 2, 2, SEL_DONT_CARE);
273 selSetElement(sel, 1, 0, SEL_HIT);
274 selSetElement(sel, 2, 0, SEL_HIT);
275 selSetElement(sel, 2, 1, SEL_HIT);
276 selSetElement(sel, 3, 0, SEL_HIT);
277 selSetElement(sel, 3, 1, SEL_HIT);
278 selSetElement(sel, 3, 2, SEL_HIT);
279 selaAddSel(sela, sel, "sel_urc", 0);
280
281 sel = selCreateBrick(4, 4, 2, 1, SEL_MISS);
282 selSetElement(sel, 1, 1, SEL_DONT_CARE);
283 selSetElement(sel, 2, 1, SEL_DONT_CARE);
284 selSetElement(sel, 2, 2, SEL_DONT_CARE);
285 selSetElement(sel, 0, 1, SEL_HIT);
286 selSetElement(sel, 0, 2, SEL_HIT);
287 selSetElement(sel, 0, 3, SEL_HIT);
288 selSetElement(sel, 1, 2, SEL_HIT);
289 selSetElement(sel, 1, 3, SEL_HIT);
290 selSetElement(sel, 2, 3, SEL_HIT);
291 selaAddSel(sela, sel, "sel_llc", 0);
292
293 sel = selCreateBrick(4, 4, 2, 2, SEL_MISS);
294 selSetElement(sel, 1, 2, SEL_DONT_CARE);
295 selSetElement(sel, 2, 1, SEL_DONT_CARE);
296 selSetElement(sel, 2, 2, SEL_DONT_CARE);
297 selSetElement(sel, 0, 0, SEL_HIT);
298 selSetElement(sel, 0, 1, SEL_HIT);
299 selSetElement(sel, 0, 2, SEL_HIT);
300 selSetElement(sel, 1, 0, SEL_HIT);
301 selSetElement(sel, 1, 1, SEL_HIT);
302 selSetElement(sel, 2, 0, SEL_HIT);
303 selaAddSel(sela, sel, "sel_lrc", 0);
304
305 return sela;
306}
307
308
309/* ------------------------------------------------------------------- *
310 * Structuring elements for comparing with DWA operations *
311 * ------------------------------------------------------------------- */
325SELA *
327{
328char name[L_BUF_SIZE];
329l_int32 i;
330SEL *sel;
331
332 PROCNAME("selaAddDwaLinear");
333
334 if (!sela) {
335 if ((sela = selaCreate(0)) == NULL)
336 return (SELA *)ERROR_PTR("sela not made", procName, NULL);
337 }
338
339 for (i = 2; i < 64; i++) {
340 sel = selCreateBrick(1, i, 0, i / 2, 1);
341 snprintf(name, L_BUF_SIZE, "sel_%dh", i);
342 selaAddSel(sela, sel, name, 0);
343 }
344 for (i = 2; i < 64; i++) {
345 sel = selCreateBrick(i, 1, i / 2, 0, 1);
346 snprintf(name, L_BUF_SIZE, "sel_%dv", i);
347 selaAddSel(sela, sel, name, 0);
348 }
349 return sela;
350}
351
352
367SELA *
369{
370char name[L_BUF_SIZE];
371l_int32 i, f1, f2, prevsize, size;
372SEL *selh, *selv;
373
374 PROCNAME("selaAddDwaCombs");
375
376 if (!sela) {
377 if ((sela = selaCreate(0)) == NULL)
378 return (SELA *)ERROR_PTR("sela not made", procName, NULL);
379 }
380
381 prevsize = 0;
382 for (i = 4; i < 64; i++) {
383 selectComposableSizes(i, &f1, &f2);
384 size = f1 * f2;
385 if (size == prevsize)
386 continue;
387 selectComposableSels(i, L_HORIZ, NULL, &selh);
388 if (selh) {
389 snprintf(name, L_BUF_SIZE, "sel_comb_%dh", size);
390 selaAddSel(sela, selh, name, 0);
391 } else {
392 L_ERROR("selh not made for i = %d\n", procName, i);
393 }
394 selectComposableSels(i, L_VERT, NULL, &selv);
395 if (selv) {
396 snprintf(name, L_BUF_SIZE, "sel_comb_%dv", size);
397 selaAddSel(sela, selv, name, 0);
398 } else {
399 L_ERROR("selv not made for i = %d\n", procName, i);
400 }
401 prevsize = size;
402 }
403
404 return sela;
405}
406
407
408/* ------------------------------------------------------------------- *
409 * Structuring elements for the intersection of lines *
410 * ------------------------------------------------------------------- */
437SELA *
439 l_float32 hlsize,
440 l_float32 mdist,
441 l_int32 norient,
442 l_int32 debugflag)
443{
444char name[L_BUF_SIZE];
445l_int32 i, j, w, xc, yc;
446l_float64 pi, halfpi, radincr, radang;
447l_float64 angle;
448PIX *pixc, *pixm, *pixt;
449PIXA *pixa;
450PTA *pta1, *pta2, *pta3, *pta4;
451SEL *sel;
452
453 PROCNAME("selaAddCrossJunctions");
454
455 if (hlsize <= 0)
456 return (SELA *)ERROR_PTR("hlsize not > 0", procName, NULL);
457 if (norient < 1 || norient > 8)
458 return (SELA *)ERROR_PTR("norient not in [1, ... 8]", procName, NULL);
459
460 if (!sela) {
461 if ((sela = selaCreate(0)) == NULL)
462 return (SELA *)ERROR_PTR("sela not made", procName, NULL);
463 }
464
465 pi = 3.1415926535;
466 halfpi = 3.1415926535 / 2.0;
467 radincr = halfpi / (l_float64)norient;
468 w = (l_int32)(2.2 * (L_MAX(hlsize, mdist) + 0.5));
469 if (w % 2 == 0)
470 w++;
471 xc = w / 2;
472 yc = w / 2;
473
474 pixa = pixaCreate(norient);
475 for (i = 0; i < norient; i++) {
476
477 /* Set the don't cares */
478 pixc = pixCreate(w, w, 32);
479 pixSetAll(pixc);
480
481 /* Add the green lines of hits */
482 pixm = pixCreate(w, w, 1);
483 radang = (l_float32)i * radincr;
484 pta1 = generatePtaLineFromPt(xc, yc, hlsize + 1, radang);
485 pta2 = generatePtaLineFromPt(xc, yc, hlsize + 1, radang + halfpi);
486 pta3 = generatePtaLineFromPt(xc, yc, hlsize + 1, radang + pi);
487 pta4 = generatePtaLineFromPt(xc, yc, hlsize + 1, radang + pi + halfpi);
488 ptaJoin(pta1, pta2, 0, -1);
489 ptaJoin(pta1, pta3, 0, -1);
490 ptaJoin(pta1, pta4, 0, -1);
491 pixRenderPta(pixm, pta1, L_SET_PIXELS);
492 pixPaintThroughMask(pixc, pixm, 0, 0, 0x00ff0000);
493 ptaDestroy(&pta1);
494 ptaDestroy(&pta2);
495 ptaDestroy(&pta3);
496 ptaDestroy(&pta4);
497
498 /* Add red misses between the lines */
499 for (j = 0; j < 4; j++) {
500 angle = radang + (j - 0.5) * halfpi;
501 pixSetPixel(pixc, xc + (l_int32)(mdist * cos(angle)),
502 yc + (l_int32)(mdist * sin(angle)), 0xff000000);
503 }
504
505 /* Add dark green for origin */
506 pixSetPixel(pixc, xc, yc, 0x00550000);
507
508 /* Generate the sel */
509 sel = selCreateFromColorPix(pixc, NULL);
510 snprintf(name, sizeof(name), "sel_cross_%d", i);
511 selaAddSel(sela, sel, name, 0);
512
513 if (debugflag) {
514 pixt = pixScaleBySampling(pixc, 10.0, 10.0);
515 pixaAddPix(pixa, pixt, L_INSERT);
516 }
517 pixDestroy(&pixm);
518 pixDestroy(&pixc);
519 }
520
521 if (debugflag) {
522 l_int32 w;
523 lept_mkdir("lept/sel");
524 pixaGetPixDimensions(pixa, 0, &w, NULL, NULL);
525 pixt = pixaDisplayTiledAndScaled(pixa, 32, w, 1, 0, 10, 2);
526 pixWriteDebug("/tmp/lept/sel/xsel1.png", pixt, IFF_PNG);
527 pixDisplay(pixt, 0, 100);
528 pixDestroy(&pixt);
529 pixt = selaDisplayInPix(sela, 15, 2, 20, 1);
530 pixWriteDebug("/tmp/lept/sel/xsel2.png", pixt, IFF_PNG);
531 pixDisplay(pixt, 500, 100);
532 pixDestroy(&pixt);
533 selaWriteStream(stderr, sela);
534 }
535 pixaDestroy(&pixa);
536
537 return sela;
538}
539
540
562SELA *
564 l_float32 hlsize,
565 l_float32 mdist,
566 l_int32 norient,
567 l_int32 debugflag)
568{
569char name[L_BUF_SIZE];
570l_int32 i, j, k, w, xc, yc;
571l_float64 pi, halfpi, radincr, jang, radang;
572l_float64 angle[3], dist[3];
573PIX *pixc, *pixm, *pixt;
574PIXA *pixa;
575PTA *pta1, *pta2, *pta3;
576SEL *sel;
577
578 PROCNAME("selaAddTJunctions");
579
580 if (hlsize <= 2)
581 return (SELA *)ERROR_PTR("hlsizel not > 1", procName, NULL);
582 if (norient < 1 || norient > 8)
583 return (SELA *)ERROR_PTR("norient not in [1, ... 8]", procName, NULL);
584
585 if (!sela) {
586 if ((sela = selaCreate(0)) == NULL)
587 return (SELA *)ERROR_PTR("sela not made", procName, NULL);
588 }
589
590 pi = 3.1415926535;
591 halfpi = 3.1415926535 / 2.0;
592 radincr = halfpi / (l_float32)norient;
593 w = (l_int32)(2.4 * (L_MAX(hlsize, mdist) + 0.5));
594 if (w % 2 == 0)
595 w++;
596 xc = w / 2;
597 yc = w / 2;
598
599 pixa = pixaCreate(4 * norient);
600 for (i = 0; i < norient; i++) {
601 for (j = 0; j < 4; j++) { /* 4 orthogonal orientations */
602 jang = (l_float32)j * halfpi;
603
604 /* Set the don't cares */
605 pixc = pixCreate(w, w, 32);
606 pixSetAll(pixc);
607
608 /* Add the green lines of hits */
609 pixm = pixCreate(w, w, 1);
610 radang = (l_float32)i * radincr;
611 pta1 = generatePtaLineFromPt(xc, yc, hlsize + 1, jang + radang);
612 pta2 = generatePtaLineFromPt(xc, yc, hlsize + 1,
613 jang + radang + halfpi);
614 pta3 = generatePtaLineFromPt(xc, yc, hlsize + 1,
615 jang + radang + pi);
616 ptaJoin(pta1, pta2, 0, -1);
617 ptaJoin(pta1, pta3, 0, -1);
618 pixRenderPta(pixm, pta1, L_SET_PIXELS);
619 pixPaintThroughMask(pixc, pixm, 0, 0, 0x00ff0000);
620 ptaDestroy(&pta1);
621 ptaDestroy(&pta2);
622 ptaDestroy(&pta3);
623
624 /* Add red misses between the lines */
625 angle[0] = radang + jang - halfpi;
626 angle[1] = radang + jang + 0.5 * halfpi;
627 angle[2] = radang + jang + 1.5 * halfpi;
628 dist[0] = 0.8 * mdist;
629 dist[1] = dist[2] = mdist;
630 for (k = 0; k < 3; k++) {
631 pixSetPixel(pixc, xc + (l_int32)(dist[k] * cos(angle[k])),
632 yc + (l_int32)(dist[k] * sin(angle[k])),
633 0xff000000);
634 }
635
636 /* Add dark green for origin */
637 pixSetPixel(pixc, xc, yc, 0x00550000);
638
639 /* Generate the sel */
640 sel = selCreateFromColorPix(pixc, NULL);
641 snprintf(name, sizeof(name), "sel_cross_%d", 4 * i + j);
642 selaAddSel(sela, sel, name, 0);
643
644 if (debugflag) {
645 pixt = pixScaleBySampling(pixc, 10.0, 10.0);
646 pixaAddPix(pixa, pixt, L_INSERT);
647 }
648 pixDestroy(&pixm);
649 pixDestroy(&pixc);
650 }
651 }
652
653 if (debugflag) {
654 l_int32 w;
655 lept_mkdir("lept/sel");
656 pixaGetPixDimensions(pixa, 0, &w, NULL, NULL);
657 pixt = pixaDisplayTiledAndScaled(pixa, 32, w, 4, 0, 10, 2);
658 pixWriteDebug("/tmp/lept/sel/tsel1.png", pixt, IFF_PNG);
659 pixDisplay(pixt, 0, 100);
660 pixDestroy(&pixt);
661 pixt = selaDisplayInPix(sela, 15, 2, 20, 4);
662 pixWriteDebug("/tmp/lept/sel/tsel2.png", pixt, IFF_PNG);
663 pixDisplay(pixt, 500, 100);
664 pixDestroy(&pixt);
665 selaWriteStream(stderr, sela);
666 }
667 pixaDestroy(&pixa);
668
669 return sela;
670}
671
672
673/* -------------------------------------------------------------------------- *
674 * Structuring elements for connectivity-preserving thinning operations *
675 * -------------------------------------------------------------------------- */
676
677 /* ------------------------------------------------------------
678 * These sels (and their rotated counterparts) are the useful
679 * 3x3 Sels for thinning. The notation is based on
680 * "Connectivity-preserving morphological image transformations,"
681 * a version of which can be found at
682 * http://www.leptonica.com/papers/conn.pdf
683 * ------------------------------------------------------------ */
684
685 /* Sels for 4-connected thinning */
686static const char *sel_4_1 = " x"
687 "oCx"
688 " x";
689static const char *sel_4_2 = " x"
690 "oCx"
691 " o ";
692static const char *sel_4_3 = " o "
693 "oCx"
694 " x";
695static const char *sel_4_4 = " o "
696 "oCx"
697 " o ";
698static const char *sel_4_5 = " ox"
699 "oCx"
700 " o ";
701static const char *sel_4_6 = " o "
702 "oCx"
703 " ox";
704static const char *sel_4_7 = " xx"
705 "oCx"
706 " o ";
707static const char *sel_4_8 = " x"
708 "oCx"
709 "o x";
710static const char *sel_4_9 = "o x"
711 "oCx"
712 " x";
713
714 /* Sels for 8-connected thinning */
715static const char *sel_8_1 = " x "
716 "oCx"
717 " x ";
718static const char *sel_8_2 = " x "
719 "oCx"
720 "o ";
721static const char *sel_8_3 = "o "
722 "oCx"
723 " x ";
724static const char *sel_8_4 = "o "
725 "oCx"
726 "o ";
727static const char *sel_8_5 = "o x"
728 "oCx"
729 "o ";
730static const char *sel_8_6 = "o "
731 "oCx"
732 "o x";
733static const char *sel_8_7 = " x "
734 "oCx"
735 "oo ";
736static const char *sel_8_8 = " x "
737 "oCx"
738 "ox ";
739static const char *sel_8_9 = "ox "
740 "oCx"
741 " x ";
742
743 /* Sels for both 4 and 8-connected thinning */
744static const char *sel_48_1 = " xx"
745 "oCx"
746 "oo ";
747static const char *sel_48_2 = "o x"
748 "oCx"
749 "o x";
750
751
763SELA *
765{
766SEL *sel;
767
768 if (!sela) sela = selaCreate(9);
769
770 sel = selCreateFromString(sel_4_1, 3, 3, "sel_4_1");
771 selaAddSel(sela, sel, NULL, 0);
772 sel = selCreateFromString(sel_4_2, 3, 3, "sel_4_2");
773 selaAddSel(sela, sel, NULL, 0);
774 sel = selCreateFromString(sel_4_3, 3, 3, "sel_4_3");
775 selaAddSel(sela, sel, NULL, 0);
776 sel = selCreateFromString(sel_4_4, 3, 3, "sel_4_4");
777 selaAddSel(sela, sel, NULL, 0);
778 sel = selCreateFromString(sel_4_5, 3, 3, "sel_4_5");
779 selaAddSel(sela, sel, NULL, 0);
780 sel = selCreateFromString(sel_4_6, 3, 3, "sel_4_6");
781 selaAddSel(sela, sel, NULL, 0);
782 sel = selCreateFromString(sel_4_7, 3, 3, "sel_4_7");
783 selaAddSel(sela, sel, NULL, 0);
784 sel = selCreateFromString(sel_4_8, 3, 3, "sel_4_8");
785 selaAddSel(sela, sel, NULL, 0);
786 sel = selCreateFromString(sel_4_9, 3, 3, "sel_4_9");
787 selaAddSel(sela, sel, NULL, 0);
788
789 return sela;
790}
791
792
804SELA *
806{
807SEL *sel;
808
809 if (!sela) sela = selaCreate(9);
810
811 sel = selCreateFromString(sel_8_1, 3, 3, "sel_8_1");
812 selaAddSel(sela, sel, NULL, 0);
813 sel = selCreateFromString(sel_8_2, 3, 3, "sel_8_2");
814 selaAddSel(sela, sel, NULL, 0);
815 sel = selCreateFromString(sel_8_3, 3, 3, "sel_8_3");
816 selaAddSel(sela, sel, NULL, 0);
817 sel = selCreateFromString(sel_8_4, 3, 3, "sel_8_4");
818 selaAddSel(sela, sel, NULL, 0);
819 sel = selCreateFromString(sel_8_5, 3, 3, "sel_8_5");
820 selaAddSel(sela, sel, NULL, 0);
821 sel = selCreateFromString(sel_8_6, 3, 3, "sel_8_6");
822 selaAddSel(sela, sel, NULL, 0);
823 sel = selCreateFromString(sel_8_7, 3, 3, "sel_8_7");
824 selaAddSel(sela, sel, NULL, 0);
825 sel = selCreateFromString(sel_8_8, 3, 3, "sel_8_8");
826 selaAddSel(sela, sel, NULL, 0);
827 sel = selCreateFromString(sel_8_9, 3, 3, "sel_8_9");
828 selaAddSel(sela, sel, NULL, 0);
829
830 return sela;
831}
832
833
845SELA *
847{
848SEL *sel;
849
850 if (!sela) sela = selaCreate(2);
851
852 sel = selCreateFromString(sel_48_1, 3, 3, "sel_48_1");
853 selaAddSel(sela, sel, NULL, 0);
854 sel = selCreateFromString(sel_48_2, 3, 3, "sel_48_2");
855 selaAddSel(sela, sel, NULL, 0);
856
857 return sela;
858}
859
860
861/* -------------------------------------------------------------------------- *
862 * Other structuring elements *
863 * -------------------------------------------------------------------------- */
877SEL *
878selMakePlusSign(l_int32 size,
879 l_int32 linewidth)
880{
881PIX *pix;
882SEL *sel;
883
884 PROCNAME("selMakePlusSign");
885
886 if (size < 3 || linewidth > size)
887 return (SEL *)ERROR_PTR("invalid input", procName, NULL);
888
889 pix = pixCreate(size, size, 1);
890 pixRenderLine(pix, size / 2, 0, size / 2, size - 1,
891 linewidth, L_SET_PIXELS);
892 pixRenderLine(pix, 0, size / 2, size, size / 2,
893 linewidth, L_SET_PIXELS);
894 sel = selCreateFromPix(pix, size / 2, size / 2, "plus_sign");
895 pixDestroy(&pix);
896 return sel;
897}
#define L_BUF_SIZE
Definition: classapp.c:59
PTA * generatePtaLineFromPt(l_int32 x, l_int32 y, l_float64 length, l_float64 radang)
generatePtaLineFromPt()
Definition: graphics.c:907
l_ok pixRenderLine(PIX *pix, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_int32 width, l_int32 op)
pixRenderLine()
Definition: graphics.c:1496
l_ok pixRenderPta(PIX *pix, PTA *pta, l_int32 op)
pixRenderPta()
Definition: graphics.c:1267
l_ok selectComposableSizes(l_int32 size, l_int32 *pfactor1, l_int32 *pfactor2)
selectComposableSizes()
Definition: morph.c:1132
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
l_ok pixSetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 val)
pixSetPixel()
Definition: pix2.c:263
l_ok pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:817
l_ok pixPaintThroughMask(PIX *pixd, PIX *pixm, l_int32 x, l_int32 y, l_uint32 val)
pixPaintThroughMask()
Definition: pix3.c:626
@ L_SET_PIXELS
Definition: pix.h:772
@ L_INSERT
Definition: pix.h:711
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:506
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:412
l_ok pixaGetPixDimensions(PIXA *pixa, l_int32 index, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixaGetPixDimensions()
Definition: pixabasic.c:726
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:167
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:1045
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:195
l_ok ptaJoin(PTA *ptad, PTA *ptas, l_int32 istart, l_int32 iend)
ptaJoin()
Definition: ptafunc1.c:167
PIX * pixScaleBySampling(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleBySampling()
Definition: scale1.c:1338
l_ok selaWriteStream(FILE *fp, SELA *sela)
selaWriteStream()
Definition: sel1.c:1484
SEL * selCreate(l_int32 height, l_int32 width, const char *name)
selCreate()
Definition: sel1.c:310
SEL * selCreateFromPix(PIX *pix, l_int32 cy, l_int32 cx, const char *name)
selCreateFromPix()
Definition: sel1.c:2008
l_ok selSetOrigin(SEL *sel, l_int32 cy, l_int32 cx)
selSetOrigin()
Definition: sel1.c:878
l_ok selaAddSel(SELA *sela, SEL *sel, const char *selname, l_int32 copyflag)
selaAddSel()
Definition: sel1.c:559
l_ok selSetElement(SEL *sel, l_int32 row, l_int32 col, l_int32 type)
selSetElement()
Definition: sel1.c:819
SELA * selaCreate(l_int32 n)
selaCreate()
Definition: sel1.c:251
SEL * selCreateFromString(const char *text, l_int32 h, l_int32 w, const char *name)
selCreateFromString()
Definition: sel1.c:1607
SEL * selCreateBrick(l_int32 h, l_int32 w, l_int32 cy, l_int32 cx, l_int32 type)
selCreateBrick()
Definition: sel1.c:418
SEL * selCreateFromColorPix(PIX *pixs, const char *selname)
Definition: sel1.c:2117
PIX * selaDisplayInPix(SELA *sela, l_int32 size, l_int32 gthick, l_int32 spacing, l_int32 ncols)
selaDisplayInPix()
Definition: sel1.c:2373
SEL * selMakePlusSign(l_int32 size, l_int32 linewidth)
selMakePlusSign()
Definition: sel2.c:878
SELA * selaAddBasic(SELA *sela)
selaAddBasic()
Definition: sel2.c:99
SELA * sela8ccThin(SELA *sela)
sela8ccThin()
Definition: sel2.c:805
SELA * selaAddDwaLinear(SELA *sela)
selaAddDwaLinear()
Definition: sel2.c:326
SELA * sela4and8ccThin(SELA *sela)
sela4and8ccThin()
Definition: sel2.c:846
SELA * selaAddCrossJunctions(SELA *sela, l_float32 hlsize, l_float32 mdist, l_int32 norient, l_int32 debugflag)
selaAddCrossJunctions()
Definition: sel2.c:438
SELA * selaAddHitMiss(SELA *sela)
selaAddHitMiss()
Definition: sel2.c:188
SELA * sela4ccThin(SELA *sela)
sela4ccThin()
Definition: sel2.c:764
SELA * selaAddDwaCombs(SELA *sela)
selaAddDwaCombs()
Definition: sel2.c:368
SELA * selaAddTJunctions(SELA *sela, l_float32 hlsize, l_float32 mdist, l_int32 norient, l_int32 debugflag)
selaAddTJunctions()
Definition: sel2.c:563
Definition: pix.h:139
Definition: pix.h:456
Definition: pix.h:517
Definition: morph.h:74
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:2218