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