Leptonica 1.82.0
Image processing and image analysis suite
colorfill.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
58#ifdef HAVE_CONFIG_H
59#include <config_auto.h>
60#endif /* HAVE_CONFIG_H */
61
62#include "allheaders.h"
63
64struct ColorEl {
65 l_int32 x;
66 l_int32 y;
67 l_uint32 color;
68};
69typedef struct ColorEl COLOREL;
70
71 /* Ignore pixels with smaller max component */
72static l_int32 DefaultMinMax = 70;
73
74 /* Static helpers */
75static COLOREL *colorelCreate(l_int32 x, l_int32 y, l_uint32 color);
76static void pixColorFillFromSeed(PIX *pixs, PIX *pixv, PTA **ppta,
77 l_int32 x, l_int32 y, L_QUEUE *lq,
78 l_int32 maxdiff, l_int32 minarea,
79 l_int32 debug);
80static void pixGetVisitedNeighbors(PIX *pixs, l_int32 x, l_int32 y,
81 l_uint32 *visited);
82static l_int32 findNextUnvisited(PIX *pixv, l_int32 *px, l_int32 *py);
83static l_int32 colorsAreSimilarForFill(l_uint32 val1, l_uint32 val2,
84 l_int32 maxdiff);
85static l_int32 pixelColorIsValid(l_uint32 val, l_int32 minmax);
86static l_int32 pixelIsOnColorBoundary(PIX *pixs, l_int32 x, l_int32 y);
87static l_int32 evalColorfillData(L_COLORFILL *cf, l_int32 debug);
88
89
90/*---------------------------------------------------------------------*
91 * Colorfill creation and destruction *
92 *---------------------------------------------------------------------*/
108 l_int32 nx,
109 l_int32 ny)
110{
111l_int32 i, j, w, h, tw, th, ntiles;
112BOX *box;
113BOXA *boxas;
114L_COLORFILL *cf;
115
116 PROCNAME("l_colorfillCreate");
117
118 if (!pixs)
119 return (L_COLORFILL *)ERROR_PTR("pixs not defined", procName, NULL);
120 if (pixGetDepth(pixs) != 32)
121 return (L_COLORFILL *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
122
123 pixGetDimensions(pixs, &w, &h, NULL);
124 tw = w / nx;
125 th = h / ny;
126 if (tw < 10 || th < 10)
127 return (L_COLORFILL *)ERROR_PTR("tile size too small", procName, NULL);
128 boxas = boxaCreate(nx * ny);
129 for (i = 0; i < ny; i++) {
130 for (j = 0; j < nx; j++) {
131 box = boxCreate(j * tw, i * th, tw, th);
132 boxaAddBox(boxas, box, L_INSERT);
133 }
134 }
135 ntiles = nx * ny;
136
137 cf = (L_COLORFILL *)LEPT_CALLOC(1, sizeof(L_COLORFILL));
138 cf->pixs = pixClone(pixs);
139 cf->nx = nx;
140 cf->ny = ny;
141 cf->tw = tw;
142 cf->th = th;
143 cf->boxas = boxas;
144 cf->naa = numaaCreate(ntiles);
145 cf->dnaa = l_dnaaCreate(ntiles);
146 cf->pixadb = pixaCreate(0);
147 return cf;
148}
149
150
157void
159{
160L_COLORFILL *cf;
161
162 PROCNAME("l_colorfillDestroy");
163
164 if (pcf == NULL) {
165 L_WARNING("ptr address is null!\n", procName);
166 return;
167 }
168
169 if ((cf = *pcf) == NULL)
170 return;
171
172 pixDestroy(&cf->pixs);
173 pixDestroy(&cf->pixst);
174 boxaDestroy(&cf->boxas);
175 pixaDestroy(&cf->pixas);
176 pixaDestroy(&cf->pixam);
177 numaaDestroy(&cf->naa);
178 l_dnaaDestroy(&cf->dnaa);
179 pixaDestroy(&cf->pixadb);
180 LEPT_FREE(cf);
181 *pcf = NULL;
182}
183
184
185/* ----------------------------------------------------------------------- *
186 * Determine color content using proximity. What do we get when *
187 * growing regions with nearly the same color? *
188 * ----------------------------------------------------------------------- */
225l_ok
227 l_int32 rref,
228 l_int32 gref,
229 l_int32 bref,
230 l_int32 minmax,
231 l_int32 maxdiff,
232 l_int32 minarea,
233 l_int32 smooth,
234 l_int32 debug)
235{
236l_int32 i, n;
237PIX *pix1, *pix2, *pix3;
238PIXA *pixas, *pixam;
239
240 PROCNAME("pixColorContentByLocation");
241
242 if (!cf)
243 return ERROR_INT("cf not defined", procName, 1);
244 if (minmax <= 0) minmax = DefaultMinMax;
245 if (minmax > 200)
246 return ERROR_INT("minmax > 200; unreasonably large", procName, 1);
247
248 /* Do the optional linear color map; this checks the ref vals
249 * and uses them if valid. Use {0,0,0} to skip this operation. */
250 if ((pix1 = pixColorShiftWhitePoint(cf->pixs, rref, gref, bref)) == NULL)
251 return ERROR_INT("pix1 not returned", procName, 1);
252 cf->pixst = pix1;
253
254 /* Break the image up into small tiles */
255 pixas = pixaCreateFromBoxa(pix1, cf->boxas, 0, 0, NULL);
256 cf->pixas = pixas;
257
258 /* Find regions of similar color in each tile */
259 n = pixaGetCount(pixas);
260 pixam = pixaCreate(n);
261 cf->pixam = pixam;
262 for (i = 0; i < n; i++) {
263 pix2 = pixaGetPix(pixas, i, L_COPY);
264 pix3 = pixColorFill(pix2, minmax, maxdiff, smooth, minarea, 0);
265 pixDestroy(&pix2);
266 pixaAddPix(pixam, pix3, L_INSERT);
267 }
268
269 /* Evaluate color components. Find the average color in each
270 * component and determine if there is more than one color in
271 * each of the tiles. */
272 evalColorfillData(cf, debug);
273
274 return 0;
275}
276
277
298PIX *
300 l_int32 minmax,
301 l_int32 maxdiff,
302 l_int32 smooth,
303 l_int32 minarea,
304 l_int32 debug)
305{
306l_int32 x, y, w, h, empty;
307l_uint32 val;
308L_KERNEL *kel;
309PIX *pixm, *pixm1, *pixv, *pixnc, *pixncd, *pixss, *pixf;
310PTA *pta1;
311L_QUEUE *lq;
312
313 PROCNAME("pixColorFill");
314
315 if (!pixs || pixGetDepth(pixs) != 32)
316 return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, NULL);
317
318 /* Set the non-color pixels to 0; generate a mask representing them */
319 pixGetDimensions(pixs, &w, &h, NULL);
320 pixnc = pixCreate(w, h, 1); /* mask for no color */
321 for (y = 0; y < h; y++) {
322 for (x = 0; x < w; x++) {
323 pixGetPixel(pixs, x, y, &val);
324 if (!pixelColorIsValid(val, minmax)) {
325 pixSetPixel(pixnc, x, y, 1);
326 pixSetPixel(pixs, x, y, 0x0);
327 }
328 }
329 }
330
331 /* Optionally, dilate the no-color mask */
332 pixncd = pixDilateBrick(NULL, pixnc, smooth, smooth);
333 pixDestroy(&pixnc);
334
335 /* Do a low-pass filter on pixs. This will make bad pixels
336 * near the zeroed non-color pixels, but any components made
337 * from these pixels will be removed at the end by the
338 * (optionally dilated) no-color mask. */
339 if (smooth > 1) {
340 kel = makeFlatKernel(smooth, smooth, smooth / 2, smooth / 2);
341 pixss = pixConvolveRGBSep(pixs, kel, kel);
342 kernelDestroy(&kel);
343 } else {
344 pixss = pixCopy(NULL, pixs);
345 }
346
347 /* Paint through everything under pixncd */
348 pixPaintThroughMask(pixss, pixncd, 0, 0, 0);
349
350 /* Find the color components */
351 pixv = pixCreate(w, h, 1); /* visited pixels */
352 pixOr(pixv, pixv, pixncd); /* consider non-color as visited */
353 pixSetBorderRingVal(pixv, 1, 1);
354 pixm = pixCreate(w, h, 1); /* color components */
355 lq = lqueueCreate(0);
356 x = y = 1; /* first row and column have been marked as visited */
357 while (findNextUnvisited(pixv, &x, &y) == 1) {
358 /* Flood fill this component, starting from (x,y) */
359 if (debug) lept_stderr("Start: x = %d, y = %d\n", x, y);
360 pixColorFillFromSeed(pixss, pixv, &pta1, x, y, lq, maxdiff,
361 minarea, debug);
362 if (pta1) { /* erode and add the pixels to pixm */
363 pixm1 = pixGenerateFromPta(pta1, w, h);
364 pixErodeBrick(pixm1, pixm1, 3, 3);
365 pixOr(pixm, pixm, pixm1);
366 pixDestroy(&pixm1);
367 ptaDestroy(&pta1);
368 }
369 }
370 pixDestroy(&pixv);
371
372 /* Remove everything under pixncd */
373 pixSubtract(pixm, pixm, pixncd);
374
375 /* Remove remaining small stuff */
376 pixf = pixSelectByArea(pixm, minarea, 4, L_SELECT_IF_GTE, NULL);
377
378 lqueueDestroy(&lq, 1);
379 pixDestroy(&pixncd);
380 pixDestroy(&pixss);
381 pixDestroy(&pixm);
382 return pixf;
383}
384
385
386/* ----------------------------------------------------------------------- *
387 * Generate data for testing *
388 * ----------------------------------------------------------------------- */
411PIXA *
413 l_int32 h,
414 l_int32 nseeds,
415 l_int32 range)
416{
417l_int32 i, j, x, y, rval, gval, bval, start, end;
418l_uint32 color;
419l_float64 dval;
420L_DNA *da;
421PIX *pix1, *pix2, *pix3, *pix4;
422PIXA *pixa;
423PTA *pta;
424PIXCMAP *cmap;
425
426 /* Generate data for seeds */
427 pta = ptaCreate(nseeds); /* for seed locations */
428 da = l_dnaCreate(nseeds); /* for colors */
429 srand(4);
430 start = 128 - range / 2;
431 end = 128 + (range - 1) / 2;
432 for (i = 0; i < nseeds; i++) {
433 genRandomIntOnInterval(0, w - 1, 0, &x);
434 genRandomIntOnInterval(0, h - 1, 0, &y);
435 ptaAddPt(pta, x, y);
436 genRandomIntOnInterval(start, end, 0, &rval);
437 genRandomIntOnInterval(start, end, 0, &gval);
438 genRandomIntOnInterval(start, end, 0, &bval);
439 composeRGBPixel(rval, gval, bval, &color);
440 l_dnaAddNumber(da, color);
441 }
442
443 /* Generate the 8 bpp seed image */
444 pix1 = pixCreate(w, h, 8);
445 for (i = 0; i < nseeds; i++) {
446 ptaGetIPt(pta, i, &x, &y);
447 pixSetPixel(pix1, x, y, i + 1); /* all seeds have non-zero values */
448 }
449
450 /* Spread seed values to all pixels that are nearest to
451 * the seed pixel from which they take their value. */
452 pix2 = pixSeedspread(pix1, 4);
453
454 /* Add a colormap for the random colors, using 0 for black */
455 cmap = pixcmapCreate(8);
456 pixcmapAddColor(cmap, 0, 0, 0);
457 for (i = 0; i < nseeds; i++) {
458 l_dnaGetDValue(da, i, &dval);
459 extractRGBValues(dval, &rval, &gval, &bval);
460 pixcmapAddColor(cmap, rval, gval, bval);
461 }
462 pixSetColormap(pix2, cmap);
463 pixDestroy(&pix1);
464 ptaDestroy(&pta);
465 l_dnaDestroy(&da);
466
467 /* Add to output; no black boundaries */
468 pixa = pixaCreate(0);
469 pixaAddPix(pixa, pix2, L_COPY);
470
471 /* Make pixels on the color boundaries black */
472 pix3 = pixCopy(NULL, pix2);
473 for (i = 0; i < h; i++) {
474 for (j = 0; j < w; j++) {
475 if (pixelIsOnColorBoundary(pix2, j, i))
476 pixSetPixel(pix3, j, i, 0); /* black */
477 }
478 }
479 pixaAddPix(pixa, pix3, L_INSERT);
480 pixDestroy(&pix2);
481
482 /* Have all the non-black regions be the same color */
483 cmap = pixcmapCreate(8);
484 pixcmapAddColor(cmap, 0, 0, 0);
485 for (i = 0; i < nseeds; i++)
486 pixcmapAddColor(cmap, rval, gval, bval);
487 pix4 = pixCopy(NULL, pix3);
488 pixSetColormap(pix4, cmap);
489 pixaAddPix(pixa, pix4, L_INSERT);
490
491 return pixa;
492}
493
494
495/* ----------------------------------------------------------------------- *
496 * Static helpers *
497 * ----------------------------------------------------------------------- */
498static COLOREL *
499colorelCreate(l_int32 x,
500 l_int32 y,
501 l_uint32 color)
502{
503COLOREL *el;
504
505 el = (COLOREL *)LEPT_CALLOC(1, sizeof(COLOREL));
506 el->x = x;
507 el->y = y;
508 el->color = color;
509 return el;
510}
511
536static void
538 PIX *pixv,
539 PTA **ppta,
540 l_int32 x,
541 l_int32 y,
542 L_QUEUE *lq,
543 l_int32 maxdiff,
544 l_int32 minarea,
545 l_int32 debug)
546{
547l_int32 w, h, np;
548l_uint32 visited[8]; /* W, N, E, S, NW, NE, SW, SE */
549l_uint32 color, val;
550COLOREL *el;
551PTA *pta;
552
553 /* Prime the queue with this pixel */
554 pixGetPixel(pixs, x, y, &val);
555 el = colorelCreate(x, y, val);
556 lqueueAdd(lq, el);
557 pixSetPixel(pixv, x, y, 1); /* visited */
558 pta = ptaCreate(0);
559 *ppta = pta;
560 ptaAddPt(pta, x, y);
561
562 /* Trace out the color component. Each pixel on the queue has
563 * a color. Pop from the queue and for each of its 8 neighbors,
564 * for those that have color:
565 * - If the pixel has a similar color, add to the pta array for
566 * the component, using the color of its parent.
567 * - Mark visited so that it will not be included in another
568 * component -- this effectively separates the growing component
569 * from all others. */
570 pixGetDimensions(pixs, &w, &h, NULL);
571 while (lqueueGetCount(lq) > 0) {
572 el = (COLOREL *)lqueueRemove(lq);
573 x = el->x;
574 y = el->y;
575 color = el->color;
576 LEPT_FREE(el);
577 pixGetVisitedNeighbors(pixv, x, y, visited);
578 if (!visited[0]) { /* check W */
579 pixGetPixel(pixs, x - 1, y, &val);
580 if (colorsAreSimilarForFill(color, val, maxdiff)) {
581 el = colorelCreate(x - 1, y, color);
582 lqueueAdd(lq, el);
583 ptaAddPt(pta, x - 1, y); /* added to component */
584 pixSetPixel(pixv, x - 1, y, 1); /* visited */
585 }
586 }
587 if (!visited[1]) { /* check N */
588 pixGetPixel(pixs, x, y - 1, &val);
589 if (colorsAreSimilarForFill(color, val, maxdiff)) {
590 el = colorelCreate(x, y - 1, color);
591 lqueueAdd(lq, el);
592 ptaAddPt(pta, x, y - 1);
593 pixSetPixel(pixv, x, y - 1, 1);
594 }
595 }
596 if (!visited[2]) { /* check E */
597 pixGetPixel(pixs, x + 1, y, &val);
598 if (colorsAreSimilarForFill(color, val, maxdiff)) {
599 el = colorelCreate(x + 1, y, color);
600 lqueueAdd(lq, el);
601 ptaAddPt(pta, x + 1, y);
602 pixSetPixel(pixv, x + 1, y, 1);
603 }
604 }
605 if (!visited[3]) { /* check S */
606 pixGetPixel(pixs, x, y + 1, &val);
607 if (colorsAreSimilarForFill(color, val, maxdiff)) {
608 el = colorelCreate(x, y + 1, color);
609 lqueueAdd(lq, el);
610 ptaAddPt(pta, x, y + 1);
611 pixSetPixel(pixv, x, y + 1, 1);
612 }
613 }
614 if (!visited[4]) { /* check NW */
615 pixGetPixel(pixs, x - 1, y - 1, &val);
616 if (colorsAreSimilarForFill(color, val, maxdiff)) {
617 el = colorelCreate(x - 1, y - 1, color);
618 lqueueAdd(lq, el);
619 ptaAddPt(pta, x - 1, y - 1);
620 pixSetPixel(pixv, x - 1, y - 1, 1);
621 }
622 }
623 if (!visited[5]) { /* check NE */
624 pixGetPixel(pixs, x + 1, y - 1, &val);
625 if (colorsAreSimilarForFill(color, val, maxdiff)) {
626 el = colorelCreate(x + 1, y - 1, color);
627 lqueueAdd(lq, el);
628 ptaAddPt(pta, x + 1, y - 1);
629 pixSetPixel(pixv, x + 1, y - 1, 1);
630 }
631 }
632 if (!visited[6]) { /* check SW */
633 pixGetPixel(pixs, x - 1, y + 1, &val);
634 if (colorsAreSimilarForFill(color, val, maxdiff)) {
635 el = colorelCreate(x - 1, y + 1, color);
636 lqueueAdd(lq, el);
637 ptaAddPt(pta, x - 1, y + 1);
638 pixSetPixel(pixv, x - 1, y + 1, 1);
639 }
640 }
641 if (!visited[7]) { /* check SE */
642 pixGetPixel(pixs, x + 1, y + 1, &val);
643 if (colorsAreSimilarForFill(color, val, maxdiff)) {
644 el = colorelCreate(x + 1, y + 1, color);
645 lqueueAdd(lq, el);
646 ptaAddPt(pta, x + 1, y + 1);
647 pixSetPixel(pixv, x + 1, y + 1, 1);
648 }
649 }
650 }
651
652 /* If there are not enough pixels, do not return the pta.
653 * Otherwise, if a pta is returned, the caller will generate
654 * a component and put it in the mask. */
655 np = ptaGetCount(pta);
656 if (np < minarea) {
657 if (debug) lept_stderr(" Too small. End: x = %d, y = %d, np = %d\n",
658 x, y, np);
659 ptaDestroy(ppta);
660 } else {
661 if (debug) lept_stderr(" Keep. End: x = %d, y = %d, np = %d\n",
662 x, y, np);
663 }
664}
665
666
686static void
688 l_int32 x,
689 l_int32 y,
690 l_uint32 *visited)
691{
692 pixGetPixel(pixs, x - 1, y, visited); /* W */
693 pixGetPixel(pixs, x, y - 1, visited + 1); /* N */
694 pixGetPixel(pixs, x + 1, y, visited + 2); /* E */
695 pixGetPixel(pixs, x, y + 1, visited + 3); /* S */
696 pixGetPixel(pixs, x - 1, y - 1, visited + 4); /* NW */
697 pixGetPixel(pixs, x + 1, y - 1, visited + 5); /* NE */
698 pixGetPixel(pixs, x - 1, y + 1, visited + 6); /* SW */
699 pixGetPixel(pixs, x + 1, y + 1, visited + 7); /* SE */
700}
701
702
717static l_int32
719 l_int32 *px,
720 l_int32 *py)
721{
722l_int32 ret;
723PIX *pix1;
724
725 pix1 = pixCopy(NULL, pixv);
726 pixInvert(pix1, pix1); /* After inversion, ON pixels are unvisited */
727 ret = nextOnPixelInRaster(pix1, 1, *py, px, py);
728 pixDestroy(&pix1);
729 return ret;
730}
731
732
757static l_int32
759 l_uint32 val2,
760 l_int32 maxdiff)
761{
762l_int32 rdiff, gdiff, bdiff, maxindex, del1, del2, del3, maxdel;
763l_int32 v1[3], v2[3];
764
765 extractRGBValues(val1, v1, v1 + 1, v1 + 2);
766 extractRGBValues(val2, v2, v2 + 1, v2 + 2);
767 rdiff = v1[0] - v2[0];
768 gdiff = v1[1] - v2[1];
769 bdiff = v1[2] - v2[2];
770 maxindex = 0;
771 if (L_ABS(gdiff) > L_ABS(rdiff))
772 maxindex = 1;
773 if (L_ABS(bdiff) > L_ABS(rdiff) && L_ABS(bdiff) > L_ABS(gdiff))
774 maxindex = 2;
775 del1 = v1[maxindex] - v2[maxindex];
776 del2 = v1[(maxindex + 1) % 3] - v2[(maxindex + 1) % 3];
777 del3 = v1[(maxindex + 2) % 3] - v2[(maxindex + 2) % 3];
778 maxdel = L_MAX(L_ABS(del1 - del2), L_ABS(del1 - del3));
779 return (maxdel <= maxdiff) ? 1 : 0;
780}
781
782
790static l_int32
791pixelColorIsValid(l_uint32 val,
792 l_int32 minmax)
793{
794l_int32 rval, gval, bval;
795
796 extractRGBValues(val, &rval, &gval, &bval);
797 if (rval < minmax && gval < minmax && bval < minmax)
798 return 0; /* maximum component is less than threshold */
799 else
800 return 1;
801}
802
803
812static l_int32
814 l_int32 x,
815 l_int32 y)
816{
817l_int32 w, h;
818l_uint32 val, neigh;
819
820 pixGetDimensions(pixs, &w, &h, NULL);
821 pixGetPixel(pixs, x, y, &val);
822 if (x > 0) {
823 pixGetPixel(pixs, x - 1, y, &neigh); /* W */
824 if (neigh != val) return TRUE;
825 }
826 if (x < w - 1) {
827 pixGetPixel(pixs, x + 1, y, &neigh); /* E */
828 if (neigh != val) return TRUE;
829 }
830 if (y > 0) {
831 pixGetPixel(pixs, x, y - 1, &neigh); /* N */
832 if (neigh != val) return TRUE;
833 }
834 if (y < h - 1) {
835 pixGetPixel(pixs, x, y + 1, &neigh); /* S */
836 if (neigh != val) return TRUE;
837 }
838 return FALSE;
839}
840
841
849static l_int32
851 l_int32 debug)
852{
853l_int32 i, j, n, nc, w, h, x, y, count;
854l_float32 rval, gval, bval;
855l_uint32 pixel;
856l_int32 *tab;
857BOX *box1;
858BOXA *boxa1;
859L_DNA *da;
860NUMA *na;
861PIX *pixm, *pix1, *pix2, *pixdb;
862PIXA *pixa1;
863
864 PROCNAME("evalColorfillData");
865
866 if (!cf)
867 return ERROR_INT("cf not defind", procName, 1);
868
869 tab = makePixelSumTab8();
870 n = cf->nx * cf->ny;
871 for (i = 0; i < n; i++) {
872 pix1 = pixaGetPix(cf->pixas, i, L_CLONE);
873 pixm = pixaGetPix(cf->pixam, i, L_CLONE);
874 pixGetDimensions(pix1, &w, &h, NULL);
875 boxa1 = pixConnComp(pixm, &pixa1, 4);
876 boxaDestroy(&boxa1);
877 nc = pixaGetCount(pixa1);
878 na = numaCreate(0);
879 da = l_dnaCreate(0);
880 pixdb = (debug) ? pixCreate(w, h, 32) : NULL;
881 for (j = 0; j < nc; j++) {
882 pix2 = pixaGetPix(pixa1, j, L_COPY);
883 box1 = pixaGetBox(pixa1, j, L_COPY);
884 boxGetGeometry(box1, &x, &y, NULL, NULL);
885 pixGetRankValueMaskedRGB(pix1, pix2, x, y, 1, 0.5,
886 &rval, &gval, &bval);
887 composeRGBPixel(rval, gval, bval, &pixel);
888
889 l_dnaAddNumber(da, pixel);
890 pixCountPixels(pix2, &count, tab);
891 numaAddNumber(na, count);
892 if (debug)
893 pixPaintThroughMask(pixdb, pix2, x, y, pixel);
894 boxDestroy(&box1);
895 pixDestroy(&pix2);
896 }
897 pixaAddPix(cf->pixadb, pixdb, L_INSERT);
898 numaaAddNuma(cf->naa, na, L_INSERT);
899 l_dnaaAddDna(cf->dnaa, da, L_INSERT);
900 pixDestroy(&pix1);
901 pixDestroy(&pixm);
902 pixaDestroy(&pixa1);
903 }
904
905 if (debug) { /* first tile */
906 na = numaaGetNuma(cf->naa, 0, L_CLONE);
907 lept_stderr("Size of components in tile 0:");
908 numaWriteStderr(na);
909 numaDestroy(&na);
910 }
911 LEPT_FREE(tab);
912 return 0;
913}
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:282
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:172
l_ok boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:313
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:502
l_ok boxaAddBox(BOXA *boxa, BOX *box, l_int32 copyflag)
boxaAddBox()
Definition: boxbasic.c:620
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:583
PIX * pixColorShiftWhitePoint(PIX *pixs, l_int32 rref, l_int32 gref, l_int32 bref)
pixColorShiftWhitePoint()
Definition: colorcontent.c:583
PIX * pixColorFill(PIX *pixs, l_int32 minmax, l_int32 maxdiff, l_int32 smooth, l_int32 minarea, l_int32 debug)
pixColorFill()
Definition: colorfill.c:299
static l_int32 pixelColorIsValid(l_uint32 val, l_int32 minmax)
pixelColorIsValid()
Definition: colorfill.c:791
l_ok pixColorContentByLocation(L_COLORFILL *cf, l_int32 rref, l_int32 gref, l_int32 bref, l_int32 minmax, l_int32 maxdiff, l_int32 minarea, l_int32 smooth, l_int32 debug)
pixColorContentByLocation()
Definition: colorfill.c:226
L_COLORFILL * l_colorfillCreate(PIX *pixs, l_int32 nx, l_int32 ny)
l_colorfillCreate()
Definition: colorfill.c:107
static void pixColorFillFromSeed(PIX *pixs, PIX *pixv, PTA **ppta, l_int32 x, l_int32 y, L_QUEUE *lq, l_int32 maxdiff, l_int32 minarea, l_int32 debug)
pixColorFillFromSeed()
Definition: colorfill.c:537
void l_colorfillDestroy(L_COLORFILL **pcf)
l_colorfillDestroy()
Definition: colorfill.c:158
PIXA * makeColorfillTestData(l_int32 w, l_int32 h, l_int32 nseeds, l_int32 range)
makeColorfillTestData()
Definition: colorfill.c:412
static l_int32 colorsAreSimilarForFill(l_uint32 val1, l_uint32 val2, l_int32 maxdiff)
colorsAreSimilarForFill()
Definition: colorfill.c:758
static l_int32 pixelIsOnColorBoundary(PIX *pixs, l_int32 x, l_int32 y)
pixelIsOnColorBoundary()
Definition: colorfill.c:813
static l_int32 evalColorfillData(L_COLORFILL *cf, l_int32 debug)
evalColorfillData()
Definition: colorfill.c:850
static void pixGetVisitedNeighbors(PIX *pixs, l_int32 x, l_int32 y, l_uint32 *visited)
pixGetVisitedNeighbors()
Definition: colorfill.c:687
static l_int32 findNextUnvisited(PIX *pixv, l_int32 *px, l_int32 *py)
findNextUnvisited()
Definition: colorfill.c:718
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
BOXA * pixConnComp(PIX *pixs, PIXA **ppixa, l_int32 connectivity)
pixConnComp()
Definition: conncomp.c:151
l_int32 nextOnPixelInRaster(PIX *pixs, l_int32 xstart, l_int32 ystart, l_int32 *px, l_int32 *py)
nextOnPixelInRaster()
Definition: conncomp.c:457
PIX * pixConvolveRGBSep(PIX *pixs, L_KERNEL *kelx, L_KERNEL *kely)
pixConvolveRGBSep()
Definition: convolve.c:2141
l_ok l_dnaAddNumber(L_DNA *da, l_float64 val)
l_dnaAddNumber()
Definition: dnabasic.c:448
L_DNAA * l_dnaaCreate(l_int32 n)
l_dnaaCreate()
Definition: dnabasic.c:1285
l_ok l_dnaGetDValue(L_DNA *da, l_int32 index, l_float64 *pval)
l_dnaGetDValue()
Definition: dnabasic.c:692
L_DNA * l_dnaCreate(l_int32 n)
l_dnaCreate()
Definition: dnabasic.c:180
l_ok l_dnaaAddDna(L_DNAA *daa, L_DNA *da, l_int32 copyflag)
l_dnaaAddDna()
Definition: dnabasic.c:1421
void l_dnaDestroy(L_DNA **pda)
l_dnaDestroy()
Definition: dnabasic.c:332
void l_dnaaDestroy(L_DNAA **pdaa)
l_dnaaDestroy()
Definition: dnabasic.c:1386
void kernelDestroy(L_KERNEL **pkel)
kernelDestroy()
Definition: kernel.c:150
L_KERNEL * makeFlatKernel(l_int32 height, l_int32 width, l_int32 cy, l_int32 cx)
makeFlatKernel()
Definition: kernel.c:1107
PIX * pixDilateBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateBrick()
Definition: morph.c:688
PIX * pixErodeBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeBrick()
Definition: morph.c:758
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:478
l_ok numaWriteStderr(NUMA *na)
numaWriteStderr()
Definition: numabasic.c:1313
NUMA * numaaGetNuma(NUMAA *naa, l_int32 index, l_int32 accessflag)
numaaGetNuma()
Definition: numabasic.c:1740
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
l_ok numaaAddNuma(NUMAA *naa, NUMA *na, l_int32 copyflag)
numaaAddNuma()
Definition: numabasic.c:1546
NUMAA * numaaCreate(l_int32 n)
numaaCreate()
Definition: numabasic.c:1407
void numaaDestroy(NUMAA **pnaa)
numaaDestroy()
Definition: numabasic.c:1510
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
Definition: pix1.c:1699
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
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 pixSetBorderRingVal(PIX *pixs, l_int32 dist, l_uint32 val)
pixSetBorderRingVal()
Definition: pix2.c:1667
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
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2751
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2820
PIX * pixOr(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixOr()
Definition: pix3.c:1560
l_int32 * makePixelSumTab8(void)
makePixelSumTab8()
Definition: pix3.c:2411
l_ok pixPaintThroughMask(PIX *pixd, PIX *pixm, l_int32 x, l_int32 y, l_uint32 val)
pixPaintThroughMask()
Definition: pix3.c:626
l_ok pixCountPixels(PIX *pixs, l_int32 *pcount, l_int32 *tab8)
pixCountPixels()
Definition: pix3.c:1937
PIX * pixSubtract(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixSubtract()
Definition: pix3.c:1753
PIX * pixInvert(PIX *pixd, PIX *pixs)
pixInvert()
Definition: pix3.c:1509
l_ok pixGetRankValueMaskedRGB(PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_int32 factor, l_float32 rank, l_float32 *prval, l_float32 *pgval, l_float32 *pbval)
pixGetRankValueMaskedRGB()
Definition: pix4.c:1076
@ L_SELECT_IF_GTE
Definition: pix.h:785
@ L_COPY
Definition: pix.h:712
@ L_CLONE
Definition: pix.h:713
@ L_INSERT
Definition: pix.h:711
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:506
PIXA * pixaCreateFromBoxa(PIX *pixs, BOXA *boxa, l_int32 start, l_int32 num, l_int32 *pcropwarn)
pixaCreateFromBoxa()
Definition: pixabasic.c:272
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:412
BOX * pixaGetBox(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetBox()
Definition: pixabasic.c:816
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:167
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:650
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:691
PIX * pixSelectByArea(PIX *pixs, l_float32 thresh, l_int32 connectivity, l_int32 type, l_int32 *pchanged)
pixSelectByArea()
Definition: pixafunc1.c:848
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
PIX * pixGenerateFromPta(PTA *pta, l_int32 w, l_int32 h)
pixGenerateFromPta()
Definition: ptafunc1.c:2023
l_int32 lqueueGetCount(L_QUEUE *lq)
lqueueGetCount()
Definition: queue.c:286
void lqueueDestroy(L_QUEUE **plq, l_int32 freeflag)
lqueueDestroy()
Definition: queue.c:134
void * lqueueRemove(L_QUEUE *lq)
lqueueRemove()
Definition: queue.c:257
l_ok lqueueAdd(L_QUEUE *lq, void *item)
lqueueAdd()
Definition: queue.c:188
L_QUEUE * lqueueCreate(l_int32 nalloc)
lqueueCreate()
Definition: queue.c:93
PIX * pixSeedspread(PIX *pixs, l_int32 connectivity)
pixSeedspread()
Definition: seedfill.c:2792
Definition: pix.h:481
Definition: pix.h:492
struct Pix * pixst
Definition: colorfill.h:50
l_int32 tw
Definition: colorfill.h:53
struct Boxa * boxas
Definition: colorfill.h:56
l_int32 th
Definition: colorfill.h:54
struct Pix * pixs
Definition: colorfill.h:49
struct Pixa * pixadb
Definition: colorfill.h:62
l_int32 nx
Definition: colorfill.h:51
struct Numaa * naa
Definition: colorfill.h:60
struct Pixa * pixas
Definition: colorfill.h:57
struct Pixa * pixam
Definition: colorfill.h:58
struct L_Dnaa * dnaa
Definition: colorfill.h:61
l_int32 ny
Definition: colorfill.h:52
Definition: array.h:95
Definition: morph.h:89
Definition: queue.h:65
Definition: array.h:71
Definition: pix.h:139
Definition: pix.h:456
Definition: pix.h:517
l_ok genRandomIntOnInterval(l_int32 start, l_int32 end, l_int32 seed, l_int32 *pval)
genRandomIntOnInterval()
Definition: utils1.c:659
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306