308char two_new_watersheds[] =
"Two new watersheds";
309char seed_absorbed_into_seeded_basin[] =
"Seed absorbed into seeded basin";
310char one_new_watershed_label[] =
"One new watershed (label)";
311char one_new_watershed_index[] =
"One new watershed (index)";
312char minima_absorbed_into_seeded_basin[] =
313 "Minima absorbed into seeded basin";
314char minima_absorbed_by_filler_or_another[] =
315 "Minima absorbed by filler or another";
316l_int32 nseeds, nother, nboth, arraysize;
317l_int32 i, j,
val,
x,
y, w, h,
index, mindepth;
318l_int32 imin, imax, jmin, jmax, cindex, clabel, nindex;
319l_int32 hindex, hlabel, hmin, hmax, minhindex, maxhindex;
321l_uint32 ulabel, uval;
322void **lines8, **linelab32;
323NUMA *nalut, *nalevels, *nash, *namh, *nasi;
332 return ERROR_INT(
"wshed not defined", __func__, 1);
339 rstack = lstackCreate(0);
340 pixGetDimensions(wshed->
pixs, &w, &h, NULL);
345 pixSelectMinInConnComp(wshed->
pixs, wshed->
pixm, &ptas, &nash);
346 pixsd = pixGenerateFromPta(ptas, w, h);
347 nseeds = ptaGetCount(ptas);
348 for (i = 0; i < nseeds; i++) {
349 ptaGetIPt(ptas, i, &
x, &
y);
351 pushWSPixel(lh, rstack, (l_int32)uval,
x,
y, i);
354 nasi = numaMakeConstant(1, nseeds);
366 pixLocalExtrema(wshed->
pixs, 200, 0, &pixmin, NULL);
367 pixRemoveSeededComponents(pixmin, pixsd, pixmin, 8, 2);
368 pixSelectMinInConnComp(wshed->
pixs, pixmin, &ptao, &namh);
369 nother = ptaGetCount(ptao);
370 for (i = 0; i < nother; i++) {
371 ptaGetIPt(ptao, i, &
x, &
y);
373 pushWSPixel(lh, rstack, (l_int32)uval,
x,
y, nseeds + i);
385 nboth = nseeds + nother;
386 arraysize = 2 * nboth;
388 nalut = numaMakeSequence(0, 1, arraysize);
389 lut = numaGetIArray(nalut);
391 links = (
NUMA **)LEPT_CALLOC(arraysize,
sizeof(
NUMA *));
392 wshed->
links = links;
393 nindex = nseeds + nother;
399 pixad = pixaCreate(nseeds);
400 wshed->
pixad = pixad;
401 nalevels = numaCreate(nseeds);
403 L_INFO(
"nseeds = %d, nother = %d\n", __func__, nseeds, nother);
404 while (lheapGetCount(lh) > 0) {
408 if (ulabel == MAX_LABEL_VALUE)
411 clabel = lut[ulabel];
413 if (clabel == cindex)
continue;
414 if (clabel == MAX_LABEL_VALUE) {
417 imin = L_MAX(0,
y - 1);
418 imax = L_MIN(h - 1,
y + 1);
419 jmin = L_MAX(0,
x - 1);
420 jmax = L_MIN(w - 1,
x + 1);
421 for (i = imin; i <= imax; i++) {
422 for (j = jmin; j <= jmax; j++) {
423 if (i ==
y && j ==
x)
continue;
425 pushWSPixel(lh, rstack, (l_int32)uval, j, i, cindex);
435 pixGetPixel(pixsd,
x,
y, &uval);
436 if (clabel < nseeds && cindex < nseeds) {
439 hmin = L_MIN(hlabel, hindex);
440 hmax = L_MAX(hlabel, hindex);
446 lept_stderr(
"clabel,hlabel = %d,%d\n", clabel, hlabel);
447 lept_stderr(
"hmin = %d, hmax = %d\n", hmin, hmax);
448 lept_stderr(
"cindex,hindex = %d,%d\n", cindex, hindex);
450 lept_stderr(
"Too shallow!\n");
453 if (hmin >= mindepth) {
454 debugWshedMerge(wshed, two_new_watersheds,
455 x,
y, clabel, cindex);
458 numaSetValue(nasi, cindex, 0);
459 numaSetValue(nasi, clabel, 0);
461 if (wshed->
debug) lept_stderr(
"nindex = %d\n", nindex);
462 debugPrintLUT(lut, nindex, wshed->
debug);
464 debugPrintLUT(lut, nindex, wshed->
debug);
466 debugPrintLUT(lut, nindex, wshed->
debug);
469 debugWshedMerge(wshed, seed_absorbed_into_seeded_basin,
470 x,
y, clabel, cindex);
474 if (hindex > hlabel) {
479 }
else if (clabel < nseeds && cindex >= nboth) {
482 debugWshedMerge(wshed, one_new_watershed_label,
483 x,
y, clabel, cindex);
485 numaSetValue(nasi, clabel, 0);
487 }
else if (cindex < nseeds && clabel >= nboth) {
488 debugWshedMerge(wshed, one_new_watershed_index,
489 x,
y, clabel, cindex);
491 numaSetValue(nasi, cindex, 0);
493 }
else if (clabel < nseeds) {
496 debugWshedMerge(wshed, minima_absorbed_into_seeded_basin,
497 x,
y, clabel, cindex);
499 }
else if (cindex < nseeds) {
500 debugWshedMerge(wshed, minima_absorbed_into_seeded_basin,
501 x,
y, clabel, cindex);
504 debugWshedMerge(wshed, minima_absorbed_by_filler_or_another,
505 x,
y, clabel, cindex);
514 for (i = 0; i < nseeds; i++) {
515 numaGetIValue(nasi, i, &ival);
518 numaSetValue(nasi, i, 0);
527 lheapDestroy(&lh, TRUE);
528 lstackDestroy(&rstack, TRUE);
601l_int32 imin, imax, jmin, jmax, minx, miny, maxx, maxy;
602l_int32 bw, bh, i, j, w, h,
x,
y;
604l_uint32 label, bval, lval;
605void **lines8, **linelab32, **linet1;
607PIX *pixs, *pixt, *pixd;
611 return ERROR_INT(
"&box not defined", __func__, 1);
614 return ERROR_INT(
"&pixd not defined", __func__, 1);
617 return ERROR_INT(
"wshed not defined", __func__, 1);
620 lq = lqueueCreate(0);
621 lq->
stack = lstackCreate(0);
629 pixGetDimensions(pixs, &w, &h, NULL);
632 minx = miny = 1000000;
635 pixSetPixel(pixt,
x,
y, 1);
636 pushNewPixel(lq,
x,
y, &minx, &maxx, &miny, &maxy);
637 if (wshed->
debug) lept_stderr(
"prime: (x,y) = (%d, %d)\n",
x,
y);
646 while (lqueueGetCount(lq) > 0) {
647 popNewPixel(lq, &
x, &
y);
648 imin = L_MAX(0,
y - 1);
649 imax = L_MIN(h - 1,
y + 1);
650 jmin = L_MAX(0,
x - 1);
651 jmax = L_MIN(w - 1,
x + 1);
652 for (i = imin; i <= imax; i++) {
653 for (j = jmin; j <= jmax; j++) {
654 if (j ==
x && i ==
y)
continue;
656 if (label == MAX_LABEL_VALUE || lut[label] !=
index)
continue;
658 if (bval == 1)
continue;
660 if (lval >= level)
continue;
662 pushNewPixel(lq, j, i, &minx, &maxx, &miny, &maxy);
668 bw = maxx - minx + 1;
669 bh = maxy - miny + 1;
670 box = boxCreate(minx, miny, bw, bh);
671 pixd = pixClipRectangle(pixt, box, NULL);
672 pixRasterop(pixt, minx, miny, bw, bh,
PIX_SRC ^
PIX_DST, pixd, 0, 0);
676 lqueueDestroy(&lq, 1);