Leptonica 1.82.0
Image processing and image analysis suite
morphapp.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
27
86#ifdef HAVE_CONFIG_H
87#include <config_auto.h>
88#endif /* HAVE_CONFIG_H */
89
90#include "allheaders.h"
91
92#define SWAP(x, y) {temp = (x); (x) = (y); (y) = temp;}
93
94/*-----------------------------------------------------------------*
95 * Extraction of boundary pixels *
96 *-----------------------------------------------------------------*/
110PIX *
112 l_int32 type)
113{
114PIX *pixd;
115
116 PROCNAME("pixExtractBoundary");
117
118 if (!pixs)
119 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
120
121 if (type == 0)
122 pixd = pixDilateBrick(NULL, pixs, 3, 3);
123 else
124 pixd = pixErodeBrick(NULL, pixs, 3, 3);
125 pixXor(pixd, pixd, pixs);
126 return pixd;
127}
128
129
130/*-----------------------------------------------------------------*
131 * Selective morph sequence operation under mask *
132 *-----------------------------------------------------------------*/
150PIX *
152 PIX *pixm,
153 const char *sequence,
154 l_int32 dispsep)
155{
156PIX *pixd;
157
158 PROCNAME("pixMorphSequenceMasked");
159
160 if (!pixs)
161 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
162 if (!sequence)
163 return (PIX *)ERROR_PTR("sequence not defined", procName, NULL);
164
165 pixd = pixMorphSequence(pixs, sequence, dispsep);
166 pixCombineMasked(pixd, pixs, pixm); /* restore src pixels under mask fg */
167 return pixd;
168}
169
170
171/*-----------------------------------------------------------------*
172 * Morph sequence operation on each component *
173 *-----------------------------------------------------------------*/
197PIX *
199 const char *sequence,
200 l_int32 connectivity,
201 l_int32 minw,
202 l_int32 minh,
203 BOXA **pboxa)
204{
205l_int32 n, i, x, y, w, h;
206BOXA *boxa;
207PIX *pix, *pixd;
208PIXA *pixas, *pixad;
209
210 PROCNAME("pixMorphSequenceByComponent");
211
212 if (!pixs)
213 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
214 if (!sequence)
215 return (PIX *)ERROR_PTR("sequence not defined", procName, NULL);
216
217 if (minw <= 0) minw = 1;
218 if (minh <= 0) minh = 1;
219
220 /* Get the c.c. */
221 if ((boxa = pixConnComp(pixs, &pixas, connectivity)) == NULL)
222 return (PIX *)ERROR_PTR("boxa not made", procName, NULL);
223
224 /* Operate on each c.c. independently */
225 pixad = pixaMorphSequenceByComponent(pixas, sequence, minw, minh);
226 pixaDestroy(&pixas);
227 boxaDestroy(&boxa);
228 if (!pixad)
229 return (PIX *)ERROR_PTR("pixad not made", procName, NULL);
230
231 /* Display the result out into pixd */
232 pixd = pixCreateTemplate(pixs);
233 n = pixaGetCount(pixad);
234 for (i = 0; i < n; i++) {
235 pixaGetBoxGeometry(pixad, i, &x, &y, &w, &h);
236 pix = pixaGetPix(pixad, i, L_CLONE);
237 pixRasterop(pixd, x, y, w, h, PIX_PAINT, pix, 0, 0);
238 pixDestroy(&pix);
239 }
240
241 if (pboxa)
242 *pboxa = pixaGetBoxa(pixad, L_CLONE);
243 pixaDestroy(&pixad);
244 return pixd;
245}
246
247
267PIXA *
269 const char *sequence,
270 l_int32 minw,
271 l_int32 minh)
272{
273l_int32 n, i, w, h, d;
274BOX *box;
275PIX *pix1, *pix2;
276PIXA *pixad;
277
278 PROCNAME("pixaMorphSequenceByComponent");
279
280 if (!pixas)
281 return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
282 if ((n = pixaGetCount(pixas)) == 0)
283 return (PIXA *)ERROR_PTR("no pix in pixas", procName, NULL);
284 if (n != pixaGetBoxaCount(pixas))
285 L_WARNING("boxa size != n\n", procName);
286 pixaGetPixDimensions(pixas, 0, NULL, NULL, &d);
287 if (d != 1)
288 return (PIXA *)ERROR_PTR("depth not 1 bpp", procName, NULL);
289
290 if (!sequence)
291 return (PIXA *)ERROR_PTR("sequence not defined", procName, NULL);
292 if (minw <= 0) minw = 1;
293 if (minh <= 0) minh = 1;
294
295 if ((pixad = pixaCreate(n)) == NULL)
296 return (PIXA *)ERROR_PTR("pixad not made", procName, NULL);
297 for (i = 0; i < n; i++) {
298 pixaGetPixDimensions(pixas, i, &w, &h, NULL);
299 if (w >= minw && h >= minh) {
300 if ((pix1 = pixaGetPix(pixas, i, L_CLONE)) == NULL) {
301 pixaDestroy(&pixad);
302 return (PIXA *)ERROR_PTR("pix1 not found", procName, NULL);
303 }
304 if ((pix2 = pixMorphCompSequence(pix1, sequence, 0)) == NULL) {
305 pixaDestroy(&pixad);
306 return (PIXA *)ERROR_PTR("pix2 not made", procName, NULL);
307 }
308 pixaAddPix(pixad, pix2, L_INSERT);
309 box = pixaGetBox(pixas, i, L_COPY);
310 pixaAddBox(pixad, box, L_INSERT);
311 pixDestroy(&pix1);
312 }
313 }
314
315 return pixad;
316}
317
318
319/*-----------------------------------------------------------------*
320 * Morph sequence operation on each region *
321 *-----------------------------------------------------------------*/
350PIX *
352 PIX *pixm,
353 const char *sequence,
354 l_int32 connectivity,
355 l_int32 minw,
356 l_int32 minh,
357 BOXA **pboxa)
358{
359l_int32 n, i, x, y, w, h;
360BOXA *boxa;
361PIX *pix, *pixd;
362PIXA *pixam, *pixad;
363
364 PROCNAME("pixMorphSequenceByRegion");
365
366 if (pboxa) *pboxa = NULL;
367 if (!pixs)
368 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
369 if (!pixm)
370 return (PIX *)ERROR_PTR("pixm not defined", procName, NULL);
371 if (pixGetDepth(pixs) != 1 || pixGetDepth(pixm) != 1)
372 return (PIX *)ERROR_PTR("pixs and pixm not both 1 bpp", procName, NULL);
373 if (!sequence)
374 return (PIX *)ERROR_PTR("sequence not defined", procName, NULL);
375
376 if (minw <= 0) minw = 1;
377 if (minh <= 0) minh = 1;
378
379 /* Get the c.c. of the mask */
380 if ((boxa = pixConnComp(pixm, &pixam, connectivity)) == NULL)
381 return (PIX *)ERROR_PTR("boxa not made", procName, NULL);
382
383 /* Operate on each region in pixs independently */
384 pixad = pixaMorphSequenceByRegion(pixs, pixam, sequence, minw, minh);
385 pixaDestroy(&pixam);
386 boxaDestroy(&boxa);
387 if (!pixad)
388 return (PIX *)ERROR_PTR("pixad not made", procName, NULL);
389
390 /* Display the result out into pixd */
391 pixd = pixCreateTemplate(pixs);
392 n = pixaGetCount(pixad);
393 for (i = 0; i < n; i++) {
394 pixaGetBoxGeometry(pixad, i, &x, &y, &w, &h);
395 pix = pixaGetPix(pixad, i, L_CLONE);
396 pixRasterop(pixd, x, y, w, h, PIX_PAINT, pix, 0, 0);
397 pixDestroy(&pix);
398 }
399
400 if (pboxa)
401 *pboxa = pixaGetBoxa(pixad, L_CLONE);
402 pixaDestroy(&pixad);
403 return pixd;
404}
405
406
429PIXA *
431 PIXA *pixam,
432 const char *sequence,
433 l_int32 minw,
434 l_int32 minh)
435{
436l_int32 n, i, w, h, same, maxd, fullpa, fullba;
437BOX *box;
438PIX *pix1, *pix2, *pix3;
439PIXA *pixad;
440
441 PROCNAME("pixaMorphSequenceByRegion");
442
443 if (!pixs)
444 return (PIXA *)ERROR_PTR("pixs not defined", procName, NULL);
445 if (pixGetDepth(pixs) != 1)
446 return (PIXA *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
447 if (!sequence)
448 return (PIXA *)ERROR_PTR("sequence not defined", procName, NULL);
449 if (!pixam)
450 return (PIXA *)ERROR_PTR("pixam not defined", procName, NULL);
451 pixaVerifyDepth(pixam, &same, &maxd);
452 if (maxd != 1)
453 return (PIXA *)ERROR_PTR("mask depth not 1 bpp", procName, NULL);
454 pixaIsFull(pixam, &fullpa, &fullba);
455 if (!fullpa || !fullba)
456 return (PIXA *)ERROR_PTR("missing comps in pixam", procName, NULL);
457 n = pixaGetCount(pixam);
458 if (minw <= 0) minw = 1;
459 if (minh <= 0) minh = 1;
460
461 if ((pixad = pixaCreate(n)) == NULL)
462 return (PIXA *)ERROR_PTR("pixad not made", procName, NULL);
463
464 /* Use the rectangle to remove the appropriate part of pixs;
465 * then AND with the mask component to get the actual fg
466 * of pixs that is under the mask component. */
467 for (i = 0; i < n; i++) {
468 pixaGetPixDimensions(pixam, i, &w, &h, NULL);
469 if (w >= minw && h >= minh) {
470 pix1 = pixaGetPix(pixam, i, L_CLONE);
471 box = pixaGetBox(pixam, i, L_COPY);
472 pix2 = pixClipRectangle(pixs, box, NULL);
473 pixAnd(pix2, pix2, pix1);
474 pix3 = pixMorphCompSequence(pix2, sequence, 0);
475 pixDestroy(&pix1);
476 pixDestroy(&pix2);
477 if (!pix3) {
478 boxDestroy(&box);
479 pixaDestroy(&pixad);
480 L_ERROR("pix3 not made in iter %d; aborting\n", procName, i);
481 break;
482 }
483 pixaAddPix(pixad, pix3, L_INSERT);
484 pixaAddBox(pixad, box, L_INSERT);
485 }
486 }
487
488 return pixad;
489}
490
491
492/*-----------------------------------------------------------------*
493 * Union and intersection of parallel composite operations *
494 *-----------------------------------------------------------------*/
504PIX *
506 SELA *sela,
507 l_int32 type)
508{
509l_int32 n, i;
510PIX *pixt, *pixd;
511SEL *sel;
512
513 PROCNAME("pixUnionOfMorphOps");
514
515 if (!pixs || pixGetDepth(pixs) != 1)
516 return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
517 if (!sela)
518 return (PIX *)ERROR_PTR("sela not defined", procName, NULL);
519 n = selaGetCount(sela);
520 if (n == 0)
521 return (PIX *)ERROR_PTR("no sels in sela", procName, NULL);
522 if (type != L_MORPH_DILATE && type != L_MORPH_ERODE &&
523 type != L_MORPH_OPEN && type != L_MORPH_CLOSE &&
524 type != L_MORPH_HMT)
525 return (PIX *)ERROR_PTR("invalid type", procName, NULL);
526
527 pixd = pixCreateTemplate(pixs);
528 for (i = 0; i < n; i++) {
529 sel = selaGetSel(sela, i);
530 if (type == L_MORPH_DILATE)
531 pixt = pixDilate(NULL, pixs, sel);
532 else if (type == L_MORPH_ERODE)
533 pixt = pixErode(NULL, pixs, sel);
534 else if (type == L_MORPH_OPEN)
535 pixt = pixOpen(NULL, pixs, sel);
536 else if (type == L_MORPH_CLOSE)
537 pixt = pixClose(NULL, pixs, sel);
538 else /* type == L_MORPH_HMT */
539 pixt = pixHMT(NULL, pixs, sel);
540 pixOr(pixd, pixd, pixt);
541 pixDestroy(&pixt);
542 }
543
544 return pixd;
545}
546
547
557PIX *
559 SELA *sela,
560 l_int32 type)
561{
562l_int32 n, i;
563PIX *pixt, *pixd;
564SEL *sel;
565
566 PROCNAME("pixIntersectionOfMorphOps");
567
568 if (!pixs || pixGetDepth(pixs) != 1)
569 return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
570 if (!sela)
571 return (PIX *)ERROR_PTR("sela not defined", procName, NULL);
572 n = selaGetCount(sela);
573 if (n == 0)
574 return (PIX *)ERROR_PTR("no sels in sela", procName, NULL);
575 if (type != L_MORPH_DILATE && type != L_MORPH_ERODE &&
576 type != L_MORPH_OPEN && type != L_MORPH_CLOSE &&
577 type != L_MORPH_HMT)
578 return (PIX *)ERROR_PTR("invalid type", procName, NULL);
579
580 pixd = pixCreateTemplate(pixs);
581 pixSetAll(pixd);
582 for (i = 0; i < n; i++) {
583 sel = selaGetSel(sela, i);
584 if (type == L_MORPH_DILATE)
585 pixt = pixDilate(NULL, pixs, sel);
586 else if (type == L_MORPH_ERODE)
587 pixt = pixErode(NULL, pixs, sel);
588 else if (type == L_MORPH_OPEN)
589 pixt = pixOpen(NULL, pixs, sel);
590 else if (type == L_MORPH_CLOSE)
591 pixt = pixClose(NULL, pixs, sel);
592 else /* type == L_MORPH_HMT */
593 pixt = pixHMT(NULL, pixs, sel);
594 pixAnd(pixd, pixd, pixt);
595 pixDestroy(&pixt);
596 }
597
598 return pixd;
599}
600
601
602
603/*-----------------------------------------------------------------*
604 * Selective connected component filling *
605 *-----------------------------------------------------------------*/
615PIX *
617 l_int32 connectivity,
618 l_int32 minw,
619 l_int32 minh)
620{
621l_int32 n, i, x, y, w, h;
622BOXA *boxa;
623PIX *pix1, *pix2, *pixd;
624PIXA *pixa;
625
626 PROCNAME("pixSelectiveConnCompFill");
627
628 if (!pixs)
629 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
630 if (pixGetDepth(pixs) != 1)
631 return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
632 if (minw <= 0) minw = 1;
633 if (minh <= 0) minh = 1;
634
635 if ((boxa = pixConnComp(pixs, &pixa, connectivity)) == NULL)
636 return (PIX *)ERROR_PTR("boxa not made", procName, NULL);
637 n = boxaGetCount(boxa);
638 pixd = pixCopy(NULL, pixs);
639 for (i = 0; i < n; i++) {
640 boxaGetBoxGeometry(boxa, i, &x, &y, &w, &h);
641 if (w >= minw && h >= minh) {
642 pix1 = pixaGetPix(pixa, i, L_CLONE);
643 if ((pix2 = pixHolesByFilling(pix1, 12 - connectivity)) == NULL) {
644 L_ERROR("pix2 not made in iter %d\n", procName, i);
645 pixDestroy(&pix1);
646 continue;
647 }
648 pixRasterop(pixd, x, y, w, h, PIX_PAINT, pix2, 0, 0);
649 pixDestroy(&pix1);
650 pixDestroy(&pix2);
651 }
652 }
653 pixaDestroy(&pixa);
654 boxaDestroy(&boxa);
655
656 return pixd;
657}
658
659
660/*-----------------------------------------------------------------*
661 * Removal of matched patterns *
662 *-----------------------------------------------------------------*/
686l_ok
688 PIX *pixp,
689 PIX *pixe,
690 l_int32 x0,
691 l_int32 y0,
692 l_int32 dsize)
693{
694l_int32 i, nc, x, y, w, h, xb, yb;
695BOXA *boxa;
696PIX *pix1, *pix2;
697PIXA *pixa;
698PTA *pta;
699SEL *sel;
700
701 PROCNAME("pixRemoveMatchedPattern");
702
703 if (!pixs)
704 return ERROR_INT("pixs not defined", procName, 1);
705 if (!pixp)
706 return ERROR_INT("pixp not defined", procName, 1);
707 if (!pixe)
708 return ERROR_INT("pixe not defined", procName, 1);
709 if (pixGetDepth(pixs) != 1 || pixGetDepth(pixp) != 1 ||
710 pixGetDepth(pixe) != 1)
711 return ERROR_INT("all input pix not 1 bpp", procName, 1);
712 if (dsize < 0 || dsize > 4)
713 return ERROR_INT("dsize not in {0,1,2,3,4}", procName, 1);
714
715 /* Find the connected components and their centroids */
716 boxa = pixConnComp(pixe, &pixa, 8);
717 if ((nc = boxaGetCount(boxa)) == 0) {
718 L_WARNING("no matched patterns\n", procName);
719 boxaDestroy(&boxa);
720 pixaDestroy(&pixa);
721 return 0;
722 }
723 pta = pixaCentroids(pixa);
724 pixaDestroy(&pixa);
725
726 /* Optionally dilate the pattern, first adding a border that
727 * is large enough to accommodate the dilated pixels */
728 sel = NULL;
729 if (dsize > 0) {
730 sel = selCreateBrick(2 * dsize + 1, 2 * dsize + 1, dsize, dsize,
731 SEL_HIT);
732 pix1 = pixAddBorder(pixp, dsize, 0);
733 pix2 = pixDilate(NULL, pix1, sel);
734 selDestroy(&sel);
735 pixDestroy(&pix1);
736 } else {
737 pix2 = pixClone(pixp);
738 }
739
740 /* Subtract out each dilated pattern. The centroid of each
741 * component is located at:
742 * (box->x + x, box->y + y)
743 * and the 'center' of the pattern used in making pixe is located at
744 * (x0 + dsize, (y0 + dsize)
745 * relative to the UL corner of the pattern. The center of the
746 * pattern is placed at the center of the component. */
747 pixGetDimensions(pix2, &w, &h, NULL);
748 for (i = 0; i < nc; i++) {
749 ptaGetIPt(pta, i, &x, &y);
750 boxaGetBoxGeometry(boxa, i, &xb, &yb, NULL, NULL);
751 pixRasterop(pixs, xb + x - x0 - dsize, yb + y - y0 - dsize,
752 w, h, PIX_DST & PIX_NOT(PIX_SRC), pix2, 0, 0);
753 }
754
755 boxaDestroy(&boxa);
756 ptaDestroy(&pta);
757 pixDestroy(&pix2);
758 return 0;
759}
760
761
762/*-----------------------------------------------------------------*
763 * Display of matched patterns *
764 *-----------------------------------------------------------------*/
791PIX *
793 PIX *pixp,
794 PIX *pixe,
795 l_int32 x0,
796 l_int32 y0,
797 l_uint32 color,
798 l_float32 scale,
799 l_int32 nlevels)
800{
801l_int32 i, nc, xb, yb, x, y, xi, yi, rval, gval, bval;
802BOXA *boxa;
803PIX *pixd, *pixt, *pixps;
804PIXA *pixa;
805PTA *pta;
806PIXCMAP *cmap;
807
808 PROCNAME("pixDisplayMatchedPattern");
809
810 if (!pixs)
811 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
812 if (!pixp)
813 return (PIX *)ERROR_PTR("pixp not defined", procName, NULL);
814 if (!pixe)
815 return (PIX *)ERROR_PTR("pixe not defined", procName, NULL);
816 if (pixGetDepth(pixs) != 1 || pixGetDepth(pixp) != 1 ||
817 pixGetDepth(pixe) != 1)
818 return (PIX *)ERROR_PTR("all input pix not 1 bpp", procName, NULL);
819 if (scale > 1.0 || scale <= 0.0) {
820 L_WARNING("scale > 1.0 or < 0.0; setting to 1.0\n", procName);
821 scale = 1.0;
822 }
823
824 /* Find the connected components and their centroids */
825 boxa = pixConnComp(pixe, &pixa, 8);
826 if ((nc = boxaGetCount(boxa)) == 0) {
827 L_WARNING("no matched patterns\n", procName);
828 boxaDestroy(&boxa);
829 pixaDestroy(&pixa);
830 return 0;
831 }
832 pta = pixaCentroids(pixa);
833
834 extractRGBValues(color, &rval, &gval, &bval);
835 if (scale == 1.0) { /* output 4 bpp at full resolution */
836 pixd = pixConvert1To4(NULL, pixs, 0, 1);
837 cmap = pixcmapCreate(4);
838 pixcmapAddColor(cmap, 255, 255, 255);
839 pixcmapAddColor(cmap, 0, 0, 0);
840 pixSetColormap(pixd, cmap);
841
842 /* Paint through pixp for each match location. The centroid of each
843 * component in pixe is located at:
844 * (box->x + x, box->y + y)
845 * and the 'center' of the pattern used in making pixe is located at
846 * (x0, y0)
847 * relative to the UL corner of the pattern. The center of the
848 * pattern is placed at the center of the component. */
849 for (i = 0; i < nc; i++) {
850 ptaGetIPt(pta, i, &x, &y);
851 boxaGetBoxGeometry(boxa, i, &xb, &yb, NULL, NULL);
852 pixSetMaskedCmap(pixd, pixp, xb + x - x0, yb + y - y0,
853 rval, gval, bval);
854 }
855 } else { /* output 4 bpp downscaled */
856 pixt = pixScaleToGray(pixs, scale);
857 pixd = pixThresholdTo4bpp(pixt, nlevels, 1);
858 pixps = pixScaleBySampling(pixp, scale, scale);
859
860 for (i = 0; i < nc; i++) {
861 ptaGetIPt(pta, i, &x, &y);
862 boxaGetBoxGeometry(boxa, i, &xb, &yb, NULL, NULL);
863 xi = (l_int32)(scale * (xb + x - x0));
864 yi = (l_int32)(scale * (yb + y - y0));
865 pixSetMaskedCmap(pixd, pixps, xi, yi, rval, gval, bval);
866 }
867 pixDestroy(&pixt);
868 pixDestroy(&pixps);
869 }
870
871 boxaDestroy(&boxa);
872 pixaDestroy(&pixa);
873 ptaDestroy(&pta);
874 return pixd;
875}
876
877
878/*------------------------------------------------------------------------*
879 * Extension of pixa by iterative erosion or dilation (and by scaling) *
880 *------------------------------------------------------------------------*/
903PIXA *
905 l_int32 type,
906 l_int32 niters,
907 SEL *sel,
908 l_int32 include)
909{
910l_int32 maxdepth, i, j, n;
911PIX *pix0, *pix1, *pix2;
912SEL *selt;
913PIXA *pixad;
914
915 PROCNAME("pixaExtendByMorph");
916
917 if (!pixas)
918 return (PIXA *)ERROR_PTR("pixas undefined", procName, NULL);
919 if (niters <= 0) {
920 L_INFO("niters = %d; nothing to do\n", procName, niters);
921 return pixaCopy(pixas, L_CLONE);
922 }
923 if (type != L_MORPH_DILATE && type != L_MORPH_ERODE)
924 return (PIXA *)ERROR_PTR("invalid type", procName, NULL);
925 pixaGetDepthInfo(pixas, &maxdepth, NULL);
926 if (maxdepth > 1)
927 return (PIXA *)ERROR_PTR("some pix have bpp > 1", procName, NULL);
928
929 if (!sel)
930 selt = selCreateBrick(2, 2, 0, 0, SEL_HIT); /* default */
931 else
932 selt = selCopy(sel);
933 n = pixaGetCount(pixas);
934 pixad = pixaCreate(n * niters);
935 for (i = 0; i < n; i++) {
936 pix1 = pixaGetPix(pixas, i, L_CLONE);
937 if (include) pixaAddPix(pixad, pix1, L_COPY);
938 pix0 = pix1; /* need to keep the handle to destroy the clone */
939 for (j = 0; j < niters; j++) {
940 if (type == L_MORPH_DILATE) {
941 pix2 = pixDilate(NULL, pix1, selt);
942 } else { /* L_MORPH_ERODE */
943 pix2 = pixErode(NULL, pix1, selt);
944 }
945 pixaAddPix(pixad, pix2, L_INSERT);
946 pix1 = pix2; /* owned by pixad; do not destroy */
947 }
948 pixDestroy(&pix0);
949 }
950
951 selDestroy(&selt);
952 return pixad;
953}
954
955
975PIXA *
977 NUMA *nasc,
978 l_int32 type,
979 l_int32 include)
980{
981l_int32 i, j, n, nsc, w, h, scalew, scaleh;
982l_float32 scalefact;
983PIX *pix1, *pix2;
984PIXA *pixad;
985
986 PROCNAME("pixaExtendByScaling");
987
988 if (!pixas)
989 return (PIXA *)ERROR_PTR("pixas undefined", procName, NULL);
990 if (!nasc || numaGetCount(nasc) == 0)
991 return (PIXA *)ERROR_PTR("nasc undefined or empty", procName, NULL);
992 if (type != L_HORIZ && type != L_VERT && type != L_BOTH_DIRECTIONS)
993 return (PIXA *)ERROR_PTR("invalid type", procName, NULL);
994
995 n = pixaGetCount(pixas);
996 nsc = numaGetCount(nasc);
997 if ((pixad = pixaCreate(n * (nsc + 1))) == NULL) {
998 L_ERROR("pixad not made: n = %d, nsc = %d\n", procName, n, nsc);
999 return NULL;
1000 }
1001 for (i = 0; i < n; i++) {
1002 pix1 = pixaGetPix(pixas, i, L_CLONE);
1003 if (include) pixaAddPix(pixad, pix1, L_COPY);
1004 pixGetDimensions(pix1, &w, &h, NULL);
1005 for (j = 0; j < nsc; j++) {
1006 numaGetFValue(nasc, j, &scalefact);
1007 scalew = w;
1008 scaleh = h;
1009 if (type == L_HORIZ || type == L_BOTH_DIRECTIONS)
1010 scalew = w * scalefact;
1011 if (type == L_VERT || type == L_BOTH_DIRECTIONS)
1012 scaleh = h * scalefact;
1013 pix2 = pixScaleToSize(pix1, scalew, scaleh);
1014 pixaAddPix(pixad, pix2, L_INSERT);
1015 }
1016 pixDestroy(&pix1);
1017 }
1018 return pixad;
1019}
1020
1021
1022/*-----------------------------------------------------------------*
1023 * Iterative morphological seed filling *
1024 *-----------------------------------------------------------------*/
1043PIX *
1045 PIX *pixm,
1046 l_int32 maxiters,
1047 l_int32 connectivity)
1048{
1049l_int32 same, i;
1050PIX *pixt, *pixd, *temp;
1051SEL *sel_3;
1052
1053 PROCNAME("pixSeedfillMorph");
1054
1055 if (!pixs || pixGetDepth(pixs) != 1)
1056 return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
1057 if (!pixm)
1058 return (PIX *)ERROR_PTR("mask pix not defined", procName, NULL);
1059 if (connectivity != 4 && connectivity != 8)
1060 return (PIX *)ERROR_PTR("connectivity not in {4,8}", procName, NULL);
1061 if (maxiters <= 0) maxiters = 1000;
1062 if (pixSizesEqual(pixs, pixm) == 0)
1063 return (PIX *)ERROR_PTR("pix sizes unequal", procName, NULL);
1064
1065 if ((sel_3 = selCreateBrick(3, 3, 1, 1, SEL_HIT)) == NULL)
1066 return (PIX *)ERROR_PTR("sel_3 not made", procName, NULL);
1067 if (connectivity == 4) { /* remove corner hits to make a '+' */
1068 selSetElement(sel_3, 0, 0, SEL_DONT_CARE);
1069 selSetElement(sel_3, 2, 2, SEL_DONT_CARE);
1070 selSetElement(sel_3, 2, 0, SEL_DONT_CARE);
1071 selSetElement(sel_3, 0, 2, SEL_DONT_CARE);
1072 }
1073
1074 pixt = pixCopy(NULL, pixs);
1075 pixd = pixCreateTemplate(pixs);
1076 for (i = 1; i <= maxiters; i++) {
1077 pixDilate(pixd, pixt, sel_3);
1078 pixAnd(pixd, pixd, pixm);
1079 pixEqual(pixd, pixt, &same);
1080 if (same || i == maxiters)
1081 break;
1082 else
1083 SWAP(pixt, pixd);
1084 }
1085 lept_stderr(" Num iters in binary reconstruction = %d\n", i);
1086
1087 pixDestroy(&pixt);
1088 selDestroy(&sel_3);
1089 return pixd;
1090}
1091
1092
1093/*-----------------------------------------------------------------*
1094 * Granulometry on binary images *
1095 *-----------------------------------------------------------------*/
1105NUMA *
1107 l_int32 runtype,
1108 l_int32 direction,
1109 l_int32 maxsize)
1110{
1111l_int32 count, i, size;
1112l_float32 val;
1113NUMA *na, *nah;
1114PIX *pix1, *pix2, *pix3;
1115SEL *sel_2a;
1116
1117 PROCNAME("pixRunHistogramMorph");
1118
1119 if (!pixs)
1120 return (NUMA *)ERROR_PTR("seed pix not defined", procName, NULL);
1121 if (runtype != L_RUN_OFF && runtype != L_RUN_ON)
1122 return (NUMA *)ERROR_PTR("invalid run type", procName, NULL);
1123 if (direction != L_HORIZ && direction != L_VERT)
1124 return (NUMA *)ERROR_PTR("direction not in {L_HORIZ, L_VERT}",
1125 procName, NULL);
1126 if (pixGetDepth(pixs) != 1)
1127 return (NUMA *)ERROR_PTR("pixs must be binary", procName, NULL);
1128
1129 if (direction == L_HORIZ)
1130 sel_2a = selCreateBrick(1, 2, 0, 0, SEL_HIT);
1131 else /* direction == L_VERT */
1132 sel_2a = selCreateBrick(2, 1, 0, 0, SEL_HIT);
1133 if (!sel_2a)
1134 return (NUMA *)ERROR_PTR("sel_2a not made", procName, NULL);
1135
1136 if (runtype == L_RUN_OFF) {
1137 if ((pix1 = pixCopy(NULL, pixs)) == NULL) {
1138 selDestroy(&sel_2a);
1139 return (NUMA *)ERROR_PTR("pix1 not made", procName, NULL);
1140 }
1141 pixInvert(pix1, pix1);
1142 } else { /* runtype == L_RUN_ON */
1143 pix1 = pixClone(pixs);
1144 }
1145
1146 /* Get pixel counts at different stages of erosion */
1147 na = numaCreate(0);
1148 pix2 = pixCreateTemplate(pixs);
1149 pix3 = pixCreateTemplate(pixs);
1150 pixCountPixels(pix1, &count, NULL);
1151 numaAddNumber(na, count);
1152 pixErode(pix2, pix1, sel_2a);
1153 pixCountPixels(pix2, &count, NULL);
1154 numaAddNumber(na, count);
1155 for (i = 0; i < maxsize / 2; i++) {
1156 pixErode(pix3, pix2, sel_2a);
1157 pixCountPixels(pix3, &count, NULL);
1158 numaAddNumber(na, count);
1159 pixErode(pix2, pix3, sel_2a);
1160 pixCountPixels(pix2, &count, NULL);
1161 numaAddNumber(na, count);
1162 }
1163
1164 /* Compute length histogram */
1165 size = numaGetCount(na);
1166 nah = numaCreate(size);
1167 numaAddNumber(nah, 0); /* number at length 0 */
1168 for (i = 1; i < size - 1; i++) {
1169 val = na->array[i+1] - 2 * na->array[i] + na->array[i-1];
1170 numaAddNumber(nah, val);
1171 }
1172
1173 pixDestroy(&pix1);
1174 pixDestroy(&pix2);
1175 pixDestroy(&pix3);
1176 selDestroy(&sel_2a);
1177 numaDestroy(&na);
1178 return nah;
1179}
1180
1181
1182/*-----------------------------------------------------------------*
1183 * Composite operations on grayscale images *
1184 *-----------------------------------------------------------------*/
1205PIX *
1207 l_int32 hsize,
1208 l_int32 vsize,
1209 l_int32 type)
1210{
1211PIX *pixt, *pixd;
1212
1213 PROCNAME("pixTophat");
1214
1215 if (!pixs)
1216 return (PIX *)ERROR_PTR("seed pix not defined", procName, NULL);
1217 if (pixGetDepth(pixs) != 8)
1218 return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
1219 if (hsize < 1 || vsize < 1)
1220 return (PIX *)ERROR_PTR("hsize or vsize < 1", procName, NULL);
1221 if ((hsize & 1) == 0 ) {
1222 L_WARNING("horiz sel size must be odd; increasing by 1\n", procName);
1223 hsize++;
1224 }
1225 if ((vsize & 1) == 0 ) {
1226 L_WARNING("vert sel size must be odd; increasing by 1\n", procName);
1227 vsize++;
1228 }
1229 if (type != L_TOPHAT_WHITE && type != L_TOPHAT_BLACK)
1230 return (PIX *)ERROR_PTR("type must be L_TOPHAT_BLACK or L_TOPHAT_WHITE",
1231 procName, NULL);
1232
1233 if (hsize == 1 && vsize == 1)
1234 return pixCreateTemplate(pixs);
1235
1236 switch (type)
1237 {
1238 case L_TOPHAT_WHITE:
1239 if ((pixt = pixOpenGray(pixs, hsize, vsize)) == NULL)
1240 return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
1241 pixd = pixSubtractGray(NULL, pixs, pixt);
1242 pixDestroy(&pixt);
1243 break;
1244 case L_TOPHAT_BLACK:
1245 if ((pixd = pixCloseGray(pixs, hsize, vsize)) == NULL)
1246 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1247 pixSubtractGray(pixd, pixd, pixs);
1248 break;
1249 default:
1250 return (PIX *)ERROR_PTR("invalid type", procName, NULL);
1251 }
1252
1253 return pixd;
1254}
1255
1256
1305PIX *
1307 l_int32 height,
1308 l_int32 connectivity)
1309{
1310PIX *pixsd, *pixd;
1311
1312 PROCNAME("pixHDome");
1313
1314 if (!pixs)
1315 return (PIX *)ERROR_PTR("src pix not defined", procName, NULL);
1316 if (pixGetDepth(pixs) != 8)
1317 return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
1318 if (height < 0)
1319 return (PIX *)ERROR_PTR("height not >= 0", procName, NULL);
1320 if (height == 0)
1321 return pixCreateTemplate(pixs);
1322
1323 if ((pixsd = pixCopy(NULL, pixs)) == NULL)
1324 return (PIX *)ERROR_PTR("pixsd not made", procName, NULL);
1325 pixAddConstantGray(pixsd, -height);
1326 pixSeedfillGray(pixsd, pixs, connectivity);
1327 pixd = pixSubtractGray(NULL, pixs, pixsd);
1328 pixDestroy(&pixsd);
1329 return pixd;
1330}
1331
1332
1361PIX *
1363 l_int32 xsize,
1364 l_int32 ysize,
1365 l_int32 type)
1366{
1367PIX *pix1, *pix2, *pix3, *pixd;
1368
1369 PROCNAME("pixFastTophat");
1370
1371 if (!pixs)
1372 return (PIX *)ERROR_PTR("seed pix not defined", procName, NULL);
1373 if (pixGetDepth(pixs) != 8)
1374 return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
1375 if (xsize < 1 || ysize < 1)
1376 return (PIX *)ERROR_PTR("size < 1", procName, NULL);
1377 if (type != L_TOPHAT_WHITE && type != L_TOPHAT_BLACK)
1378 return (PIX *)ERROR_PTR("type must be L_TOPHAT_BLACK or L_TOPHAT_WHITE",
1379 procName, NULL);
1380
1381 if (xsize == 1 && ysize == 1)
1382 return pixCreateTemplate(pixs);
1383
1384 switch (type)
1385 {
1386 case L_TOPHAT_WHITE:
1387 if ((pix1 = pixScaleGrayMinMax(pixs, xsize, ysize, L_CHOOSE_MIN))
1388 == NULL)
1389 return (PIX *)ERROR_PTR("pix1 not made", procName, NULL);
1390 pix2 = pixBlockconv(pix1, 1, 1); /* small smoothing */
1391 pix3 = pixScaleBySampling(pix2, xsize, ysize);
1392 pixd = pixSubtractGray(NULL, pixs, pix3);
1393 pixDestroy(&pix3);
1394 break;
1395 case L_TOPHAT_BLACK:
1396 if ((pix1 = pixScaleGrayMinMax(pixs, xsize, ysize, L_CHOOSE_MAX))
1397 == NULL)
1398 return (PIX *)ERROR_PTR("pix1 not made", procName, NULL);
1399 pix2 = pixBlockconv(pix1, 1, 1); /* small smoothing */
1400 pixd = pixScaleBySampling(pix2, xsize, ysize);
1401 pixSubtractGray(pixd, pixd, pixs);
1402 break;
1403 default:
1404 return (PIX *)ERROR_PTR("invalid type", procName, NULL);
1405 }
1406
1407 pixDestroy(&pix1);
1408 pixDestroy(&pix2);
1409 return pixd;
1410}
1411
1412
1423PIX *
1425 l_int32 hsize,
1426 l_int32 vsize,
1427 l_int32 smoothing)
1428{
1429PIX *pixg, *pixd;
1430
1431 PROCNAME("pixMorphGradient");
1432
1433 if (!pixs)
1434 return (PIX *)ERROR_PTR("seed pix not defined", procName, NULL);
1435 if (pixGetDepth(pixs) != 8)
1436 return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
1437 if (hsize < 1 || vsize < 1)
1438 return (PIX *)ERROR_PTR("hsize or vsize < 1", procName, NULL);
1439 if ((hsize & 1) == 0 ) {
1440 L_WARNING("horiz sel size must be odd; increasing by 1\n", procName);
1441 hsize++;
1442 }
1443 if ((vsize & 1) == 0 ) {
1444 L_WARNING("vert sel size must be odd; increasing by 1\n", procName);
1445 vsize++;
1446 }
1447
1448 /* Optionally smooth first to remove noise.
1449 * If smoothing is 0, just get a copy */
1450 pixg = pixBlockconvGray(pixs, NULL, smoothing, smoothing);
1451
1452 /* This gives approximately the gradient of a transition */
1453 pixd = pixDilateGray(pixg, hsize, vsize);
1454 pixSubtractGray(pixd, pixd, pixg);
1455 pixDestroy(&pixg);
1456 return pixd;
1457}
1458
1459
1460/*-----------------------------------------------------------------*
1461 * Centroid of component *
1462 *-----------------------------------------------------------------*/
1477PTA *
1479{
1480l_int32 i, n;
1481l_int32 *centtab = NULL;
1482l_int32 *sumtab = NULL;
1483l_float32 x, y;
1484PIX *pix;
1485PTA *pta;
1486
1487 PROCNAME("pixaCentroids");
1488
1489 if (!pixa)
1490 return (PTA *)ERROR_PTR("pixa not defined", procName, NULL);
1491 if ((n = pixaGetCount(pixa)) == 0)
1492 return (PTA *)ERROR_PTR("no pix in pixa", procName, NULL);
1493
1494 if ((pta = ptaCreate(n)) == NULL)
1495 return (PTA *)ERROR_PTR("pta not defined", procName, NULL);
1496 centtab = makePixelCentroidTab8();
1497 sumtab = makePixelSumTab8();
1498
1499 for (i = 0; i < n; i++) {
1500 pix = pixaGetPix(pixa, i, L_CLONE);
1501 if (pixCentroid(pix, centtab, sumtab, &x, &y) == 1)
1502 L_ERROR("centroid failure for pix %d\n", procName, i);
1503 pixDestroy(&pix);
1504 ptaAddPt(pta, x, y);
1505 }
1506
1507 LEPT_FREE(centtab);
1508 LEPT_FREE(sumtab);
1509 return pta;
1510}
1511
1512
1532l_ok
1534 l_int32 *centtab,
1535 l_int32 *sumtab,
1536 l_float32 *pxave,
1537 l_float32 *pyave)
1538{
1539l_int32 w, h, d, i, j, wpl, pixsum, rowsum, val;
1540l_float32 xsum, ysum;
1541l_uint32 *data, *line;
1542l_uint32 word;
1543l_uint8 byte;
1544l_int32 *ctab, *stab;
1545
1546 PROCNAME("pixCentroid");
1547
1548 if (!pxave || !pyave)
1549 return ERROR_INT("&pxave and &pyave not defined", procName, 1);
1550 *pxave = *pyave = 0.0;
1551 if (!pix)
1552 return ERROR_INT("pix not defined", procName, 1);
1553 pixGetDimensions(pix, &w, &h, &d);
1554 if (d != 1 && d != 8)
1555 return ERROR_INT("pix not 1 or 8 bpp", procName, 1);
1556
1557 ctab = centtab;
1558 stab = sumtab;
1559 if (d == 1) {
1560 pixSetPadBits(pix, 0);
1561 if (!centtab)
1562 ctab = makePixelCentroidTab8();
1563 if (!sumtab)
1564 stab = makePixelSumTab8();
1565 }
1566
1567 data = pixGetData(pix);
1568 wpl = pixGetWpl(pix);
1569 xsum = ysum = 0.0;
1570 pixsum = 0;
1571 if (d == 1) {
1572 for (i = 0; i < h; i++) {
1573 /* The body of this loop computes the sum of the set
1574 * (1) bits on this row, weighted by their distance
1575 * from the left edge of pix, and accumulates that into
1576 * xsum; it accumulates their distance from the top
1577 * edge of pix into ysum, and their total count into
1578 * pixsum. It's equivalent to
1579 * for (j = 0; j < w; j++) {
1580 * if (GET_DATA_BIT(line, j)) {
1581 * xsum += j;
1582 * ysum += i;
1583 * pixsum++;
1584 * }
1585 * }
1586 */
1587 line = data + wpl * i;
1588 rowsum = 0;
1589 for (j = 0; j < wpl; j++) {
1590 word = line[j];
1591 if (word) {
1592 byte = word & 0xff;
1593 rowsum += stab[byte];
1594 xsum += ctab[byte] + (j * 32 + 24) * stab[byte];
1595 byte = (word >> 8) & 0xff;
1596 rowsum += stab[byte];
1597 xsum += ctab[byte] + (j * 32 + 16) * stab[byte];
1598 byte = (word >> 16) & 0xff;
1599 rowsum += stab[byte];
1600 xsum += ctab[byte] + (j * 32 + 8) * stab[byte];
1601 byte = (word >> 24) & 0xff;
1602 rowsum += stab[byte];
1603 xsum += ctab[byte] + j * 32 * stab[byte];
1604 }
1605 }
1606 pixsum += rowsum;
1607 ysum += rowsum * i;
1608 }
1609 if (pixsum == 0) {
1610 L_WARNING("no ON pixels in pix\n", procName);
1611 } else {
1612 *pxave = xsum / (l_float32)pixsum;
1613 *pyave = ysum / (l_float32)pixsum;
1614 }
1615 } else { /* d == 8 */
1616 for (i = 0; i < h; i++) {
1617 line = data + wpl * i;
1618 for (j = 0; j < w; j++) {
1619 val = GET_DATA_BYTE(line, j);
1620 xsum += val * j;
1621 ysum += val * i;
1622 pixsum += val;
1623 }
1624 }
1625 if (pixsum == 0) {
1626 L_WARNING("all pixels are 0\n", procName);
1627 } else {
1628 *pxave = xsum / (l_float32)pixsum;
1629 *pyave = ysum / (l_float32)pixsum;
1630 }
1631 }
1632
1633 if (!centtab) LEPT_FREE(ctab);
1634 if (!sumtab) LEPT_FREE(stab);
1635 return 0;
1636}
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:282
l_ok boxaGetBoxGeometry(BOXA *boxa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxaGetBoxGeometry()
Definition: boxbasic.c:879
l_int32 boxaGetCount(BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:734
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:583
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
Definition: colormap.c:125
l_ok pixcmapAddColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapAddColor()
Definition: colormap.c:414
l_ok pixEqual(PIX *pix1, PIX *pix2, l_int32 *psame)
pixEqual()
Definition: compare.c:156
BOXA * pixConnComp(PIX *pixs, PIXA **ppixa, l_int32 connectivity)
pixConnComp()
Definition: conncomp.c:151
PIX * pixBlockconv(PIX *pix, l_int32 wc, l_int32 hc)
pixBlockconv()
Definition: convolve.c:132
PIX * pixBlockconvGray(PIX *pixs, PIX *pixacc, l_int32 wc, l_int32 hc)
pixBlockconvGray()
Definition: convolve.c:216
PIX * pixDilateGray(PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateGray()
Definition: graymorph.c:278
PIX * pixCloseGray(PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseGray()
Definition: graymorph.c:526
PIX * pixOpenGray(PIX *pixs, l_int32 hsize, l_int32 vsize)
pixOpenGray()
Definition: graymorph.c:394
PIX * pixThresholdTo4bpp(PIX *pixs, l_int32 nlevels, l_int32 cmapflag)
pixThresholdTo4bpp()
Definition: grayquant.c:1520
PIX * pixDilateBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateBrick()
Definition: morph.c:688
PIX * pixOpen(PIX *pixd, PIX *pixs, SEL *sel)
pixOpen()
Definition: morph.c:426
PIX * pixDilate(PIX *pixd, PIX *pixs, SEL *sel)
pixDilate()
Definition: morph.c:213
PIX * pixClose(PIX *pixd, PIX *pixs, SEL *sel)
pixClose()
Definition: morph.c:473
PIX * pixHMT(PIX *pixd, PIX *pixs, SEL *sel)
pixHMT()
Definition: morph.c:342
PIX * pixErode(PIX *pixd, PIX *pixs, SEL *sel)
pixErode()
Definition: morph.c:267
PIX * pixErodeBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeBrick()
Definition: morph.c:758
PIXA * pixaExtendByScaling(PIXA *pixas, NUMA *nasc, l_int32 type, l_int32 include)
pixaExtendByScaling()
Definition: morphapp.c:976
PIX * pixSelectiveConnCompFill(PIX *pixs, l_int32 connectivity, l_int32 minw, l_int32 minh)
pixSelectiveConnCompFill()
Definition: morphapp.c:616
PIX * pixHDome(PIX *pixs, l_int32 height, l_int32 connectivity)
pixHDome()
Definition: morphapp.c:1306
NUMA * pixRunHistogramMorph(PIX *pixs, l_int32 runtype, l_int32 direction, l_int32 maxsize)
pixRunHistogramMorph()
Definition: morphapp.c:1106
PIXA * pixaExtendByMorph(PIXA *pixas, l_int32 type, l_int32 niters, SEL *sel, l_int32 include)
pixaExtendByMorph()
Definition: morphapp.c:904
PTA * pixaCentroids(PIXA *pixa)
pixaCentroids()
Definition: morphapp.c:1478
PIX * pixMorphGradient(PIX *pixs, l_int32 hsize, l_int32 vsize, l_int32 smoothing)
pixMorphGradient()
Definition: morphapp.c:1424
PIX * pixExtractBoundary(PIX *pixs, l_int32 type)
pixExtractBoundary()
Definition: morphapp.c:111
PIX * pixIntersectionOfMorphOps(PIX *pixs, SELA *sela, l_int32 type)
pixIntersectionOfMorphOps()
Definition: morphapp.c:558
l_ok pixRemoveMatchedPattern(PIX *pixs, PIX *pixp, PIX *pixe, l_int32 x0, l_int32 y0, l_int32 dsize)
pixRemoveMatchedPattern()
Definition: morphapp.c:687
PIX * pixMorphSequenceByRegion(PIX *pixs, PIX *pixm, const char *sequence, l_int32 connectivity, l_int32 minw, l_int32 minh, BOXA **pboxa)
pixMorphSequenceByRegion()
Definition: morphapp.c:351
PIX * pixDisplayMatchedPattern(PIX *pixs, PIX *pixp, PIX *pixe, l_int32 x0, l_int32 y0, l_uint32 color, l_float32 scale, l_int32 nlevels)
pixDisplayMatchedPattern()
Definition: morphapp.c:792
PIX * pixTophat(PIX *pixs, l_int32 hsize, l_int32 vsize, l_int32 type)
pixTophat()
Definition: morphapp.c:1206
PIXA * pixaMorphSequenceByComponent(PIXA *pixas, const char *sequence, l_int32 minw, l_int32 minh)
pixaMorphSequenceByComponent()
Definition: morphapp.c:268
PIX * pixFastTophat(PIX *pixs, l_int32 xsize, l_int32 ysize, l_int32 type)
pixFastTophat()
Definition: morphapp.c:1362
PIX * pixSeedfillMorph(PIX *pixs, PIX *pixm, l_int32 maxiters, l_int32 connectivity)
pixSeedfillMorph()
Definition: morphapp.c:1044
l_ok pixCentroid(PIX *pix, l_int32 *centtab, l_int32 *sumtab, l_float32 *pxave, l_float32 *pyave)
pixCentroid()
Definition: morphapp.c:1533
PIX * pixMorphSequenceMasked(PIX *pixs, PIX *pixm, const char *sequence, l_int32 dispsep)
pixMorphSequenceMasked()
Definition: morphapp.c:151
PIX * pixUnionOfMorphOps(PIX *pixs, SELA *sela, l_int32 type)
pixUnionOfMorphOps()
Definition: morphapp.c:505
PIXA * pixaMorphSequenceByRegion(PIX *pixs, PIXA *pixam, const char *sequence, l_int32 minw, l_int32 minh)
pixaMorphSequenceByRegion()
Definition: morphapp.c:430
PIX * pixMorphSequenceByComponent(PIX *pixs, const char *sequence, l_int32 connectivity, l_int32 minw, l_int32 minh, BOXA **pboxa)
pixMorphSequenceByComponent()
Definition: morphapp.c:198
PIX * pixMorphCompSequence(PIX *pixs, const char *sequence, l_int32 dispsep)
pixMorphCompSequence()
Definition: morphseq.c:304
PIX * pixMorphSequence(PIX *pixs, const char *sequence, l_int32 dispsep)
pixMorphSequence()
Definition: morphseq.c:137
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:478
l_ok numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:719
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:658
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
l_ok pixSetMaskedCmap(PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_int32 rval, l_int32 gval, l_int32 bval)
pixSetMaskedCmap()
Definition: paintcmap.c:698
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
Definition: pix1.c:1699
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
l_int32 pixSizesEqual(const PIX *pix1, const PIX *pix2)
pixSizesEqual()
Definition: pix1.c:1985
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:383
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
l_ok pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:817
l_ok pixSetPadBits(PIX *pix, l_int32 val)
pixSetPadBits()
Definition: pix2.c:1382
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2820
PIX * pixAddBorder(PIX *pixs, l_int32 npix, l_uint32 val)
pixAddBorder()
Definition: pix2.c:1823
PIX * pixOr(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixOr()
Definition: pix3.c:1560
l_int32 * makePixelSumTab8(void)
makePixelSumTab8()
Definition: pix3.c:2411
l_ok pixCountPixels(PIX *pixs, l_int32 *pcount, l_int32 *tab8)
pixCountPixels()
Definition: pix3.c:1937
PIX * pixAnd(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixAnd()
Definition: pix3.c:1624
l_int32 * makePixelCentroidTab8(void)
makePixelCentroidTab8()
Definition: pix3.c:2451
l_ok pixCombineMasked(PIX *pixd, PIX *pixs, PIX *pixm)
pixCombineMasked()
Definition: pix3.c:382
PIX * pixInvert(PIX *pixd, PIX *pixs)
pixInvert()
Definition: pix3.c:1509
PIX * pixXor(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixXor()
Definition: pix3.c:1688
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:1026
#define PIX_DST
Definition: pix.h:331
@ L_COPY
Definition: pix.h:712
@ L_CLONE
Definition: pix.h:713
@ L_INSERT
Definition: pix.h:711
#define PIX_PAINT
Definition: pix.h:336
#define PIX_SRC
Definition: pix.h:330
#define PIX_NOT(op)
Definition: pix.h:332
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 pixaVerifyDepth(PIXA *pixa, l_int32 *psame, l_int32 *pmaxd)
pixaVerifyDepth()
Definition: pixabasic.c:960
l_int32 pixaGetBoxaCount(PIXA *pixa)
pixaGetBoxaCount()
Definition: pixabasic.c:784
BOX * pixaGetBox(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetBox()
Definition: pixabasic.c:816
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
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:650
l_ok pixaAddBox(PIXA *pixa, BOX *box, l_int32 copyflag)
pixaAddBox()
Definition: pixabasic.c:555
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:691
l_ok pixaIsFull(PIXA *pixa, l_int32 *pfullpa, l_int32 *pfullba)
pixaIsFull()
Definition: pixabasic.c:1057
l_ok pixaGetBoxGeometry(PIXA *pixa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
pixaGetBoxGeometry()
Definition: pixabasic.c:854
BOXA * pixaGetBoxa(PIXA *pixa, l_int32 accesstype)
pixaGetBoxa()
Definition: pixabasic.c:760
PIXA * pixaCopy(PIXA *pixa, l_int32 copyflag)
pixaCopy()
Definition: pixabasic.c:453
l_ok pixaGetDepthInfo(PIXA *pixa, l_int32 *pmaxdepth, l_int32 *psame)
pixaGetDepthInfo()
Definition: pixafunc1.c:2884
PIX * pixSubtractGray(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixSubtractGray()
Definition: pixarith.c:357
l_ok pixAddConstantGray(PIX *pixs, l_int32 val)
pixAddConstantGray()
Definition: pixarith.c:119
PIX * pixConvert1To4(PIX *pixd, PIX *pixs, l_int32 val0, l_int32 val1)
pixConvert1To4()
Definition: pixconv.c:2280
l_ok ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:578
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:120
l_ok ptaAddPt(PTA *pta, l_float32 x, l_float32 y)
ptaAddPt()
Definition: ptabasic.c:343
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:195
l_ok pixRasterop(PIX *pixd, l_int32 dx, l_int32 dy, l_int32 dw, l_int32 dh, l_int32 op, PIX *pixs, l_int32 sx, l_int32 sy)
pixRasterop()
Definition: rop.c:204
PIX * pixScaleBySampling(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleBySampling()
Definition: scale1.c:1338
PIX * pixScaleToSize(PIX *pixs, l_int32 wd, l_int32 hd)
pixScaleToSize()
Definition: scale1.c:323
PIX * pixScaleToGray(PIX *pixs, l_float32 scalefactor)
pixScaleToGray()
Definition: scale2.c:208
PIX * pixScaleGrayMinMax(PIX *pixs, l_int32 xfact, l_int32 yfact, l_int32 type)
pixScaleGrayMinMax()
Definition: scale2.c:1019
PIX * pixHolesByFilling(PIX *pixs, l_int32 connectivity)
pixHolesByFilling()
Definition: seedfill.c:609
l_ok pixSeedfillGray(PIX *pixs, PIX *pixm, l_int32 connectivity)
pixSeedfillGray()
Definition: seedfill.c:929
SEL * selaGetSel(SELA *sela, l_int32 i)
selaGetSel()
Definition: sel1.c:662
void selDestroy(SEL **psel)
selDestroy()
Definition: sel1.c:340
l_ok selSetElement(SEL *sel, l_int32 row, l_int32 col, l_int32 type)
selSetElement()
Definition: sel1.c:819
SEL * selCopy(SEL *sel)
selCopy()
Definition: sel1.c:371
l_int32 selaGetCount(SELA *sela)
selaGetCount()
Definition: sel1.c:637
SEL * selCreateBrick(l_int32 h, l_int32 w, l_int32 cy, l_int32 cx, l_int32 type)
selCreateBrick()
Definition: sel1.c:418
Definition: pix.h:481
Definition: pix.h:492
Definition: array.h:71
l_float32 * array
Definition: array.h:77
Definition: pix.h:139
Definition: pix.h:456
Definition: pix.h:517
Definition: morph.h:74
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306