Leptonica  1.77.0
Image processing and image analysis suite
selgen.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 
70 #include "allheaders.h"
71 
72 
73  /* default minimum distance of a hit-miss pixel element to
74  * a boundary pixel of its color. */
75 static const l_int32 DEFAULT_DISTANCE_TO_BOUNDARY = 1;
76 static const l_int32 MAX_DISTANCE_TO_BOUNDARY = 4;
77 
78  /* default min runlength to accept a hit or miss element located
79  * at its center */
80 static const l_int32 DEFAULT_MIN_RUNLENGTH = 3;
81 
82 
83  /* default scalefactor for displaying image and hit-miss sel
84  * that is derived from it */
85 static const l_int32 DEFAULT_SEL_SCALEFACTOR = 7;
86 static const l_int32 MAX_SEL_SCALEFACTOR = 31; /* should be big enough */
87 
88 #ifndef NO_CONSOLE_IO
89 #define DEBUG_DISPLAY_HM_SEL 0
90 #endif /* ~NO_CONSOLE_IO */
91 
92 
93 /*-----------------------------------------------------------------*
94  * Generate a subsampled structuring element *
95  *-----------------------------------------------------------------*/
145 SEL *
147  l_int32 nhlines,
148  l_int32 nvlines,
149  l_int32 distance,
150  l_int32 minlength,
151  l_int32 toppix,
152  l_int32 botpix,
153  l_int32 leftpix,
154  l_int32 rightpix,
155  PIX **ppixe)
156 {
157 l_int32 ws, hs, w, h, x, y, xval, yval, i, j, nh, nm;
158 l_float32 delh, delw;
159 NUMA *nah, *nam;
160 PIX *pixt1, *pixt2, *pixfg, *pixbg;
161 PTA *ptah, *ptam;
162 SEL *seld, *sel;
163 
164  PROCNAME("pixGenerateSelWithRuns");
165 
166  if (ppixe) *ppixe = NULL;
167  if (!pixs)
168  return (SEL *)ERROR_PTR("pixs not defined", procName, NULL);
169  if (pixGetDepth(pixs) != 1)
170  return (SEL *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
171  if (nhlines < 1 && nvlines < 1)
172  return (SEL *)ERROR_PTR("nvlines and nhlines both < 1", procName, NULL);
173 
174  if (distance <= 0)
175  distance = DEFAULT_DISTANCE_TO_BOUNDARY;
176  if (minlength <= 0)
177  minlength = DEFAULT_MIN_RUNLENGTH;
178  if (distance > MAX_DISTANCE_TO_BOUNDARY) {
179  L_WARNING("distance too large; setting to max value\n", procName);
180  distance = MAX_DISTANCE_TO_BOUNDARY;
181  }
182 
183  /* Locate the foreground */
184  pixClipToForeground(pixs, &pixt1, NULL);
185  if (!pixt1)
186  return (SEL *)ERROR_PTR("pixt1 not made", procName, NULL);
187  ws = pixGetWidth(pixt1);
188  hs = pixGetHeight(pixt1);
189  w = ws;
190  h = hs;
191 
192  /* Crop out a region including the foreground, and add pixels
193  * on sides depending on the side flags */
194  if (toppix || botpix || leftpix || rightpix) {
195  x = y = 0;
196  if (toppix) {
197  h += toppix;
198  y = toppix;
199  if (toppix < distance + minlength)
200  L_WARNING("no miss elements in added top pixels\n", procName);
201  }
202  if (botpix) {
203  h += botpix;
204  if (botpix < distance + minlength)
205  L_WARNING("no miss elements in added bot pixels\n", procName);
206  }
207  if (leftpix) {
208  w += leftpix;
209  x = leftpix;
210  if (leftpix < distance + minlength)
211  L_WARNING("no miss elements in added left pixels\n", procName);
212  }
213  if (rightpix) {
214  w += rightpix;
215  if (rightpix < distance + minlength)
216  L_WARNING("no miss elements in added right pixels\n", procName);
217  }
218  pixt2 = pixCreate(w, h, 1);
219  pixRasterop(pixt2, x, y, ws, hs, PIX_SRC, pixt1, 0, 0);
220  } else {
221  pixt2 = pixClone(pixt1);
222  }
223  if (ppixe)
224  *ppixe = pixClone(pixt2);
225  pixDestroy(&pixt1);
226 
227  /* Identify fg and bg pixels that are at least 'distance' pixels
228  * away from the boundary pixels in their set */
229  seld = selCreateBrick(2 * distance + 1, 2 * distance + 1,
230  distance, distance, SEL_HIT);
231  pixfg = pixErode(NULL, pixt2, seld);
232  pixbg = pixDilate(NULL, pixt2, seld);
233  pixInvert(pixbg, pixbg);
234  selDestroy(&seld);
235  pixDestroy(&pixt2);
236 
237  /* Accumulate hit and miss points */
238  ptah = ptaCreate(0);
239  ptam = ptaCreate(0);
240  if (nhlines >= 1) {
241  delh = (l_float32)h / (l_float32)(nhlines + 1);
242  for (i = 0, y = 0; i < nhlines; i++) {
243  y += (l_int32)(delh + 0.5);
244  nah = pixGetRunCentersOnLine(pixfg, -1, y, minlength);
245  nam = pixGetRunCentersOnLine(pixbg, -1, y, minlength);
246  nh = numaGetCount(nah);
247  nm = numaGetCount(nam);
248  for (j = 0; j < nh; j++) {
249  numaGetIValue(nah, j, &xval);
250  ptaAddPt(ptah, xval, y);
251  }
252  for (j = 0; j < nm; j++) {
253  numaGetIValue(nam, j, &xval);
254  ptaAddPt(ptam, xval, y);
255  }
256  numaDestroy(&nah);
257  numaDestroy(&nam);
258  }
259  }
260  if (nvlines >= 1) {
261  delw = (l_float32)w / (l_float32)(nvlines + 1);
262  for (i = 0, x = 0; i < nvlines; i++) {
263  x += (l_int32)(delw + 0.5);
264  nah = pixGetRunCentersOnLine(pixfg, x, -1, minlength);
265  nam = pixGetRunCentersOnLine(pixbg, x, -1, minlength);
266  nh = numaGetCount(nah);
267  nm = numaGetCount(nam);
268  for (j = 0; j < nh; j++) {
269  numaGetIValue(nah, j, &yval);
270  ptaAddPt(ptah, x, yval);
271  }
272  for (j = 0; j < nm; j++) {
273  numaGetIValue(nam, j, &yval);
274  ptaAddPt(ptam, x, yval);
275  }
276  numaDestroy(&nah);
277  numaDestroy(&nam);
278  }
279  }
280 
281  /* Make the Sel with those points */
282  sel = selCreateBrick(h, w, h / 2, w / 2, SEL_DONT_CARE);
283  nh = ptaGetCount(ptah);
284  for (i = 0; i < nh; i++) {
285  ptaGetIPt(ptah, i, &x, &y);
286  selSetElement(sel, y, x, SEL_HIT);
287  }
288  nm = ptaGetCount(ptam);
289  for (i = 0; i < nm; i++) {
290  ptaGetIPt(ptam, i, &x, &y);
291  selSetElement(sel, y, x, SEL_MISS);
292  }
293 
294  pixDestroy(&pixfg);
295  pixDestroy(&pixbg);
296  ptaDestroy(&ptah);
297  ptaDestroy(&ptam);
298  return sel;
299 }
300 
301 
335 SEL *
337  l_float32 hitfract,
338  l_float32 missfract,
339  l_int32 distance,
340  l_int32 toppix,
341  l_int32 botpix,
342  l_int32 leftpix,
343  l_int32 rightpix,
344  PIX **ppixe)
345 {
346 l_int32 ws, hs, w, h, x, y, i, j, thresh;
347 l_uint32 val;
348 PIX *pixt1, *pixt2, *pixfg, *pixbg;
349 SEL *seld, *sel;
350 
351  PROCNAME("pixGenerateSelRandom");
352 
353  if (ppixe) *ppixe = NULL;
354  if (!pixs)
355  return (SEL *)ERROR_PTR("pixs not defined", procName, NULL);
356  if (pixGetDepth(pixs) != 1)
357  return (SEL *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
358  if (hitfract <= 0.0 && missfract <= 0.0)
359  return (SEL *)ERROR_PTR("no hits or misses", procName, NULL);
360  if (hitfract > 1.0 || missfract > 1.0)
361  return (SEL *)ERROR_PTR("fraction can't be > 1.0", procName, NULL);
362 
363  if (distance <= 0)
364  distance = DEFAULT_DISTANCE_TO_BOUNDARY;
365  if (distance > MAX_DISTANCE_TO_BOUNDARY) {
366  L_WARNING("distance too large; setting to max value\n", procName);
367  distance = MAX_DISTANCE_TO_BOUNDARY;
368  }
369 
370  /* Locate the foreground */
371  pixClipToForeground(pixs, &pixt1, NULL);
372  if (!pixt1)
373  return (SEL *)ERROR_PTR("pixt1 not made", procName, NULL);
374  ws = pixGetWidth(pixt1);
375  hs = pixGetHeight(pixt1);
376  w = ws;
377  h = hs;
378 
379  /* Crop out a region including the foreground, and add pixels
380  * on sides depending on the side flags */
381  if (toppix || botpix || leftpix || rightpix) {
382  x = y = 0;
383  if (toppix) {
384  h += toppix;
385  y = toppix;
386  }
387  if (botpix)
388  h += botpix;
389  if (leftpix) {
390  w += leftpix;
391  x = leftpix;
392  }
393  if (rightpix)
394  w += rightpix;
395  pixt2 = pixCreate(w, h, 1);
396  pixRasterop(pixt2, x, y, ws, hs, PIX_SRC, pixt1, 0, 0);
397  } else {
398  pixt2 = pixClone(pixt1);
399  }
400  if (ppixe)
401  *ppixe = pixClone(pixt2);
402  pixDestroy(&pixt1);
403 
404  /* Identify fg and bg pixels that are at least 'distance' pixels
405  * away from the boundary pixels in their set */
406  seld = selCreateBrick(2 * distance + 1, 2 * distance + 1,
407  distance, distance, SEL_HIT);
408  pixfg = pixErode(NULL, pixt2, seld);
409  pixbg = pixDilate(NULL, pixt2, seld);
410  pixInvert(pixbg, pixbg);
411  selDestroy(&seld);
412  pixDestroy(&pixt2);
413 
414  /* Generate the sel from a random selection of these points */
415  sel = selCreateBrick(h, w, h / 2, w / 2, SEL_DONT_CARE);
416  if (hitfract > 0.0) {
417  thresh = (l_int32)(hitfract * (l_float64)RAND_MAX);
418  for (i = 0; i < h; i++) {
419  for (j = 0; j < w; j++) {
420  pixGetPixel(pixfg, j, i, &val);
421  if (val) {
422  if (rand() < thresh)
423  selSetElement(sel, i, j, SEL_HIT);
424  }
425  }
426  }
427  }
428  if (missfract > 0.0) {
429  thresh = (l_int32)(missfract * (l_float64)RAND_MAX);
430  for (i = 0; i < h; i++) {
431  for (j = 0; j < w; j++) {
432  pixGetPixel(pixbg, j, i, &val);
433  if (val) {
434  if (rand() < thresh)
435  selSetElement(sel, i, j, SEL_MISS);
436  }
437  }
438  }
439  }
440 
441  pixDestroy(&pixfg);
442  pixDestroy(&pixbg);
443  return sel;
444 }
445 
446 
488 SEL *
490  l_int32 hitdist,
491  l_int32 missdist,
492  l_int32 hitskip,
493  l_int32 missskip,
494  l_int32 topflag,
495  l_int32 botflag,
496  l_int32 leftflag,
497  l_int32 rightflag,
498  PIX **ppixe)
499 {
500 l_int32 ws, hs, w, h, x, y, ix, iy, i, npt;
501 PIX *pixt1, *pixt2, *pixt3, *pixfg, *pixbg;
502 SEL *selh, *selm, *sel_3, *sel;
503 PTA *ptah, *ptam;
504 
505  PROCNAME("pixGenerateSelBoundary");
506 
507  if (ppixe) *ppixe = NULL;
508  if (!pixs)
509  return (SEL *)ERROR_PTR("pixs not defined", procName, NULL);
510  if (pixGetDepth(pixs) != 1)
511  return (SEL *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
512  if (hitdist < 0 || hitdist > 4 || missdist < 0 || missdist > 4)
513  return (SEL *)ERROR_PTR("dist not in {0 .. 4}", procName, NULL);
514  if (hitskip < 0 && missskip < 0)
515  return (SEL *)ERROR_PTR("no hits or misses", procName, NULL);
516 
517  /* Locate the foreground */
518  pixClipToForeground(pixs, &pixt1, NULL);
519  if (!pixt1)
520  return (SEL *)ERROR_PTR("pixt1 not made", procName, NULL);
521  ws = pixGetWidth(pixt1);
522  hs = pixGetHeight(pixt1);
523  w = ws;
524  h = hs;
525 
526  /* Crop out a region including the foreground, and add pixels
527  * on sides depending on the side flags */
528  if (topflag || botflag || leftflag || rightflag) {
529  x = y = 0;
530  if (topflag) {
531  h += missdist + 1;
532  y = missdist + 1;
533  }
534  if (botflag)
535  h += missdist + 1;
536  if (leftflag) {
537  w += missdist + 1;
538  x = missdist + 1;
539  }
540  if (rightflag)
541  w += missdist + 1;
542  pixt2 = pixCreate(w, h, 1);
543  pixRasterop(pixt2, x, y, ws, hs, PIX_SRC, pixt1, 0, 0);
544  } else {
545  pixt2 = pixClone(pixt1);
546  }
547  if (ppixe)
548  *ppixe = pixClone(pixt2);
549  pixDestroy(&pixt1);
550 
551  /* Identify fg and bg pixels that are exactly hitdist and
552  * missdist (rsp) away from the boundary pixels in their set.
553  * Then get a subsampled set of these points. */
554  sel_3 = selCreateBrick(3, 3, 1, 1, SEL_HIT);
555  if (hitskip >= 0) {
556  selh = selCreateBrick(2 * hitdist + 1, 2 * hitdist + 1,
557  hitdist, hitdist, SEL_HIT);
558  pixt3 = pixErode(NULL, pixt2, selh);
559  pixfg = pixErode(NULL, pixt3, sel_3);
560  pixXor(pixfg, pixfg, pixt3);
561  ptah = pixSubsampleBoundaryPixels(pixfg, hitskip);
562  pixDestroy(&pixt3);
563  pixDestroy(&pixfg);
564  selDestroy(&selh);
565  }
566  if (missskip >= 0) {
567  selm = selCreateBrick(2 * missdist + 1, 2 * missdist + 1,
568  missdist, missdist, SEL_HIT);
569  pixt3 = pixDilate(NULL, pixt2, selm);
570  pixbg = pixDilate(NULL, pixt3, sel_3);
571  pixXor(pixbg, pixbg, pixt3);
572  ptam = pixSubsampleBoundaryPixels(pixbg, missskip);
573  pixDestroy(&pixt3);
574  pixDestroy(&pixbg);
575  selDestroy(&selm);
576  }
577  selDestroy(&sel_3);
578  pixDestroy(&pixt2);
579 
580  /* Generate the hit-miss sel from these point */
581  sel = selCreateBrick(h, w, h / 2, w / 2, SEL_DONT_CARE);
582  if (hitskip >= 0) {
583  npt = ptaGetCount(ptah);
584  for (i = 0; i < npt; i++) {
585  ptaGetIPt(ptah, i, &ix, &iy);
586  selSetElement(sel, iy, ix, SEL_HIT);
587  }
588  }
589  if (missskip >= 0) {
590  npt = ptaGetCount(ptam);
591  for (i = 0; i < npt; i++) {
592  ptaGetIPt(ptam, i, &ix, &iy);
593  selSetElement(sel, iy, ix, SEL_MISS);
594  }
595  }
596 
597  ptaDestroy(&ptah);
598  ptaDestroy(&ptam);
599  return sel;
600 }
601 
602 
603 /*-----------------------------------------------------------------*
604  * Accumulate data on runs along lines *
605  *-----------------------------------------------------------------*/
635 NUMA *
637  l_int32 x,
638  l_int32 y,
639  l_int32 minlength)
640 {
641 l_int32 w, h, i, r, nruns, len;
642 NUMA *naruns, *nad;
643 
644  PROCNAME("pixGetRunCentersOnLine");
645 
646  if (!pixs)
647  return (NUMA *)ERROR_PTR("pixs not defined", procName, NULL);
648  if (pixGetDepth(pixs) != 1)
649  return (NUMA *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
650  if (x != -1 && y != -1)
651  return (NUMA *)ERROR_PTR("x or y must be -1", procName, NULL);
652  if (x == -1 && y == -1)
653  return (NUMA *)ERROR_PTR("x or y cannot both be -1", procName, NULL);
654 
655  if ((nad = numaCreate(0)) == NULL)
656  return (NUMA *)ERROR_PTR("nad not made", procName, NULL);
657  w = pixGetWidth(pixs);
658  h = pixGetHeight(pixs);
659  if (x == -1) { /* horizontal run */
660  if (y < 0 || y >= h)
661  return nad;
662  naruns = pixGetRunsOnLine(pixs, 0, y, w - 1, y);
663  } else { /* vertical run */
664  if (x < 0 || x >= w)
665  return nad;
666  naruns = pixGetRunsOnLine(pixs, x, 0, x, h - 1);
667  }
668  nruns = numaGetCount(naruns);
669 
670  /* extract run center values; the first run is always bg */
671  r = 0; /* cumulative distance along line */
672  for (i = 0; i < nruns; i++) {
673  if (i % 2 == 0) { /* bg run */
674  numaGetIValue(naruns, i, &len);
675  r += len;
676  continue;
677  } else {
678  numaGetIValue(naruns, i, &len);
679  if (len >= minlength)
680  numaAddNumber(nad, r + len / 2);
681  r += len;
682  }
683  }
684 
685  numaDestroy(&naruns);
686  return nad;
687 }
688 
689 
707 NUMA *
709  l_int32 x1,
710  l_int32 y1,
711  l_int32 x2,
712  l_int32 y2)
713 {
714 l_int32 w, h, x, y, npts;
715 l_int32 i, runlen, preval;
716 l_uint32 val;
717 NUMA *numa;
718 PTA *pta;
719 
720  PROCNAME("pixGetRunsOnLine");
721 
722  if (!pixs)
723  return (NUMA *)ERROR_PTR("pixs not defined", procName, NULL);
724  if (pixGetDepth(pixs) != 1)
725  return (NUMA *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
726 
727  w = pixGetWidth(pixs);
728  h = pixGetHeight(pixs);
729  if (x1 < 0 || x1 >= w)
730  return (NUMA *)ERROR_PTR("x1 not valid", procName, NULL);
731  if (x2 < 0 || x2 >= w)
732  return (NUMA *)ERROR_PTR("x2 not valid", procName, NULL);
733  if (y1 < 0 || y1 >= h)
734  return (NUMA *)ERROR_PTR("y1 not valid", procName, NULL);
735  if (y2 < 0 || y2 >= h)
736  return (NUMA *)ERROR_PTR("y2 not valid", procName, NULL);
737 
738  if ((pta = generatePtaLine(x1, y1, x2, y2)) == NULL)
739  return (NUMA *)ERROR_PTR("pta not made", procName, NULL);
740  if ((npts = ptaGetCount(pta)) == 0) {
741  ptaDestroy(&pta);
742  return (NUMA *)ERROR_PTR("pta has no pts", procName, NULL);
743  }
744  if ((numa = numaCreate(0)) == NULL) {
745  ptaDestroy(&pta);
746  return (NUMA *)ERROR_PTR("numa not made", procName, NULL);
747  }
748 
749  for (i = 0; i < npts; i++) {
750  ptaGetIPt(pta, i, &x, &y);
751  pixGetPixel(pixs, x, y, &val);
752  if (i == 0) {
753  if (val == 1) { /* black pixel; append white run of size 0 */
754  numaAddNumber(numa, 0);
755  }
756  preval = val;
757  runlen = 1;
758  continue;
759  }
760  if (val == preval) { /* extend current run */
761  preval = val;
762  runlen++;
763  } else { /* end previous run */
764  numaAddNumber(numa, runlen);
765  preval = val;
766  runlen = 1;
767  }
768  }
769  numaAddNumber(numa, runlen); /* append last run */
770 
771  ptaDestroy(&pta);
772  return numa;
773 }
774 
775 
776 /*-----------------------------------------------------------------*
777  * Subsample boundary pixels in relatively ordered way *
778  *-----------------------------------------------------------------*/
802 PTA *
804  l_int32 skip)
805 {
806 l_int32 x, y, xn, yn, xs, ys, xa, ya, count;
807 PIX *pixt;
808 PTA *pta;
809 
810  PROCNAME("pixSubsampleBoundaryPixels");
811 
812  if (!pixs)
813  return (PTA *)ERROR_PTR("pixs not defined", procName, NULL);
814  if (pixGetDepth(pixs) != 1)
815  return (PTA *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
816  if (skip < 0)
817  return (PTA *)ERROR_PTR("skip < 0", procName, NULL);
818 
819  if (skip == 0)
820  return ptaGetPixelsFromPix(pixs, NULL);
821 
822  pta = ptaCreate(0);
823  pixt = pixCopy(NULL, pixs);
824  xs = ys = 0;
825  while (nextOnPixelInRaster(pixt, xs, ys, &xn, &yn)) { /* new series */
826  xs = xn;
827  ys = yn;
828 
829  /* Add first point in this series */
830  ptaAddPt(pta, xs, ys);
831 
832  /* Trace out boundary, erasing all and saving every (skip + 1)th */
833  x = xs;
834  y = ys;
835  pixSetPixel(pixt, x, y, 0);
836  count = 0;
837  while (adjacentOnPixelInRaster(pixt, x, y, &xa, &ya)) {
838  x = xa;
839  y = ya;
840  pixSetPixel(pixt, x, y, 0);
841  if (count == skip) {
842  ptaAddPt(pta, x, y);
843  count = 0;
844  } else {
845  count++;
846  }
847  }
848  }
849 
850  pixDestroy(&pixt);
851  return pta;
852 }
853 
854 
869 l_int32
871  l_int32 x,
872  l_int32 y,
873  l_int32 *pxa,
874  l_int32 *pya)
875 {
876 l_int32 w, h, i, xa, ya, found;
877 l_int32 xdel[] = {-1, 0, 1, 0, -1, 1, 1, -1};
878 l_int32 ydel[] = {0, 1, 0, -1, 1, 1, -1, -1};
879 l_uint32 val;
880 
881  PROCNAME("adjacentOnPixelInRaster");
882 
883  if (!pixs)
884  return ERROR_INT("pixs not defined", procName, 0);
885  if (pixGetDepth(pixs) != 1)
886  return ERROR_INT("pixs not 1 bpp", procName, 0);
887  w = pixGetWidth(pixs);
888  h = pixGetHeight(pixs);
889  found = 0;
890  for (i = 0; i < 8; i++) {
891  xa = x + xdel[i];
892  ya = y + ydel[i];
893  if (xa < 0 || xa >= w || ya < 0 || ya >= h)
894  continue;
895  pixGetPixel(pixs, xa, ya, &val);
896  if (val == 1) {
897  found = 1;
898  *pxa = xa;
899  *pya = ya;
900  break;
901  }
902  }
903  return found;
904 }
905 
906 
907 
908 /*-----------------------------------------------------------------*
909  * Display generated sel with originating image *
910  *-----------------------------------------------------------------*/
927 PIX *
929  SEL *sel,
930  l_int32 scalefactor,
931  l_uint32 hitcolor,
932  l_uint32 misscolor)
933 {
934 l_int32 i, j, type;
935 l_float32 fscale;
936 PIX *pixt, *pixd;
937 PIXCMAP *cmap;
938 
939  PROCNAME("pixDisplayHitMissSel");
940 
941  if (!pixs)
942  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
943  if (pixGetDepth(pixs) != 1)
944  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
945  if (!sel)
946  return (PIX *)ERROR_PTR("sel not defined", procName, NULL);
947 
948  if (scalefactor <= 0)
949  scalefactor = DEFAULT_SEL_SCALEFACTOR;
950  if (scalefactor > MAX_SEL_SCALEFACTOR) {
951  L_WARNING("scalefactor too large; using max value\n", procName);
952  scalefactor = MAX_SEL_SCALEFACTOR;
953  }
954 
955  /* Generate a version of pixs with a colormap */
956  pixt = pixConvert1To8(NULL, pixs, 0, 1);
957  cmap = pixcmapCreate(8);
958  pixcmapAddColor(cmap, 255, 255, 255);
959  pixcmapAddColor(cmap, 0, 0, 0);
960  pixcmapAddColor(cmap, hitcolor >> 24, (hitcolor >> 16) & 0xff,
961  (hitcolor >> 8) & 0xff);
962  pixcmapAddColor(cmap, misscolor >> 24, (misscolor >> 16) & 0xff,
963  (misscolor >> 8) & 0xff);
964  pixSetColormap(pixt, cmap);
965 
966  /* Color the hits and misses */
967  for (i = 0; i < sel->sy; i++) {
968  for (j = 0; j < sel->sx; j++) {
969  selGetElement(sel, i, j, &type);
970  if (type == SEL_DONT_CARE)
971  continue;
972  if (type == SEL_HIT)
973  pixSetPixel(pixt, j, i, 2);
974  else /* type == SEL_MISS */
975  pixSetPixel(pixt, j, i, 3);
976  }
977  }
978 
979  /* Scale it up */
980  fscale = (l_float32)scalefactor;
981  pixd = pixScaleBySampling(pixt, fscale, fscale);
982 
983  pixDestroy(&pixt);
984  return pixd;
985 }
NUMA * pixGetRunsOnLine(PIX *pixs, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2)
pixGetRunsOnLine()
Definition: selgen.c:708
PTA * pixSubsampleBoundaryPixels(PIX *pixs, l_int32 skip)
pixSubsampleBoundaryPixels()
Definition: selgen.c:803
l_ok ptaAddPt(PTA *pta, l_float32 x, l_float32 y)
ptaAddPt()
Definition: ptabasic.c:342
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:473
l_int32 nextOnPixelInRaster(PIX *pixs, l_int32 xstart, l_int32 ystart, l_int32 *px, l_int32 *py)
nextOnPixelInRaster()
Definition: conncomp.c:453
l_ok pixRasterop(PIX *pixd, l_int32 dx, l_int32 dy, l_int32 dw, l_int32 dh, l_int32 op, PIX *pixs, l_int32 sx, l_int32 sy)
pixRasterop()
Definition: rop.c:193
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:116
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:302
PIX * pixInvert(PIX *pixd, PIX *pixs)
pixInvert()
Definition: pix3.c:1395
SEL * pixGenerateSelRandom(PIX *pixs, l_float32 hitfract, l_float32 missfract, l_int32 distance, l_int32 toppix, l_int32 botpix, l_int32 leftpix, l_int32 rightpix, PIX **ppixe)
pixGenerateSelRandom()
Definition: selgen.c:336
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:187
l_int32 ptaGetCount(PTA *pta)
ptaGetCount()
Definition: ptabasic.c:504
l_int32 sy
Definition: morph.h:64
PIX * pixScaleBySampling(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleBySampling()
Definition: scale1.c:1338
SEL * pixGenerateSelBoundary(PIX *pixs, l_int32 hitdist, l_int32 missdist, l_int32 hitskip, l_int32 missskip, l_int32 topflag, l_int32 botflag, l_int32 leftflag, l_int32 rightflag, PIX **ppixe)
pixGenerateSelBoundary()
Definition: selgen.c:489
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
Definition: pix1.c:1573
PIX * pixErode(PIX *pixd, PIX *pixs, SEL *sel)
pixErode()
Definition: morph.c:263
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
Definition: colormap.c:111
l_ok pixClipToForeground(PIX *pixs, PIX **ppixd, BOX **pbox)
pixClipToForeground()
Definition: pix5.c:1660
l_ok selGetElement(SEL *sel, l_int32 row, l_int32 col, l_int32 *ptype)
selGetElement()
Definition: sel1.c:781
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:727
Definition: array.h:59
PIX * pixXor(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixXor()
Definition: pix3.c:1574
PTA * generatePtaLine(l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2)
generatePtaLine()
Definition: graphics.c:138
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:631
l_int32 sx
Definition: morph.h:65
void selDestroy(SEL **psel)
selDestroy()
Definition: sel1.c:337
l_ok pixSetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 val)
pixSetPixel()
Definition: pix2.c:253
NUMA * pixGetRunCentersOnLine(PIX *pixs, l_int32 x, l_int32 y, l_int32 minlength)
pixGetRunCentersOnLine()
Definition: selgen.c:636
SEL * selCreateBrick(l_int32 h, l_int32 w, l_int32 cy, l_int32 cx, l_int32 type)
selCreateBrick()
Definition: sel1.c:418
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:515
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
PIX * pixDisplayHitMissSel(PIX *pixs, SEL *sel, l_int32 scalefactor, l_uint32 hitcolor, l_uint32 misscolor)
pixDisplayHitMissSel()
Definition: selgen.c:928
SEL * pixGenerateSelWithRuns(PIX *pixs, l_int32 nhlines, l_int32 nvlines, l_int32 distance, l_int32 minlength, l_int32 toppix, l_int32 botpix, l_int32 leftpix, l_int32 rightpix, PIX **ppixe)
pixGenerateSelWithRuns()
Definition: selgen.c:146
l_int32 adjacentOnPixelInRaster(PIX *pixs, l_int32 x, l_int32 y, l_int32 *pxa, l_int32 *pya)
adjacentOnPixelInRaster()
Definition: selgen.c:870
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:360
l_ok pixGetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 *pval)
pixGetPixel()
Definition: pix2.c:180
Definition: pix.h:134
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:192
#define PIX_SRC
Definition: pix.h:327
PIX * pixCopy(PIX *pixd, PIX *pixs)
pixCopy()
Definition: pix1.c:628
PIX * pixConvert1To8(PIX *pixd, PIX *pixs, l_uint8 val0, l_uint8 val1)
pixConvert1To8()
Definition: pixconv.c:2366
l_ok ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:555
PIX * pixDilate(PIX *pixd, PIX *pixs, SEL *sel)
pixDilate()
Definition: morph.c:209
PTA * ptaGetPixelsFromPix(PIX *pixs, BOX *box)
ptaGetPixelsFromPix()
Definition: ptafunc1.c:1908
l_ok pixcmapAddColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapAddColor()
Definition: colormap.c:341
Definition: pix.h:517
l_ok selSetElement(SEL *sel, l_int32 row, l_int32 col, l_int32 type)
selSetElement()
Definition: sel1.c:821