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