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