115 #include "allheaders.h" 117 #ifndef NO_CONSOLE_IO 118 #define DEBUG_WATERSHED 0 121 static const l_uint32 MAX_LABEL_VALUE = 0x7fffffff;
146 l_int32
index, l_int32 level,
158 static void pushNewPixel(
L_QUEUE *lq, l_int32
x, l_int32
y,
159 l_int32 *pminx, l_int32 *pmaxx,
160 l_int32 *pminy, l_int32 *pmaxy);
161 static void popNewPixel(
L_QUEUE *lq, l_int32 *px, l_int32 *py);
165 l_int32
x, l_int32
y, l_int32
index);
166 static void popWSPixel(
L_HEAP *lh,
L_STACK *stack, l_int32 *pval,
167 l_int32 *px, l_int32 *py, l_int32 *pindex);
170 static void debugPrintLUT(l_int32 *lut, l_int32 size, l_int32 debug);
172 static void debugWshedMerge(
L_WSHED *wshed,
char *descr, l_int32
x,
173 l_int32
y, l_int32 label, l_int32
index);
211 PROCNAME(
"wshedCreate");
214 return (
L_WSHED *)ERROR_PTR(
"pixs is not defined", procName, NULL);
215 if (pixGetDepth(pixs) != 8)
216 return (
L_WSHED *)ERROR_PTR(
"pixs is not 8 bpp", procName, NULL);
218 return (
L_WSHED *)ERROR_PTR(
"pixm is not defined", procName, NULL);
219 if (pixGetDepth(pixm) != 1)
220 return (
L_WSHED *)ERROR_PTR(
"pixm is not 1 bpp", procName, NULL);
222 if (pixGetWidth(pixm) != w || pixGetHeight(pixm) != h)
223 return (
L_WSHED *)ERROR_PTR(
"pixs/m sizes are unequal", procName, NULL);
226 return (
L_WSHED *)ERROR_PTR(
"wshed not made", procName, NULL);
230 wshed->
mindepth = L_MAX(1, mindepth);
238 wshed->
debug = debugflag;
255 PROCNAME(
"wshedDestroy");
257 if (pwshed == NULL) {
258 L_WARNING(
"ptr address is null!\n", procName);
262 if ((wshed = *pwshed) == NULL)
280 LEPT_FREE(wshed->
lut);
284 LEPT_FREE(wshed->
links);
307 char two_new_watersheds[] =
"Two new watersheds";
308 char seed_absorbed_into_seeded_basin[] =
"Seed absorbed into seeded basin";
309 char one_new_watershed_label[] =
"One new watershed (label)";
310 char one_new_watershed_index[] =
"One new watershed (index)";
311 char minima_absorbed_into_seeded_basin[] =
312 "Minima absorbed into seeded basin";
313 char minima_absorbed_by_filler_or_another[] =
314 "Minima absorbed by filler or another";
315 l_int32 nseeds, nother, nboth, arraysize;
316 l_int32 i, j,
val,
x,
y, w, h,
index, mindepth;
317 l_int32 imin, imax, jmin, jmax, cindex, clabel, nindex;
318 l_int32 hindex, hlabel, hmin, hmax, minhindex, maxhindex;
320 l_uint32 ulabel, uval;
321 void **lines8, **linelab32;
322 NUMA *nalut, *nalevels, *nash, *namh, *nasi;
330 PROCNAME(
"wshedApply");
333 return ERROR_INT(
"wshed not defined", procName, 1);
349 for (i = 0; i < nseeds; i++) {
352 pushWSPixel(lh, rstack, (l_int32)uval,
x,
y, i);
371 for (i = 0; i < nother; i++) {
374 pushWSPixel(lh, rstack, (l_int32)uval,
x,
y, nseeds + i);
386 nboth = nseeds + nother;
387 arraysize = 2 * nboth;
392 links = (
NUMA **)LEPT_CALLOC(arraysize,
sizeof(
NUMA *));
393 wshed->
links = links;
394 nindex = nseeds + nother;
401 wshed->
pixad = pixad;
404 L_INFO(
"nseeds = %d, nother = %d\n", procName, nseeds, nother);
409 if (ulabel == MAX_LABEL_VALUE)
412 clabel = lut[ulabel];
414 if (clabel == cindex)
continue;
415 if (clabel == MAX_LABEL_VALUE) {
418 imin = L_MAX(0,
y - 1);
419 imax = L_MIN(h - 1,
y + 1);
420 jmin = L_MAX(0,
x - 1);
421 jmax = L_MIN(w - 1,
x + 1);
422 for (i = imin; i <= imax; i++) {
423 for (j = jmin; j <= jmax; j++) {
424 if (i ==
y && j ==
x)
continue;
426 pushWSPixel(lh, rstack, (l_int32)uval, j, i, cindex);
437 if (clabel < nseeds && cindex < nseeds) {
440 hmin = L_MIN(hlabel, hindex);
441 hmax = L_MAX(hlabel, hindex);
447 fprintf(stderr,
"clabel,hlabel = %d,%d\n", clabel, hlabel);
448 fprintf(stderr,
"hmin = %d, hmax = %d\n", hmin, hmax);
449 fprintf(stderr,
"cindex,hindex = %d,%d\n", cindex, hindex);
451 fprintf(stderr,
"Too shallow!\n");
454 if (hmin >= mindepth) {
455 debugWshedMerge(wshed, two_new_watersheds,
456 x,
y, clabel, cindex);
462 if (wshed->
debug) fprintf(stderr,
"nindex = %d\n", nindex);
463 debugPrintLUT(lut, nindex, wshed->
debug);
465 debugPrintLUT(lut, nindex, wshed->
debug);
467 debugPrintLUT(lut, nindex, wshed->
debug);
470 debugWshedMerge(wshed, seed_absorbed_into_seeded_basin,
471 x,
y, clabel, cindex);
475 if (hindex > hlabel) {
480 }
else if (clabel < nseeds && cindex >= nboth) {
483 debugWshedMerge(wshed, one_new_watershed_label,
484 x,
y, clabel, cindex);
488 }
else if (cindex < nseeds && clabel >= nboth) {
489 debugWshedMerge(wshed, one_new_watershed_index,
490 x,
y, clabel, cindex);
494 }
else if (clabel < nseeds) {
497 debugWshedMerge(wshed, minima_absorbed_into_seeded_basin,
498 x,
y, clabel, cindex);
500 }
else if (cindex < nseeds) {
501 debugWshedMerge(wshed, minima_absorbed_into_seeded_basin,
502 x,
y, clabel, cindex);
505 debugWshedMerge(wshed, minima_absorbed_by_filler_or_another,
506 x,
y, clabel, cindex);
515 for (i = 0; i < nseeds; i++) {
561 PROCNAME(
"wshedSaveBasin");
564 L_ERROR(
"wshed not defined\n", procName);
605 l_int32 imin, imax, jmin, jmax, minx, miny, maxx, maxy;
606 l_int32 bw, bh, i, j, w, h,
x,
y;
608 l_uint32 label, bval, lval;
609 void **lines8, **linelab32, **linet1;
611 PIX *pixs, *pixt, *pixd;
614 PROCNAME(
"identifyWatershedBasin");
617 return ERROR_INT(
"&box not defined", procName, 1);
620 return ERROR_INT(
"&pixd not defined", procName, 1);
623 return ERROR_INT(
"wshed not defined", procName, 1);
638 minx = miny = 1000000;
642 pushNewPixel(lq,
x,
y, &minx, &maxx, &miny, &maxy);
643 if (wshed->
debug) fprintf(stderr,
"prime: (x,y) = (%d, %d)\n",
x,
y);
653 popNewPixel(lq, &
x, &
y);
654 imin = L_MAX(0,
y - 1);
655 imax = L_MIN(h - 1,
y + 1);
656 jmin = L_MAX(0,
x - 1);
657 jmax = L_MIN(w - 1,
x + 1);
658 for (i = imin; i <= imax; i++) {
659 for (j = jmin; j <= jmax; j++) {
660 if (j ==
x && i ==
y)
continue;
662 if (label == MAX_LABEL_VALUE || lut[label] !=
index)
continue;
664 if (bval == 1)
continue;
666 if (lval >= level)
continue;
668 pushNewPixel(lq, j, i, &minx, &maxx, &miny, &maxy);
674 bw = maxx - minx + 1;
675 bh = maxy - miny + 1;
716 l_int32 i, n, size,
index;
721 PROCNAME(
"mergeLookup");
724 return ERROR_INT(
"wshed not defined", procName, 1);
726 if (sindex < 0 || sindex >= size)
727 return ERROR_INT(
"invalid sindex", procName, 1);
728 if (dindex < 0 || dindex >= size)
729 return ERROR_INT(
"invalid dindex", procName, 1);
733 links = wshed->
links;
735 if ((na = links[sindex]) != NULL) {
737 for (i = 0; i < n; i++) {
742 lut[sindex] = dindex;
750 numaJoin(links[dindex], links[sindex], 0, -1);
783 PROCNAME(
"wshedGetHeight");
786 return ERROR_INT(
"&height not defined", procName, 1);
789 return ERROR_INT(
"wshed not defined", procName, 1);
791 if (label < wshed->nseeds)
793 else if (label < wshed->nseeds + wshed->
nother)
796 return ERROR_INT(
"finished watershed; should not call", procName, 1);
798 *pheight =
val - minval;
827 PROCNAME(
"pushNewPixel");
830 L_ERROR(
"queue not defined\n", procName);
835 *pminx = L_MIN(*pminx,
x);
836 *pmaxx = L_MAX(*pmaxx,
x);
837 *pminy = L_MIN(*pminy,
y);
838 *pmaxy = L_MAX(*pmaxy,
y);
872 PROCNAME(
"popNewPixel");
875 L_ERROR(
"lqueue not defined\n", procName);
912 PROCNAME(
"pushWSPixel");
915 L_ERROR(
"heap not defined\n", procName);
919 L_ERROR(
"stack not defined\n", procName);
929 wsp->
val = (l_float32)
val;
963 PROCNAME(
"popWSPixel");
966 L_ERROR(
"lheap not defined\n", procName);
970 L_ERROR(
"stack not defined\n", procName);
973 if (!pval || !px || !py || !pindex) {
974 L_ERROR(
"data can't be returned\n", procName);
980 *pval = (l_int32)wsp->
val;
983 *pindex = wsp->
index;
990 debugPrintLUT(l_int32 *lut,
997 fprintf(stderr,
"lut: ");
998 for (i = 0; i < size; i++)
999 fprintf(stderr,
"%d ", lut[i]);
1000 fprintf(stderr,
"\n");
1006 debugWshedMerge(
L_WSHED *wshed,
1013 if (!wshed || (wshed->
debug == 0))
1015 fprintf(stderr,
"%s:\n", descr);
1016 fprintf(stderr,
" (x, y) = (%d, %d)\n",
x,
y);
1017 fprintf(stderr,
" clabel = %d, cindex = %d\n", label,
index);
1038 PROCNAME(
"wshedBasins");
1041 return ERROR_INT(
"wshed not defined", procName, 1);
1060 l_int32 i, n, level, bx, by;
1065 PROCNAME(
"wshedRenderFill");
1068 return (
PIX *)ERROR_PTR(
"wshed not defined", procName, NULL);
1073 for (i = 0; i < n; i++) {
1097 PIX *pixg, *pixt, *pixc, *pixm, *pixd;
1100 PROCNAME(
"wshedRenderColors");
1103 return (
PIX *)ERROR_PTR(
"wshed not defined", procName, NULL);
l_ok lheapAdd(L_HEAP *lh, void *item)
lheapAdd()
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
void lstackDestroy(L_STACK **plstack, l_int32 freeflag)
lstackDestroy()
PIX * pixGenerateFromPta(PTA *pta, l_int32 w, l_int32 h)
pixGenerateFromPta()
PIX * pixRemoveSeededComponents(PIX *pixd, PIX *pixs, PIX *pixm, l_int32 connectivity, l_int32 bordersize)
pixRemoveSeededComponents()
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
PIXA * pixaCreate(l_int32 n)
pixaCreate()
L_QUEUE * lqueueCreate(l_int32 nalloc)
lqueueCreate()
l_int32 lstackGetCount(L_STACK *lstack)
lstackGetCount()
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()
void wshedDestroy(L_WSHED **pwshed)
wshedDestroy()
void ** pixGetLinePtrs(PIX *pix, l_int32 *psize)
pixGetLinePtrs()
NUMA * numaMakeConstant(l_float32 val, l_int32 size)
numaMakeConstant()
#define GET_DATA_FOUR_BYTES(pdata, n)
l_ok pixLocalExtrema(PIX *pixs, l_int32 maxmin, l_int32 minmax, PIX **ppixmin, PIX **ppixmax)
pixLocalExtrema()
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
NUMA * numaCreate(l_int32 n)
numaCreate()
l_int32 ptaGetCount(PTA *pta)
ptaGetCount()
void lheapDestroy(L_HEAP **plh, l_int32 freeflag)
lheapDestroy()
PIX * pixaDisplay(PIXA *pixa, l_int32 w, l_int32 h)
pixaDisplay()
#define GET_DATA_BIT(pdata, n)
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
l_ok numaSetValue(NUMA *na, l_int32 index, l_float32 val)
numaSetValue()
l_int32 lheapGetCount(L_HEAP *lh)
lheapGetCount()
l_ok pixPaintThroughMask(PIX *pixd, PIX *pixm, l_int32 x, l_int32 y, l_uint32 val)
pixPaintThroughMask()
void * lqueueRemove(L_QUEUE *lq)
lqueueRemove()
l_ok lstackAdd(L_STACK *lstack, void *item)
lstackAdd()
l_ok pixSetAllArbitrary(PIX *pix, l_uint32 val)
pixSetAllArbitrary()
l_ok pixCombineMasked(PIX *pixd, PIX *pixs, PIX *pixm)
pixCombineMasked()
PIXA * pixaCopy(PIXA *pixa, l_int32 copyflag)
pixaCopy()
l_int32 * numaGetIArray(NUMA *na)
numaGetIArray()
PIX * pixaDisplayRandomCmap(PIXA *pixa, l_int32 w, l_int32 h)
pixaDisplayRandomCmap()
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
PIX * wshedRenderColors(L_WSHED *wshed)
wshedRenderColors()
void * lstackRemove(L_STACK *lstack)
lstackRemove()
l_int32 numaGetCount(NUMA *na)
numaGetCount()
l_ok pixSetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 val)
pixSetPixel()
l_ok lqueueAdd(L_QUEUE *lq, void *item)
lqueueAdd()
static l_int32 mergeLookup(L_WSHED *wshed, l_int32 sindex, l_int32 dindex)
mergeLookup()
L_HEAP * lheapCreate(l_int32 nalloc, l_int32 direction)
lheapCreate()
#define GET_DATA_BYTE(pdata, n)
void * lheapRemove(L_HEAP *lh)
lheapRemove()
L_STACK * lstackCreate(l_int32 nalloc)
lstackCreate()
l_ok pixaGetBoxGeometry(PIXA *pixa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
pixaGetBoxGeometry()
l_ok wshedApply(L_WSHED *wshed)
wshedApply()
PIX * wshedRenderFill(L_WSHED *wshed)
wshedRenderFill()
static void wshedSaveBasin(L_WSHED *wshed, l_int32 index, l_int32 level)
wshedSaveBasin()
PIX * pixClone(PIX *pixs)
pixClone()
void pixDestroy(PIX **ppix)
pixDestroy()
NUMA * numaMakeSequence(l_float32 startval, l_float32 increment, l_int32 size)
numaMakeSequence()
l_int32 lqueueGetCount(L_QUEUE *lq)
lqueueGetCount()
void numaDestroy(NUMA **pna)
numaDestroy()
l_ok pixGetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 *pval)
pixGetPixel()
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
L_WSHED * wshedCreate(PIX *pixs, PIX *pixm, l_int32 mindepth, l_int32 debugflag)
wshedCreate()
l_ok numaJoin(NUMA *nad, NUMA *nas, l_int32 istart, l_int32 iend)
numaJoin()
#define SET_DATA_FOUR_BYTES(pdata, n, val)
static l_int32 identifyWatershedBasin(L_WSHED *wshed, l_int32 index, l_int32 level, BOX **pbox, PIX **ppixd)
identifyWatershedBasin()
l_ok wshedBasins(L_WSHED *wshed, PIXA **ppixa, NUMA **pnalevels)
wshedBasins()
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
void lqueueDestroy(L_QUEUE **plq, l_int32 freeflag)
lqueueDestroy()
l_ok pixSelectMinInConnComp(PIX *pixs, PIX *pixm, PTA **ppta, NUMA **pnav)
pixSelectMinInConnComp()
void ptaDestroy(PTA **ppta)
ptaDestroy()
PIX * pixCopy(PIX *pixd, PIX *pixs)
pixCopy()
NUMA * numaClone(NUMA *na)
numaClone()
l_ok ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
static l_int32 wshedGetHeight(L_WSHED *wshed, l_int32 val, l_int32 label, l_int32 *pheight)
wshedGetHeight()
l_ok pixaAddBox(PIXA *pixa, BOX *box, l_int32 copyflag)
pixaAddBox()
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
#define SET_DATA_BIT(pdata, n)