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. */
78static const l_int32 DefaultDistanceToBoundary = 1;
79static const l_int32 MaxDistanceToBoundary = 4;
80
81 /* Default min runlength to accept a hit or miss element located
82 * at its center */
83static const l_int32 DefaultMinRunlength = 3;
84
85 /* Default scalefactor for displaying image and hit-miss sel
86 * that is derived from it */
87static const l_int32 DefaultSelScalefactor = 7;
88static 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 *-----------------------------------------------------------------*/
147SEL *
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{
159l_int32 ws, hs, w, h, x, y, xval, yval, i, j, nh, nm;
160l_float32 delh, delw;
161NUMA *nah, *nam;
162PIX *pixt1, *pixt2, *pixfg, *pixbg;
163PTA *ptah, *ptam;
164SEL *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
337SEL *
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{
348l_int32 ws, hs, w, h, x, y, i, j, thresh;
349l_uint32 val;
350PIX *pixt1, *pixt2, *pixfg, *pixbg;
351SEL *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
490SEL *
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{
502l_int32 ws, hs, w, h, x, y, ix, iy, i, npt;
503PIX *pixt1, *pixt2, *pixt3, *pixfg, *pixbg;
504SEL *selh, *selm, *sel_3, *sel;
505PTA *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 *-----------------------------------------------------------------*/
637NUMA *
639 l_int32 x,
640 l_int32 y,
641 l_int32 minlength)
642{
643l_int32 w, h, i, r, nruns, len;
644NUMA *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
709NUMA *
711 l_int32 x1,
712 l_int32 y1,
713 l_int32 x2,
714 l_int32 y2)
715{
716l_int32 w, h, x, y, npts;
717l_int32 i, runlen, preval;
718l_uint32 val;
719NUMA *numa;
720PTA *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 *-----------------------------------------------------------------*/
804PTA *
806 l_int32 skip)
807{
808l_int32 x, y, xn, yn, xs, ys, xa, ya, count;
809PIX *pixt;
810PTA *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
871l_int32
873 l_int32 x,
874 l_int32 y,
875 l_int32 *pxa,
876 l_int32 *pya)
877{
878l_int32 w, h, i, xa, ya, found;
879l_int32 xdel[] = {-1, 0, 1, 0, -1, 1, 1, -1};
880l_int32 ydel[] = {0, 1, 0, -1, 1, 1, -1, -1};
881l_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 *-----------------------------------------------------------------*/
929PIX *
931 SEL *sel,
932 l_int32 scalefactor,
933 l_uint32 hitcolor,
934 l_uint32 misscolor)
935{
936l_int32 i, j, type;
937l_float32 fscale;
938PIX *pixt, *pixd;
939PIXCMAP *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 * pixDilate(PIX *pixd, PIX *pixs, SEL *sel)
pixDilate()
Definition: morph.c:213
PIX * pixErode(PIX *pixd, PIX *pixs, SEL *sel)
pixErode()
Definition: morph.c:267
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:478
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
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
Definition: pix1.c:1699
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
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
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:120
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
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
PIX * pixDisplayHitMissSel(PIX *pixs, SEL *sel, l_int32 scalefactor, l_uint32 hitcolor, l_uint32 misscolor)
pixDisplayHitMissSel()
Definition: selgen.c:930
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
NUMA * pixGetRunsOnLine(PIX *pixs, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2)
pixGetRunsOnLine()
Definition: selgen.c:710
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
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
PTA * pixSubsampleBoundaryPixels(PIX *pixs, l_int32 skip)
pixSubsampleBoundaryPixels()
Definition: selgen.c:805
l_int32 adjacentOnPixelInRaster(PIX *pixs, l_int32 x, l_int32 y, l_int32 *pxa, l_int32 *pya)
adjacentOnPixelInRaster()
Definition: selgen.c:872
NUMA * pixGetRunCentersOnLine(PIX *pixs, l_int32 x, l_int32 y, l_int32 minlength)
pixGetRunCentersOnLine()
Definition: selgen.c:638
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