Leptonica  1.83.1
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 #include "array_internal.h"
92 
93 #define SWAP(x, y) {temp = (x); (x) = (y); (y) = temp;}
94 
95 /*-----------------------------------------------------------------*
96  * Extraction of boundary pixels *
97  *-----------------------------------------------------------------*/
111 PIX *
113  l_int32 type)
114 {
115 PIX *pixd;
116 
117  if (!pixs)
118  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
119 
120  if (type == 0)
121  pixd = pixDilateBrick(NULL, pixs, 3, 3);
122  else
123  pixd = pixErodeBrick(NULL, pixs, 3, 3);
124  pixXor(pixd, pixd, pixs);
125  return pixd;
126 }
127 
128 
129 /*-----------------------------------------------------------------*
130  * Selective morph sequence operation under mask *
131  *-----------------------------------------------------------------*/
149 PIX *
151  PIX *pixm,
152  const char *sequence,
153  l_int32 dispsep)
154 {
155 PIX *pixd;
156 
157  if (!pixs)
158  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
159  if (!sequence)
160  return (PIX *)ERROR_PTR("sequence not defined", __func__, 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  if (!pixs)
208  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
209  if (!sequence)
210  return (PIX *)ERROR_PTR("sequence not defined", __func__, NULL);
211 
212  if (minw <= 0) minw = 1;
213  if (minh <= 0) minh = 1;
214 
215  /* Get the c.c. */
216  if ((boxa = pixConnComp(pixs, &pixas, connectivity)) == NULL)
217  return (PIX *)ERROR_PTR("boxa not made", __func__, NULL);
218 
219  /* Operate on each c.c. independently */
220  pixad = pixaMorphSequenceByComponent(pixas, sequence, minw, minh);
221  pixaDestroy(&pixas);
222  boxaDestroy(&boxa);
223  if (!pixad)
224  return (PIX *)ERROR_PTR("pixad not made", __func__, NULL);
225 
226  /* Display the result out into pixd */
227  pixd = pixCreateTemplate(pixs);
228  n = pixaGetCount(pixad);
229  for (i = 0; i < n; i++) {
230  pixaGetBoxGeometry(pixad, i, &x, &y, &w, &h);
231  pix = pixaGetPix(pixad, i, L_CLONE);
232  pixRasterop(pixd, x, y, w, h, PIX_PAINT, pix, 0, 0);
233  pixDestroy(&pix);
234  }
235 
236  if (pboxa)
237  *pboxa = pixaGetBoxa(pixad, L_CLONE);
238  pixaDestroy(&pixad);
239  return pixd;
240 }
241 
242 
262 PIXA *
264  const char *sequence,
265  l_int32 minw,
266  l_int32 minh)
267 {
268 l_int32 n, i, w, h, d;
269 BOX *box;
270 PIX *pix1, *pix2;
271 PIXA *pixad;
272 
273  if (!pixas)
274  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
275  if ((n = pixaGetCount(pixas)) == 0)
276  return (PIXA *)ERROR_PTR("no pix in pixas", __func__, NULL);
277  if (n != pixaGetBoxaCount(pixas))
278  L_WARNING("boxa size != n\n", __func__);
279  pixaGetPixDimensions(pixas, 0, NULL, NULL, &d);
280  if (d != 1)
281  return (PIXA *)ERROR_PTR("depth not 1 bpp", __func__, NULL);
282 
283  if (!sequence)
284  return (PIXA *)ERROR_PTR("sequence not defined", __func__, NULL);
285  if (minw <= 0) minw = 1;
286  if (minh <= 0) minh = 1;
287 
288  if ((pixad = pixaCreate(n)) == NULL)
289  return (PIXA *)ERROR_PTR("pixad not made", __func__, NULL);
290  for (i = 0; i < n; i++) {
291  pixaGetPixDimensions(pixas, i, &w, &h, NULL);
292  if (w >= minw && h >= minh) {
293  if ((pix1 = pixaGetPix(pixas, i, L_CLONE)) == NULL) {
294  pixaDestroy(&pixad);
295  return (PIXA *)ERROR_PTR("pix1 not found", __func__, NULL);
296  }
297  if ((pix2 = pixMorphCompSequence(pix1, sequence, 0)) == NULL) {
298  pixaDestroy(&pixad);
299  return (PIXA *)ERROR_PTR("pix2 not made", __func__, NULL);
300  }
301  pixaAddPix(pixad, pix2, L_INSERT);
302  box = pixaGetBox(pixas, i, L_COPY);
303  pixaAddBox(pixad, box, L_INSERT);
304  pixDestroy(&pix1);
305  }
306  }
307 
308  return pixad;
309 }
310 
311 
312 /*-----------------------------------------------------------------*
313  * Morph sequence operation on each region *
314  *-----------------------------------------------------------------*/
343 PIX *
345  PIX *pixm,
346  const char *sequence,
347  l_int32 connectivity,
348  l_int32 minw,
349  l_int32 minh,
350  BOXA **pboxa)
351 {
352 l_int32 n, i, x, y, w, h;
353 BOXA *boxa;
354 PIX *pix, *pixd;
355 PIXA *pixam, *pixad;
356 
357  if (pboxa) *pboxa = NULL;
358  if (!pixs)
359  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
360  if (!pixm)
361  return (PIX *)ERROR_PTR("pixm not defined", __func__, NULL);
362  if (pixGetDepth(pixs) != 1 || pixGetDepth(pixm) != 1)
363  return (PIX *)ERROR_PTR("pixs and pixm not both 1 bpp", __func__, NULL);
364  if (!sequence)
365  return (PIX *)ERROR_PTR("sequence not defined", __func__, NULL);
366 
367  if (minw <= 0) minw = 1;
368  if (minh <= 0) minh = 1;
369 
370  /* Get the c.c. of the mask */
371  if ((boxa = pixConnComp(pixm, &pixam, connectivity)) == NULL)
372  return (PIX *)ERROR_PTR("boxa not made", __func__, NULL);
373 
374  /* Operate on each region in pixs independently */
375  pixad = pixaMorphSequenceByRegion(pixs, pixam, sequence, minw, minh);
376  pixaDestroy(&pixam);
377  boxaDestroy(&boxa);
378  if (!pixad)
379  return (PIX *)ERROR_PTR("pixad not made", __func__, NULL);
380 
381  /* Display the result out into pixd */
382  pixd = pixCreateTemplate(pixs);
383  n = pixaGetCount(pixad);
384  for (i = 0; i < n; i++) {
385  pixaGetBoxGeometry(pixad, i, &x, &y, &w, &h);
386  pix = pixaGetPix(pixad, i, L_CLONE);
387  pixRasterop(pixd, x, y, w, h, PIX_PAINT, pix, 0, 0);
388  pixDestroy(&pix);
389  }
390 
391  if (pboxa)
392  *pboxa = pixaGetBoxa(pixad, L_CLONE);
393  pixaDestroy(&pixad);
394  return pixd;
395 }
396 
397 
420 PIXA *
422  PIXA *pixam,
423  const char *sequence,
424  l_int32 minw,
425  l_int32 minh)
426 {
427 l_int32 n, i, w, h, same, maxd, fullpa, fullba;
428 BOX *box;
429 PIX *pix1, *pix2, *pix3;
430 PIXA *pixad;
431 
432  if (!pixs)
433  return (PIXA *)ERROR_PTR("pixs not defined", __func__, NULL);
434  if (pixGetDepth(pixs) != 1)
435  return (PIXA *)ERROR_PTR("pixs not 1 bpp", __func__, NULL);
436  if (!sequence)
437  return (PIXA *)ERROR_PTR("sequence not defined", __func__, NULL);
438  if (!pixam)
439  return (PIXA *)ERROR_PTR("pixam not defined", __func__, NULL);
440  pixaVerifyDepth(pixam, &same, &maxd);
441  if (maxd != 1)
442  return (PIXA *)ERROR_PTR("mask depth not 1 bpp", __func__, NULL);
443  pixaIsFull(pixam, &fullpa, &fullba);
444  if (!fullpa || !fullba)
445  return (PIXA *)ERROR_PTR("missing comps in pixam", __func__, NULL);
446  n = pixaGetCount(pixam);
447  if (minw <= 0) minw = 1;
448  if (minh <= 0) minh = 1;
449 
450  if ((pixad = pixaCreate(n)) == NULL)
451  return (PIXA *)ERROR_PTR("pixad not made", __func__, NULL);
452 
453  /* Use the rectangle to remove the appropriate part of pixs;
454  * then AND with the mask component to get the actual fg
455  * of pixs that is under the mask component. */
456  for (i = 0; i < n; i++) {
457  pixaGetPixDimensions(pixam, i, &w, &h, NULL);
458  if (w >= minw && h >= minh) {
459  pix1 = pixaGetPix(pixam, i, L_CLONE);
460  box = pixaGetBox(pixam, i, L_COPY);
461  pix2 = pixClipRectangle(pixs, box, NULL);
462  pixAnd(pix2, pix2, pix1);
463  pix3 = pixMorphCompSequence(pix2, sequence, 0);
464  pixDestroy(&pix1);
465  pixDestroy(&pix2);
466  if (!pix3) {
467  boxDestroy(&box);
468  pixaDestroy(&pixad);
469  L_ERROR("pix3 not made in iter %d; aborting\n", __func__, i);
470  break;
471  }
472  pixaAddPix(pixad, pix3, L_INSERT);
473  pixaAddBox(pixad, box, L_INSERT);
474  }
475  }
476 
477  return pixad;
478 }
479 
480 
481 /*-----------------------------------------------------------------*
482  * Union and intersection of parallel composite operations *
483  *-----------------------------------------------------------------*/
493 PIX *
495  SELA *sela,
496  l_int32 type)
497 {
498 l_int32 n, i;
499 PIX *pixt, *pixd;
500 SEL *sel;
501 
502  if (!pixs || pixGetDepth(pixs) != 1)
503  return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", __func__, NULL);
504  if (!sela)
505  return (PIX *)ERROR_PTR("sela not defined", __func__, NULL);
506  n = selaGetCount(sela);
507  if (n == 0)
508  return (PIX *)ERROR_PTR("no sels in sela", __func__, NULL);
509  if (type != L_MORPH_DILATE && type != L_MORPH_ERODE &&
510  type != L_MORPH_OPEN && type != L_MORPH_CLOSE &&
511  type != L_MORPH_HMT)
512  return (PIX *)ERROR_PTR("invalid type", __func__, NULL);
513 
514  pixd = pixCreateTemplate(pixs);
515  for (i = 0; i < n; i++) {
516  sel = selaGetSel(sela, i);
517  if (type == L_MORPH_DILATE)
518  pixt = pixDilate(NULL, pixs, sel);
519  else if (type == L_MORPH_ERODE)
520  pixt = pixErode(NULL, pixs, sel);
521  else if (type == L_MORPH_OPEN)
522  pixt = pixOpen(NULL, pixs, sel);
523  else if (type == L_MORPH_CLOSE)
524  pixt = pixClose(NULL, pixs, sel);
525  else /* type == L_MORPH_HMT */
526  pixt = pixHMT(NULL, pixs, sel);
527  pixOr(pixd, pixd, pixt);
528  pixDestroy(&pixt);
529  }
530 
531  return pixd;
532 }
533 
534 
544 PIX *
546  SELA *sela,
547  l_int32 type)
548 {
549 l_int32 n, i;
550 PIX *pixt, *pixd;
551 SEL *sel;
552 
553  if (!pixs || pixGetDepth(pixs) != 1)
554  return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", __func__, NULL);
555  if (!sela)
556  return (PIX *)ERROR_PTR("sela not defined", __func__, NULL);
557  n = selaGetCount(sela);
558  if (n == 0)
559  return (PIX *)ERROR_PTR("no sels in sela", __func__, NULL);
560  if (type != L_MORPH_DILATE && type != L_MORPH_ERODE &&
561  type != L_MORPH_OPEN && type != L_MORPH_CLOSE &&
562  type != L_MORPH_HMT)
563  return (PIX *)ERROR_PTR("invalid type", __func__, NULL);
564 
565  pixd = pixCreateTemplate(pixs);
566  pixSetAll(pixd);
567  for (i = 0; i < n; i++) {
568  sel = selaGetSel(sela, i);
569  if (type == L_MORPH_DILATE)
570  pixt = pixDilate(NULL, pixs, sel);
571  else if (type == L_MORPH_ERODE)
572  pixt = pixErode(NULL, pixs, sel);
573  else if (type == L_MORPH_OPEN)
574  pixt = pixOpen(NULL, pixs, sel);
575  else if (type == L_MORPH_CLOSE)
576  pixt = pixClose(NULL, pixs, sel);
577  else /* type == L_MORPH_HMT */
578  pixt = pixHMT(NULL, pixs, sel);
579  pixAnd(pixd, pixd, pixt);
580  pixDestroy(&pixt);
581  }
582 
583  return pixd;
584 }
585 
586 
587 
588 /*-----------------------------------------------------------------*
589  * Selective connected component filling *
590  *-----------------------------------------------------------------*/
600 PIX *
602  l_int32 connectivity,
603  l_int32 minw,
604  l_int32 minh)
605 {
606 l_int32 n, i, x, y, w, h;
607 BOXA *boxa;
608 PIX *pix1, *pix2, *pixd;
609 PIXA *pixa;
610 
611  if (!pixs)
612  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
613  if (pixGetDepth(pixs) != 1)
614  return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, NULL);
615  if (minw <= 0) minw = 1;
616  if (minh <= 0) minh = 1;
617 
618  if ((boxa = pixConnComp(pixs, &pixa, connectivity)) == NULL)
619  return (PIX *)ERROR_PTR("boxa not made", __func__, NULL);
620  n = boxaGetCount(boxa);
621  pixd = pixCopy(NULL, pixs);
622  for (i = 0; i < n; i++) {
623  boxaGetBoxGeometry(boxa, i, &x, &y, &w, &h);
624  if (w >= minw && h >= minh) {
625  pix1 = pixaGetPix(pixa, i, L_CLONE);
626  if ((pix2 = pixHolesByFilling(pix1, 12 - connectivity)) == NULL) {
627  L_ERROR("pix2 not made in iter %d\n", __func__, i);
628  pixDestroy(&pix1);
629  continue;
630  }
631  pixRasterop(pixd, x, y, w, h, PIX_PAINT, pix2, 0, 0);
632  pixDestroy(&pix1);
633  pixDestroy(&pix2);
634  }
635  }
636  pixaDestroy(&pixa);
637  boxaDestroy(&boxa);
638 
639  return pixd;
640 }
641 
642 
643 /*-----------------------------------------------------------------*
644  * Removal of matched patterns *
645  *-----------------------------------------------------------------*/
669 l_ok
671  PIX *pixp,
672  PIX *pixe,
673  l_int32 x0,
674  l_int32 y0,
675  l_int32 dsize)
676 {
677 l_int32 i, nc, x, y, w, h, xb, yb;
678 BOXA *boxa;
679 PIX *pix1, *pix2;
680 PIXA *pixa;
681 PTA *pta;
682 SEL *sel;
683 
684  if (!pixs)
685  return ERROR_INT("pixs not defined", __func__, 1);
686  if (!pixp)
687  return ERROR_INT("pixp not defined", __func__, 1);
688  if (!pixe)
689  return ERROR_INT("pixe not defined", __func__, 1);
690  if (pixGetDepth(pixs) != 1 || pixGetDepth(pixp) != 1 ||
691  pixGetDepth(pixe) != 1)
692  return ERROR_INT("all input pix not 1 bpp", __func__, 1);
693  if (dsize < 0 || dsize > 4)
694  return ERROR_INT("dsize not in {0,1,2,3,4}", __func__, 1);
695 
696  /* Find the connected components and their centroids */
697  boxa = pixConnComp(pixe, &pixa, 8);
698  if ((nc = boxaGetCount(boxa)) == 0) {
699  L_WARNING("no matched patterns\n", __func__);
700  boxaDestroy(&boxa);
701  pixaDestroy(&pixa);
702  return 0;
703  }
704  pta = pixaCentroids(pixa);
705  pixaDestroy(&pixa);
706 
707  /* Optionally dilate the pattern, first adding a border that
708  * is large enough to accommodate the dilated pixels */
709  sel = NULL;
710  if (dsize > 0) {
711  sel = selCreateBrick(2 * dsize + 1, 2 * dsize + 1, dsize, dsize,
712  SEL_HIT);
713  pix1 = pixAddBorder(pixp, dsize, 0);
714  pix2 = pixDilate(NULL, pix1, sel);
715  selDestroy(&sel);
716  pixDestroy(&pix1);
717  } else {
718  pix2 = pixClone(pixp);
719  }
720 
721  /* Subtract out each dilated pattern. The centroid of each
722  * component is located at:
723  * (box->x + x, box->y + y)
724  * and the 'center' of the pattern used in making pixe is located at
725  * (x0 + dsize, (y0 + dsize)
726  * relative to the UL corner of the pattern. The center of the
727  * pattern is placed at the center of the component. */
728  pixGetDimensions(pix2, &w, &h, NULL);
729  for (i = 0; i < nc; i++) {
730  ptaGetIPt(pta, i, &x, &y);
731  boxaGetBoxGeometry(boxa, i, &xb, &yb, NULL, NULL);
732  pixRasterop(pixs, xb + x - x0 - dsize, yb + y - y0 - dsize,
733  w, h, PIX_DST & PIX_NOT(PIX_SRC), pix2, 0, 0);
734  }
735 
736  boxaDestroy(&boxa);
737  ptaDestroy(&pta);
738  pixDestroy(&pix2);
739  return 0;
740 }
741 
742 
743 /*-----------------------------------------------------------------*
744  * Display of matched patterns *
745  *-----------------------------------------------------------------*/
772 PIX *
774  PIX *pixp,
775  PIX *pixe,
776  l_int32 x0,
777  l_int32 y0,
778  l_uint32 color,
779  l_float32 scale,
780  l_int32 nlevels)
781 {
782 l_int32 i, nc, xb, yb, x, y, xi, yi, rval, gval, bval;
783 BOXA *boxa;
784 PIX *pixd, *pixt, *pixps;
785 PIXA *pixa;
786 PTA *pta;
787 PIXCMAP *cmap;
788 
789  if (!pixs)
790  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
791  if (!pixp)
792  return (PIX *)ERROR_PTR("pixp not defined", __func__, NULL);
793  if (!pixe)
794  return (PIX *)ERROR_PTR("pixe not defined", __func__, NULL);
795  if (pixGetDepth(pixs) != 1 || pixGetDepth(pixp) != 1 ||
796  pixGetDepth(pixe) != 1)
797  return (PIX *)ERROR_PTR("all input pix not 1 bpp", __func__, NULL);
798  if (scale > 1.0 || scale <= 0.0) {
799  L_WARNING("scale > 1.0 or < 0.0; setting to 1.0\n", __func__);
800  scale = 1.0;
801  }
802 
803  /* Find the connected components and their centroids */
804  boxa = pixConnComp(pixe, &pixa, 8);
805  if ((nc = boxaGetCount(boxa)) == 0) {
806  L_WARNING("no matched patterns\n", __func__);
807  boxaDestroy(&boxa);
808  pixaDestroy(&pixa);
809  return 0;
810  }
811  pta = pixaCentroids(pixa);
812 
813  extractRGBValues(color, &rval, &gval, &bval);
814  if (scale == 1.0) { /* output 4 bpp at full resolution */
815  pixd = pixConvert1To4(NULL, pixs, 0, 1);
816  cmap = pixcmapCreate(4);
817  pixcmapAddColor(cmap, 255, 255, 255);
818  pixcmapAddColor(cmap, 0, 0, 0);
819  pixSetColormap(pixd, cmap);
820 
821  /* Paint through pixp for each match location. The centroid of each
822  * component in pixe is located at:
823  * (box->x + x, box->y + y)
824  * and the 'center' of the pattern used in making pixe is located at
825  * (x0, y0)
826  * relative to the UL corner of the pattern. The center of the
827  * pattern is placed at the center of the component. */
828  for (i = 0; i < nc; i++) {
829  ptaGetIPt(pta, i, &x, &y);
830  boxaGetBoxGeometry(boxa, i, &xb, &yb, NULL, NULL);
831  pixSetMaskedCmap(pixd, pixp, xb + x - x0, yb + y - y0,
832  rval, gval, bval);
833  }
834  } else { /* output 4 bpp downscaled */
835  pixt = pixScaleToGray(pixs, scale);
836  pixd = pixThresholdTo4bpp(pixt, nlevels, 1);
837  pixps = pixScaleBySampling(pixp, scale, scale);
838 
839  for (i = 0; i < nc; i++) {
840  ptaGetIPt(pta, i, &x, &y);
841  boxaGetBoxGeometry(boxa, i, &xb, &yb, NULL, NULL);
842  xi = (l_int32)(scale * (xb + x - x0));
843  yi = (l_int32)(scale * (yb + y - y0));
844  pixSetMaskedCmap(pixd, pixps, xi, yi, rval, gval, bval);
845  }
846  pixDestroy(&pixt);
847  pixDestroy(&pixps);
848  }
849 
850  boxaDestroy(&boxa);
851  pixaDestroy(&pixa);
852  ptaDestroy(&pta);
853  return pixd;
854 }
855 
856 
857 /*------------------------------------------------------------------------*
858  * Extension of pixa by iterative erosion or dilation (and by scaling) *
859  *------------------------------------------------------------------------*/
882 PIXA *
884  l_int32 type,
885  l_int32 niters,
886  SEL *sel,
887  l_int32 include)
888 {
889 l_int32 maxdepth, i, j, n;
890 PIX *pix0, *pix1, *pix2;
891 SEL *selt;
892 PIXA *pixad;
893 
894  if (!pixas)
895  return (PIXA *)ERROR_PTR("pixas undefined", __func__, NULL);
896  if (niters <= 0) {
897  L_INFO("niters = %d; nothing to do\n", __func__, niters);
898  return pixaCopy(pixas, L_CLONE);
899  }
900  if (type != L_MORPH_DILATE && type != L_MORPH_ERODE)
901  return (PIXA *)ERROR_PTR("invalid type", __func__, NULL);
902  pixaGetDepthInfo(pixas, &maxdepth, NULL);
903  if (maxdepth > 1)
904  return (PIXA *)ERROR_PTR("some pix have bpp > 1", __func__, NULL);
905 
906  if (!sel)
907  selt = selCreateBrick(2, 2, 0, 0, SEL_HIT); /* default */
908  else
909  selt = selCopy(sel);
910  n = pixaGetCount(pixas);
911  pixad = pixaCreate(n * niters);
912  for (i = 0; i < n; i++) {
913  pix1 = pixaGetPix(pixas, i, L_CLONE);
914  if (include) pixaAddPix(pixad, pix1, L_COPY);
915  pix0 = pix1; /* need to keep the handle to destroy the clone */
916  for (j = 0; j < niters; j++) {
917  if (type == L_MORPH_DILATE) {
918  pix2 = pixDilate(NULL, pix1, selt);
919  } else { /* L_MORPH_ERODE */
920  pix2 = pixErode(NULL, pix1, selt);
921  }
922  pixaAddPix(pixad, pix2, L_INSERT);
923  pix1 = pix2; /* owned by pixad; do not destroy */
924  }
925  pixDestroy(&pix0);
926  }
927 
928  selDestroy(&selt);
929  return pixad;
930 }
931 
932 
952 PIXA *
954  NUMA *nasc,
955  l_int32 type,
956  l_int32 include)
957 {
958 l_int32 i, j, n, nsc, w, h, scalew, scaleh;
959 l_float32 scalefact;
960 PIX *pix1, *pix2;
961 PIXA *pixad;
962 
963  if (!pixas)
964  return (PIXA *)ERROR_PTR("pixas undefined", __func__, NULL);
965  if (!nasc || numaGetCount(nasc) == 0)
966  return (PIXA *)ERROR_PTR("nasc undefined or empty", __func__, NULL);
967  if (type != L_HORIZ && type != L_VERT && type != L_BOTH_DIRECTIONS)
968  return (PIXA *)ERROR_PTR("invalid type", __func__, NULL);
969 
970  n = pixaGetCount(pixas);
971  nsc = numaGetCount(nasc);
972  if ((pixad = pixaCreate(n * (nsc + 1))) == NULL) {
973  L_ERROR("pixad not made: n = %d, nsc = %d\n", __func__, n, nsc);
974  return NULL;
975  }
976  for (i = 0; i < n; i++) {
977  pix1 = pixaGetPix(pixas, i, L_CLONE);
978  if (include) pixaAddPix(pixad, pix1, L_COPY);
979  pixGetDimensions(pix1, &w, &h, NULL);
980  for (j = 0; j < nsc; j++) {
981  numaGetFValue(nasc, j, &scalefact);
982  scalew = w;
983  scaleh = h;
984  if (type == L_HORIZ || type == L_BOTH_DIRECTIONS)
985  scalew = w * scalefact;
986  if (type == L_VERT || type == L_BOTH_DIRECTIONS)
987  scaleh = h * scalefact;
988  pix2 = pixScaleToSize(pix1, scalew, scaleh);
989  pixaAddPix(pixad, pix2, L_INSERT);
990  }
991  pixDestroy(&pix1);
992  }
993  return pixad;
994 }
995 
996 
997 /*-----------------------------------------------------------------*
998  * Iterative morphological seed filling *
999  *-----------------------------------------------------------------*/
1018 PIX *
1020  PIX *pixm,
1021  l_int32 maxiters,
1022  l_int32 connectivity)
1023 {
1024 l_int32 same, i;
1025 PIX *pixt, *pixd, *temp;
1026 SEL *sel_3;
1027 
1028  if (!pixs || pixGetDepth(pixs) != 1)
1029  return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", __func__, NULL);
1030  if (!pixm)
1031  return (PIX *)ERROR_PTR("mask pix not defined", __func__, NULL);
1032  if (connectivity != 4 && connectivity != 8)
1033  return (PIX *)ERROR_PTR("connectivity not in {4,8}", __func__, NULL);
1034  if (maxiters <= 0) maxiters = 1000;
1035  if (pixSizesEqual(pixs, pixm) == 0)
1036  return (PIX *)ERROR_PTR("pix sizes unequal", __func__, NULL);
1037 
1038  if ((sel_3 = selCreateBrick(3, 3, 1, 1, SEL_HIT)) == NULL)
1039  return (PIX *)ERROR_PTR("sel_3 not made", __func__, NULL);
1040  if (connectivity == 4) { /* remove corner hits to make a '+' */
1041  selSetElement(sel_3, 0, 0, SEL_DONT_CARE);
1042  selSetElement(sel_3, 2, 2, SEL_DONT_CARE);
1043  selSetElement(sel_3, 2, 0, SEL_DONT_CARE);
1044  selSetElement(sel_3, 0, 2, SEL_DONT_CARE);
1045  }
1046 
1047  pixt = pixCopy(NULL, pixs);
1048  pixd = pixCreateTemplate(pixs);
1049  for (i = 1; i <= maxiters; i++) {
1050  pixDilate(pixd, pixt, sel_3);
1051  pixAnd(pixd, pixd, pixm);
1052  pixEqual(pixd, pixt, &same);
1053  if (same || i == maxiters)
1054  break;
1055  else
1056  SWAP(pixt, pixd);
1057  }
1058  lept_stderr(" Num iters in binary reconstruction = %d\n", i);
1059 
1060  pixDestroy(&pixt);
1061  selDestroy(&sel_3);
1062  return pixd;
1063 }
1064 
1065 
1066 /*-----------------------------------------------------------------*
1067  * Granulometry on binary images *
1068  *-----------------------------------------------------------------*/
1078 NUMA *
1080  l_int32 runtype,
1081  l_int32 direction,
1082  l_int32 maxsize)
1083 {
1084 l_int32 count, i, size;
1085 l_float32 val;
1086 NUMA *na, *nah;
1087 PIX *pix1, *pix2, *pix3;
1088 SEL *sel_2a;
1089 
1090  if (!pixs)
1091  return (NUMA *)ERROR_PTR("seed pix not defined", __func__, NULL);
1092  if (runtype != L_RUN_OFF && runtype != L_RUN_ON)
1093  return (NUMA *)ERROR_PTR("invalid run type", __func__, NULL);
1094  if (direction != L_HORIZ && direction != L_VERT)
1095  return (NUMA *)ERROR_PTR("direction not in {L_HORIZ, L_VERT}",
1096  __func__, NULL);
1097  if (pixGetDepth(pixs) != 1)
1098  return (NUMA *)ERROR_PTR("pixs must be binary", __func__, NULL);
1099 
1100  if (direction == L_HORIZ)
1101  sel_2a = selCreateBrick(1, 2, 0, 0, SEL_HIT);
1102  else /* direction == L_VERT */
1103  sel_2a = selCreateBrick(2, 1, 0, 0, SEL_HIT);
1104  if (!sel_2a)
1105  return (NUMA *)ERROR_PTR("sel_2a not made", __func__, NULL);
1106 
1107  if (runtype == L_RUN_OFF) {
1108  if ((pix1 = pixCopy(NULL, pixs)) == NULL) {
1109  selDestroy(&sel_2a);
1110  return (NUMA *)ERROR_PTR("pix1 not made", __func__, NULL);
1111  }
1112  pixInvert(pix1, pix1);
1113  } else { /* runtype == L_RUN_ON */
1114  pix1 = pixClone(pixs);
1115  }
1116 
1117  /* Get pixel counts at different stages of erosion */
1118  na = numaCreate(0);
1119  pix2 = pixCreateTemplate(pixs);
1120  pix3 = pixCreateTemplate(pixs);
1121  pixCountPixels(pix1, &count, NULL);
1122  numaAddNumber(na, count);
1123  pixErode(pix2, pix1, sel_2a);
1124  pixCountPixels(pix2, &count, NULL);
1125  numaAddNumber(na, count);
1126  for (i = 0; i < maxsize / 2; i++) {
1127  pixErode(pix3, pix2, sel_2a);
1128  pixCountPixels(pix3, &count, NULL);
1129  numaAddNumber(na, count);
1130  pixErode(pix2, pix3, sel_2a);
1131  pixCountPixels(pix2, &count, NULL);
1132  numaAddNumber(na, count);
1133  }
1134 
1135  /* Compute length histogram */
1136  size = numaGetCount(na);
1137  nah = numaCreate(size);
1138  numaAddNumber(nah, 0); /* number at length 0 */
1139  for (i = 1; i < size - 1; i++) {
1140  val = na->array[i+1] - 2 * na->array[i] + na->array[i-1];
1141  numaAddNumber(nah, val);
1142  }
1143 
1144  pixDestroy(&pix1);
1145  pixDestroy(&pix2);
1146  pixDestroy(&pix3);
1147  selDestroy(&sel_2a);
1148  numaDestroy(&na);
1149  return nah;
1150 }
1151 
1152 
1153 /*-----------------------------------------------------------------*
1154  * Composite operations on grayscale images *
1155  *-----------------------------------------------------------------*/
1176 PIX *
1178  l_int32 hsize,
1179  l_int32 vsize,
1180  l_int32 type)
1181 {
1182 PIX *pixt, *pixd;
1183 
1184  if (!pixs)
1185  return (PIX *)ERROR_PTR("seed pix not defined", __func__, NULL);
1186  if (pixGetDepth(pixs) != 8)
1187  return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
1188  if (hsize < 1 || vsize < 1)
1189  return (PIX *)ERROR_PTR("hsize or vsize < 1", __func__, NULL);
1190  if ((hsize & 1) == 0 ) {
1191  L_WARNING("horiz sel size must be odd; increasing by 1\n", __func__);
1192  hsize++;
1193  }
1194  if ((vsize & 1) == 0 ) {
1195  L_WARNING("vert sel size must be odd; increasing by 1\n", __func__);
1196  vsize++;
1197  }
1198  if (type != L_TOPHAT_WHITE && type != L_TOPHAT_BLACK)
1199  return (PIX *)ERROR_PTR("type must be L_TOPHAT_BLACK or L_TOPHAT_WHITE",
1200  __func__, NULL);
1201 
1202  if (hsize == 1 && vsize == 1)
1203  return pixCreateTemplate(pixs);
1204 
1205  switch (type)
1206  {
1207  case L_TOPHAT_WHITE:
1208  if ((pixt = pixOpenGray(pixs, hsize, vsize)) == NULL)
1209  return (PIX *)ERROR_PTR("pixt not made", __func__, NULL);
1210  pixd = pixSubtractGray(NULL, pixs, pixt);
1211  pixDestroy(&pixt);
1212  break;
1213  case L_TOPHAT_BLACK:
1214  if ((pixd = pixCloseGray(pixs, hsize, vsize)) == NULL)
1215  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
1216  pixSubtractGray(pixd, pixd, pixs);
1217  break;
1218  default:
1219  return (PIX *)ERROR_PTR("invalid type", __func__, NULL);
1220  }
1221 
1222  return pixd;
1223 }
1224 
1225 
1274 PIX *
1276  l_int32 height,
1277  l_int32 connectivity)
1278 {
1279 PIX *pixsd, *pixd;
1280 
1281  if (!pixs)
1282  return (PIX *)ERROR_PTR("src pix not defined", __func__, NULL);
1283  if (pixGetDepth(pixs) != 8)
1284  return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
1285  if (height < 0)
1286  return (PIX *)ERROR_PTR("height not >= 0", __func__, NULL);
1287  if (height == 0)
1288  return pixCreateTemplate(pixs);
1289 
1290  if ((pixsd = pixCopy(NULL, pixs)) == NULL)
1291  return (PIX *)ERROR_PTR("pixsd not made", __func__, NULL);
1292  pixAddConstantGray(pixsd, -height);
1293  pixSeedfillGray(pixsd, pixs, connectivity);
1294  pixd = pixSubtractGray(NULL, pixs, pixsd);
1295  pixDestroy(&pixsd);
1296  return pixd;
1297 }
1298 
1299 
1328 PIX *
1330  l_int32 xsize,
1331  l_int32 ysize,
1332  l_int32 type)
1333 {
1334 PIX *pix1, *pix2, *pix3, *pixd;
1335 
1336  if (!pixs)
1337  return (PIX *)ERROR_PTR("seed pix not defined", __func__, NULL);
1338  if (pixGetDepth(pixs) != 8)
1339  return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
1340  if (xsize < 1 || ysize < 1)
1341  return (PIX *)ERROR_PTR("size < 1", __func__, NULL);
1342  if (type != L_TOPHAT_WHITE && type != L_TOPHAT_BLACK)
1343  return (PIX *)ERROR_PTR("type must be L_TOPHAT_BLACK or L_TOPHAT_WHITE",
1344  __func__, NULL);
1345 
1346  if (xsize == 1 && ysize == 1)
1347  return pixCreateTemplate(pixs);
1348 
1349  switch (type)
1350  {
1351  case L_TOPHAT_WHITE:
1352  if ((pix1 = pixScaleGrayMinMax(pixs, xsize, ysize, L_CHOOSE_MIN))
1353  == NULL)
1354  return (PIX *)ERROR_PTR("pix1 not made", __func__, NULL);
1355  pix2 = pixBlockconv(pix1, 1, 1); /* small smoothing */
1356  pix3 = pixScaleBySampling(pix2, xsize, ysize);
1357  pixd = pixSubtractGray(NULL, pixs, pix3);
1358  pixDestroy(&pix3);
1359  break;
1360  case L_TOPHAT_BLACK:
1361  if ((pix1 = pixScaleGrayMinMax(pixs, xsize, ysize, L_CHOOSE_MAX))
1362  == NULL)
1363  return (PIX *)ERROR_PTR("pix1 not made", __func__, NULL);
1364  pix2 = pixBlockconv(pix1, 1, 1); /* small smoothing */
1365  pixd = pixScaleBySampling(pix2, xsize, ysize);
1366  pixSubtractGray(pixd, pixd, pixs);
1367  break;
1368  default:
1369  return (PIX *)ERROR_PTR("invalid type", __func__, NULL);
1370  }
1371 
1372  pixDestroy(&pix1);
1373  pixDestroy(&pix2);
1374  return pixd;
1375 }
1376 
1377 
1388 PIX *
1390  l_int32 hsize,
1391  l_int32 vsize,
1392  l_int32 smoothing)
1393 {
1394 PIX *pixg, *pixd;
1395 
1396  if (!pixs)
1397  return (PIX *)ERROR_PTR("seed pix not defined", __func__, NULL);
1398  if (pixGetDepth(pixs) != 8)
1399  return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
1400  if (hsize < 1 || vsize < 1)
1401  return (PIX *)ERROR_PTR("hsize or vsize < 1", __func__, NULL);
1402  if ((hsize & 1) == 0 ) {
1403  L_WARNING("horiz sel size must be odd; increasing by 1\n", __func__);
1404  hsize++;
1405  }
1406  if ((vsize & 1) == 0 ) {
1407  L_WARNING("vert sel size must be odd; increasing by 1\n", __func__);
1408  vsize++;
1409  }
1410 
1411  /* Optionally smooth first to remove noise.
1412  * If smoothing is 0, just get a copy */
1413  pixg = pixBlockconvGray(pixs, NULL, smoothing, smoothing);
1414 
1415  /* This gives approximately the gradient of a transition */
1416  pixd = pixDilateGray(pixg, hsize, vsize);
1417  pixSubtractGray(pixd, pixd, pixg);
1418  pixDestroy(&pixg);
1419  return pixd;
1420 }
1421 
1422 
1423 /*-----------------------------------------------------------------*
1424  * Centroid of component *
1425  *-----------------------------------------------------------------*/
1440 PTA *
1442 {
1443 l_int32 i, n;
1444 l_int32 *centtab = NULL;
1445 l_int32 *sumtab = NULL;
1446 l_float32 x, y;
1447 PIX *pix;
1448 PTA *pta;
1449 
1450  if (!pixa)
1451  return (PTA *)ERROR_PTR("pixa not defined", __func__, NULL);
1452  if ((n = pixaGetCount(pixa)) == 0)
1453  return (PTA *)ERROR_PTR("no pix in pixa", __func__, NULL);
1454 
1455  if ((pta = ptaCreate(n)) == NULL)
1456  return (PTA *)ERROR_PTR("pta not defined", __func__, NULL);
1457  centtab = makePixelCentroidTab8();
1458  sumtab = makePixelSumTab8();
1459 
1460  for (i = 0; i < n; i++) {
1461  pix = pixaGetPix(pixa, i, L_CLONE);
1462  if (pixCentroid(pix, centtab, sumtab, &x, &y) == 1)
1463  L_ERROR("centroid failure for pix %d\n", __func__, i);
1464  pixDestroy(&pix);
1465  ptaAddPt(pta, x, y);
1466  }
1467 
1468  LEPT_FREE(centtab);
1469  LEPT_FREE(sumtab);
1470  return pta;
1471 }
1472 
1473 
1493 l_ok
1495  l_int32 *centtab,
1496  l_int32 *sumtab,
1497  l_float32 *pxave,
1498  l_float32 *pyave)
1499 {
1500 l_int32 w, h, d, i, j, wpl, pixsum, rowsum, val;
1501 l_float32 xsum, ysum;
1502 l_uint32 *data, *line;
1503 l_uint32 word;
1504 l_uint8 byte;
1505 l_int32 *ctab, *stab;
1506 
1507  if (!pxave || !pyave)
1508  return ERROR_INT("&pxave and &pyave not defined", __func__, 1);
1509  *pxave = *pyave = 0.0;
1510  if (!pix)
1511  return ERROR_INT("pix not defined", __func__, 1);
1512  pixGetDimensions(pix, &w, &h, &d);
1513  if (d != 1 && d != 8)
1514  return ERROR_INT("pix not 1 or 8 bpp", __func__, 1);
1515 
1516  ctab = centtab;
1517  stab = sumtab;
1518  if (d == 1) {
1519  pixSetPadBits(pix, 0);
1520  if (!centtab)
1521  ctab = makePixelCentroidTab8();
1522  if (!sumtab)
1523  stab = makePixelSumTab8();
1524  }
1525 
1526  data = pixGetData(pix);
1527  wpl = pixGetWpl(pix);
1528  xsum = ysum = 0.0;
1529  pixsum = 0;
1530  if (d == 1) {
1531  for (i = 0; i < h; i++) {
1532  /* The body of this loop computes the sum of the set
1533  * (1) bits on this row, weighted by their distance
1534  * from the left edge of pix, and accumulates that into
1535  * xsum; it accumulates their distance from the top
1536  * edge of pix into ysum, and their total count into
1537  * pixsum. It's equivalent to
1538  * for (j = 0; j < w; j++) {
1539  * if (GET_DATA_BIT(line, j)) {
1540  * xsum += j;
1541  * ysum += i;
1542  * pixsum++;
1543  * }
1544  * }
1545  */
1546  line = data + wpl * i;
1547  rowsum = 0;
1548  for (j = 0; j < wpl; j++) {
1549  word = line[j];
1550  if (word) {
1551  byte = word & 0xff;
1552  rowsum += stab[byte];
1553  xsum += ctab[byte] + (j * 32 + 24) * stab[byte];
1554  byte = (word >> 8) & 0xff;
1555  rowsum += stab[byte];
1556  xsum += ctab[byte] + (j * 32 + 16) * stab[byte];
1557  byte = (word >> 16) & 0xff;
1558  rowsum += stab[byte];
1559  xsum += ctab[byte] + (j * 32 + 8) * stab[byte];
1560  byte = (word >> 24) & 0xff;
1561  rowsum += stab[byte];
1562  xsum += ctab[byte] + j * 32 * stab[byte];
1563  }
1564  }
1565  pixsum += rowsum;
1566  ysum += rowsum * i;
1567  }
1568  if (pixsum == 0) {
1569  L_WARNING("no ON pixels in pix\n", __func__);
1570  } else {
1571  *pxave = xsum / (l_float32)pixsum;
1572  *pyave = ysum / (l_float32)pixsum;
1573  }
1574  } else { /* d == 8 */
1575  for (i = 0; i < h; i++) {
1576  line = data + wpl * i;
1577  for (j = 0; j < w; j++) {
1578  val = GET_DATA_BYTE(line, j);
1579  xsum += val * j;
1580  ysum += val * i;
1581  pixsum += val;
1582  }
1583  }
1584  if (pixsum == 0) {
1585  L_WARNING("all pixels are 0\n", __func__);
1586  } else {
1587  *pxave = xsum / (l_float32)pixsum;
1588  *pyave = ysum / (l_float32)pixsum;
1589  }
1590  }
1591 
1592  if (d == 1) {
1593  if (!centtab) LEPT_FREE(ctab);
1594  if (!sumtab) LEPT_FREE(stab);
1595  }
1596  return 0;
1597 }
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:273
l_ok boxaGetBoxGeometry(BOXA *boxa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxaGetBoxGeometry()
Definition: boxbasic.c:796
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:519
l_int32 boxaGetCount(const BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:661
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
Definition: colormap.c:126
l_ok pixcmapAddColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapAddColor()
Definition: colormap.c:403
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:152
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:214
PIX * pixCloseGray(PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseGray()
Definition: graymorph.c:520
PIX * pixDilateGray(PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateGray()
Definition: graymorph.c:276
PIX * pixOpenGray(PIX *pixs, l_int32 hsize, l_int32 vsize)
pixOpenGray()
Definition: graymorph.c:390
PIX * pixThresholdTo4bpp(PIX *pixs, l_int32 nlevels, l_int32 cmapflag)
pixThresholdTo4bpp()
Definition: grayquant.c:1496
PIX * pixOpen(PIX *pixd, PIX *pixs, SEL *sel)
pixOpen()
Definition: morph.c:420
PIX * pixErode(PIX *pixd, PIX *pixs, SEL *sel)
pixErode()
Definition: morph.c:265
PIX * pixClose(PIX *pixd, PIX *pixs, SEL *sel)
pixClose()
Definition: morph.c:465
PIX * pixErodeBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeBrick()
Definition: morph.c:740
PIX * pixDilate(PIX *pixd, PIX *pixs, SEL *sel)
pixDilate()
Definition: morph.c:213
PIX * pixHMT(PIX *pixd, PIX *pixs, SEL *sel)
pixHMT()
Definition: morph.c:338
PIX * pixDilateBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateBrick()
Definition: morph.c:672
PIX * pixMorphGradient(PIX *pixs, l_int32 hsize, l_int32 vsize, l_int32 smoothing)
pixMorphGradient()
Definition: morphapp.c:1389
PIX * pixSeedfillMorph(PIX *pixs, PIX *pixm, l_int32 maxiters, l_int32 connectivity)
pixSeedfillMorph()
Definition: morphapp.c:1019
PTA * pixaCentroids(PIXA *pixa)
pixaCentroids()
Definition: morphapp.c:1441
l_ok pixRemoveMatchedPattern(PIX *pixs, PIX *pixp, PIX *pixe, l_int32 x0, l_int32 y0, l_int32 dsize)
pixRemoveMatchedPattern()
Definition: morphapp.c:670
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:773
PIX * pixMorphSequenceMasked(PIX *pixs, PIX *pixm, const char *sequence, l_int32 dispsep)
pixMorphSequenceMasked()
Definition: morphapp.c:150
PIX * pixSelectiveConnCompFill(PIX *pixs, l_int32 connectivity, l_int32 minw, l_int32 minh)
pixSelectiveConnCompFill()
Definition: morphapp.c:601
PIX * pixHDome(PIX *pixs, l_int32 height, l_int32 connectivity)
pixHDome()
Definition: morphapp.c:1275
PIXA * pixaExtendByScaling(PIXA *pixas, NUMA *nasc, l_int32 type, l_int32 include)
pixaExtendByScaling()
Definition: morphapp.c:953
PIX * pixMorphSequenceByRegion(PIX *pixs, PIX *pixm, const char *sequence, l_int32 connectivity, l_int32 minw, l_int32 minh, BOXA **pboxa)
pixMorphSequenceByRegion()
Definition: morphapp.c:344
PIX * pixTophat(PIX *pixs, l_int32 hsize, l_int32 vsize, l_int32 type)
pixTophat()
Definition: morphapp.c:1177
PIX * pixIntersectionOfMorphOps(PIX *pixs, SELA *sela, l_int32 type)
pixIntersectionOfMorphOps()
Definition: morphapp.c:545
l_ok pixCentroid(PIX *pix, l_int32 *centtab, l_int32 *sumtab, l_float32 *pxave, l_float32 *pyave)
pixCentroid()
Definition: morphapp.c:1494
PIX * pixUnionOfMorphOps(PIX *pixs, SELA *sela, l_int32 type)
pixUnionOfMorphOps()
Definition: morphapp.c:494
PIXA * pixaMorphSequenceByComponent(PIXA *pixas, const char *sequence, l_int32 minw, l_int32 minh)
pixaMorphSequenceByComponent()
Definition: morphapp.c:263
PIX * pixMorphSequenceByComponent(PIX *pixs, const char *sequence, l_int32 connectivity, l_int32 minw, l_int32 minh, BOXA **pboxa)
pixMorphSequenceByComponent()
Definition: morphapp.c:195
PIXA * pixaExtendByMorph(PIXA *pixas, l_int32 type, l_int32 niters, SEL *sel, l_int32 include)
pixaExtendByMorph()
Definition: morphapp.c:883
PIX * pixFastTophat(PIX *pixs, l_int32 xsize, l_int32 ysize, l_int32 type)
pixFastTophat()
Definition: morphapp.c:1329
PIXA * pixaMorphSequenceByRegion(PIX *pixs, PIXA *pixam, const char *sequence, l_int32 minw, l_int32 minh)
pixaMorphSequenceByRegion()
Definition: morphapp.c:421
NUMA * pixRunHistogramMorph(PIX *pixs, l_int32 runtype, l_int32 direction, l_int32 maxsize)
pixRunHistogramMorph()
Definition: morphapp.c:1079
PIX * pixExtractBoundary(PIX *pixs, l_int32 type)
pixExtractBoundary()
Definition: morphapp.c:112
PIX * pixMorphSequence(PIX *pixs, const char *sequence, l_int32 dispsep)
pixMorphSequence()
Definition: morphseq.c:137
PIX * pixMorphCompSequence(PIX *pixs, const char *sequence, l_int32 dispsep)
pixMorphCompSequence()
Definition: morphseq.c:302
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:460
l_ok numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:687
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:193
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:357
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:630
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:686
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1642
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
Definition: pix1.c:1582
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:608
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1074
l_int32 pixSizesEqual(const PIX *pix1, const PIX *pix2)
pixSizesEqual()
Definition: pix1.c:1878
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:689
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:380
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:582
PIX * pixAddBorder(PIX *pixs, l_int32 npix, l_uint32 val)
pixAddBorder()
Definition: pix2.c:1773
l_ok pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:799
l_ok pixSetPadBits(PIX *pix, l_int32 val)
pixSetPadBits()
Definition: pix2.c:1346
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2793
PIX * pixInvert(PIX *pixd, PIX *pixs)
pixInvert()
Definition: pix3.c:1481
l_ok pixCountPixels(PIX *pixs, l_int32 *pcount, l_int32 *tab8)
pixCountPixels()
Definition: pix3.c:1893
PIX * pixOr(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixOr()
Definition: pix3.c:1530
PIX * pixAnd(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixAnd()
Definition: pix3.c:1592
l_int32 * makePixelSumTab8(void)
makePixelSumTab8()
Definition: pix3.c:2354
PIX * pixXor(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixXor()
Definition: pix3.c:1654
l_int32 * makePixelCentroidTab8(void)
makePixelCentroidTab8()
Definition: pix3.c:2394
l_ok pixCombineMasked(PIX *pixd, PIX *pixs, PIX *pixm)
pixCombineMasked()
Definition: pix3.c:378
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:994
#define PIX_DST
Definition: pix.h:445
@ L_COPY
Definition: pix.h:505
@ L_CLONE
Definition: pix.h:506
@ L_INSERT
Definition: pix.h:504
#define PIX_PAINT
Definition: pix.h:450
#define PIX_SRC
Definition: pix.h:444
#define PIX_NOT(op)
Definition: pix.h:446
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:493
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:404
l_ok pixaVerifyDepth(PIXA *pixa, l_int32 *psame, l_int32 *pmaxd)
pixaVerifyDepth()
Definition: pixabasic.c:900
BOX * pixaGetBox(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetBox()
Definition: pixabasic.c:764
l_int32 pixaGetBoxaCount(PIXA *pixa)
pixaGetBoxaCount()
Definition: pixabasic.c:734
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:167
l_ok pixaGetPixDimensions(PIXA *pixa, l_int32 index, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixaGetPixDimensions()
Definition: pixabasic.c:680
PIXA * pixaCopy(PIXA *pixa, l_int32 copyflag)
pixaCopy()
Definition: pixabasic.c:442
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:629
l_ok pixaAddBox(PIXA *pixa, BOX *box, l_int32 copyflag)
pixaAddBox()
Definition: pixabasic.c:540
l_ok pixaIsFull(PIXA *pixa, l_int32 *pfullpa, l_int32 *pfullba)
pixaIsFull()
Definition: pixabasic.c:993
BOXA * pixaGetBoxa(PIXA *pixa, l_int32 accesstype)
pixaGetBoxa()
Definition: pixabasic.c:712
l_ok pixaGetBoxGeometry(PIXA *pixa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
pixaGetBoxGeometry()
Definition: pixabasic.c:800
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:647
l_ok pixaGetDepthInfo(PIXA *pixa, l_int32 *pmaxdepth, l_int32 *psame)
pixaGetDepthInfo()
Definition: pixafunc1.c:2799
l_ok pixAddConstantGray(PIX *pixs, l_int32 val)
pixAddConstantGray()
Definition: pixarith.c:119
PIX * pixSubtractGray(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixSubtractGray()
Definition: pixarith.c:351
PIX * pixConvert1To4(PIX *pixd, PIX *pixs, l_int32 val0, l_int32 val1)
pixConvert1To4()
Definition: pixconv.c:2228
l_ok ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:527
l_ok ptaAddPt(PTA *pta, l_float32 x, l_float32 y)
ptaAddPt()
Definition: ptabasic.c:328
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:120
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:191
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 * pixScaleToSize(PIX *pixs, l_int32 wd, l_int32 hd)
pixScaleToSize()
Definition: scale1.c:319
PIX * pixScaleBySampling(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleBySampling()
Definition: scale1.c:1306
PIX * pixScaleGrayMinMax(PIX *pixs, l_int32 xfact, l_int32 yfact, l_int32 type)
pixScaleGrayMinMax()
Definition: scale2.c:997
PIX * pixScaleToGray(PIX *pixs, l_float32 scalefactor)
pixScaleToGray()
Definition: scale2.c:208
PIX * pixHolesByFilling(PIX *pixs, l_int32 connectivity)
pixHolesByFilling()
Definition: seedfill.c:603
l_ok pixSeedfillGray(PIX *pixs, PIX *pixm, l_int32 connectivity)
pixSeedfillGray()
Definition: seedfill.c:911
SEL * selCopy(SEL *sel)
selCopy()
Definition: sel1.c:365
void selDestroy(SEL **psel)
selDestroy()
Definition: sel1.c:336
l_ok selSetElement(SEL *sel, l_int32 row, l_int32 col, l_int32 type)
selSetElement()
Definition: sel1.c:789
SEL * selaGetSel(SELA *sela, l_int32 i)
selaGetSel()
Definition: sel1.c:642
l_int32 selaGetCount(SELA *sela)
selaGetCount()
Definition: sel1.c:619
SEL * selCreateBrick(l_int32 h, l_int32 w, l_int32 cy, l_int32 cx, l_int32 type)
selCreateBrick()
Definition: sel1.c:410
l_float32 * array
Definition: morph.h:74
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306