Skip to content

Commit 8f73d52

Browse files
perf: apply spaghetti inspired labeling procedure to 6-connected binary (#149)
* perf: apply spaghetti inspired labeling procedure to 6-connected binary * perf: disable EPL for all binary images
1 parent ef0bea1 commit 8f73d52

2 files changed

Lines changed: 134 additions & 18 deletions

File tree

cc3d/cc3d_binary.hpp

Lines changed: 132 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -574,43 +574,159 @@ OUT* connected_components3d_6_binary(
574574
const int64_t xstart = runs[row << 1];
575575
const int64_t xend = runs[(row << 1) + 1];
576576

577-
for (int64_t x = xstart; x < xend; x++) {
578-
loc = x + sx * (y + sy * z);
577+
loc = xstart + sx * (y + sy * z);
578+
const int64_t loc_end = loc + (xend - xstart);
579579

580-
if (in_labels[loc] == 0) {
580+
if (in_labels[loc] == 0) {
581+
goto BLACK;
582+
}
583+
else if (y > 0 && in_labels[loc + K]) {
584+
out_labels[loc] = out_labels[loc + K];
585+
586+
if (z > 0 && in_labels[loc + E] && !in_labels[loc + B]) {
587+
equivalences.unify(out_labels[loc], out_labels[loc + E]);
588+
goto SIMPLE;
589+
}
590+
goto SIMPLE_K;
591+
}
592+
else if (z > 0 && in_labels[loc + E]) {
593+
out_labels[loc] = out_labels[loc + E];
594+
goto SIMPLE_E;
595+
}
596+
else {
597+
next_label++;
598+
out_labels[loc] = next_label;
599+
equivalences.add(out_labels[loc]);
600+
goto STANDARD;
601+
}
602+
603+
STANDARD:
604+
loc++;
605+
if (loc >= loc_end) {
581606
continue;
582607
}
583-
else if (x > 0 && in_labels[loc + M]) {
584-
out_labels[loc] = out_labels[loc + M];
585608

586-
if (y > 0 && in_labels[loc + K] && !in_labels[loc + J]) {
587-
equivalences.unify(out_labels[loc], out_labels[loc + K]);
588-
if (z > 0 && in_labels[loc + E]) {
589-
if (!in_labels[loc + D] && !in_labels[loc + B]) {
590-
equivalences.unify(out_labels[loc], out_labels[loc + E]);
591-
}
609+
if (in_labels[loc] == 0) {
610+
goto BLACK;
611+
}
612+
613+
out_labels[loc] = out_labels[loc + M];
614+
615+
if (y > 0 && in_labels[loc + K] && !in_labels[loc + J]) {
616+
equivalences.unify(out_labels[loc], out_labels[loc + K]);
617+
if (z > 0 && in_labels[loc + E]) {
618+
if (!in_labels[loc + D] && !in_labels[loc + B]) {
619+
equivalences.unify(out_labels[loc], out_labels[loc + E]);
592620
}
621+
goto SIMPLE;
593622
}
594-
else if (z > 0 && in_labels[loc + E] && !in_labels[loc + D]) {
595-
equivalences.unify(out_labels[loc], out_labels[loc + E]);
623+
goto SIMPLE_K;
624+
}
625+
else if (z > 0 && in_labels[loc + E] && !in_labels[loc + D]) {
626+
equivalences.unify(out_labels[loc], out_labels[loc + E]);
627+
goto SIMPLE_E;
628+
}
629+
630+
goto STANDARD;
631+
632+
SIMPLE:
633+
loc++;
634+
if (loc >= loc_end) {
635+
continue;
636+
}
637+
638+
if (in_labels[loc] == 0) {
639+
goto BLACK;
640+
}
641+
642+
out_labels[loc] = out_labels[loc + M];
643+
644+
if (y > 0 && in_labels[loc + K]) {
645+
if (z > 0 && in_labels[loc + E]) {
646+
goto SIMPLE;
596647
}
648+
goto SIMPLE_K;
649+
}
650+
else if (z > 0 && in_labels[loc + E]) {
651+
goto SIMPLE_E;
652+
}
653+
goto STANDARD;
654+
655+
SIMPLE_E:
656+
loc++;
657+
if (loc >= loc_end) {
658+
continue;
659+
}
660+
661+
if (in_labels[loc] == 0) {
662+
goto BLACK;
663+
}
664+
665+
out_labels[loc] = out_labels[loc + M];
666+
667+
if (y > 0 && in_labels[loc + K] && !in_labels[loc + J]) {
668+
equivalences.unify(out_labels[loc], out_labels[loc + K]);
669+
goto SIMPLE_K;
670+
}
671+
goto STANDARD;
672+
673+
SIMPLE_K:
674+
loc++;
675+
if (loc >= loc_end) {
676+
continue;
677+
}
678+
679+
if (in_labels[loc] == 0) {
680+
goto BLACK;
681+
}
682+
683+
out_labels[loc] = out_labels[loc + M];
684+
685+
if (y > 0 && in_labels[loc + K]) {
686+
if (z > 0 && in_labels[loc + E]) {
687+
if (!in_labels[loc + B]) {
688+
equivalences.unify(out_labels[loc], out_labels[loc + E]);
689+
}
690+
goto SIMPLE;
691+
}
692+
goto SIMPLE_K;
693+
}
694+
else if (z > 0 && in_labels[loc + E]) {
695+
equivalences.unify(out_labels[loc], out_labels[loc + E]);
696+
goto SIMPLE_E;
697+
}
698+
goto STANDARD;
699+
700+
BLACK:
701+
loc++;
702+
if (loc >= loc_end) {
703+
continue;
704+
}
705+
706+
if (in_labels[loc] == 0) {
707+
goto BLACK;
597708
}
598709
else if (y > 0 && in_labels[loc + K]) {
599710
out_labels[loc] = out_labels[loc + K];
600711

601-
if (z > 0 && in_labels[loc + E] && !in_labels[loc + B]) {
602-
equivalences.unify(out_labels[loc], out_labels[loc + E]);
712+
if (z > 0 && in_labels[loc + E]) {
713+
if (!in_labels[loc + B]) {
714+
equivalences.unify(out_labels[loc], out_labels[loc + E]);
715+
}
716+
goto SIMPLE;
603717
}
718+
goto SIMPLE_K;
604719
}
605720
else if (z > 0 && in_labels[loc + E]) {
606721
out_labels[loc] = out_labels[loc + E];
722+
goto SIMPLE_E;
607723
}
608724
else {
609725
next_label++;
610726
out_labels[loc] = next_label;
611727
equivalences.add(out_labels[loc]);
728+
goto STANDARD;
612729
}
613-
}
614730
}
615731
}
616732

cc3d/fastcc3d.pyx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,11 +374,11 @@ def connected_components(
374374
binary_image = binary_image or (dtype == bool)
375375
376376
# EPL saves time for multilabel because it helps us reduce the size of
377-
# the union-find allocation. However, for 2D binary images, we can use
377+
# the union-find allocation. However, for binary images, we can use
378378
# a static calculation to save 1/2 to 1/8 of the allocation. We unfortunately
379379
# lose hyperfast calculation of extremely sparse images (e.g. 1 pixel or line of pixels)
380380
# but reducing passes on the image improves times significantly for typical images.
381-
if binary_image and connectivity in (4,8):
381+
if binary_image:
382382
epl = voxels
383383
first_foreground_row = 0
384384
last_foreground_row = sy

0 commit comments

Comments
 (0)