Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I efficiently get the contour associated with the label? #6395

Open
GlassyWing opened this issue Jun 1, 2022 · 4 comments
Open
Labels
🫂 Support User help and QA 😴 Dormant no recent activity

Comments

@GlassyWing
Copy link

Description

One way is

for label_i in range(1, labels.max()):
    contour = measure.find_contours(labels == label_i, 0.5)[0]

But it is 100 times slower than finding the contour directly, since there are hundreds of labels

@grlee77
Copy link
Contributor

grlee77 commented Jun 1, 2022

There may be a better way to do this, but here is one idea. It does not avoid the for loop, but does result in calling find_contours only on the region of the labels image surrounding each label which should improve efficiency.

Basically regionprops is used to determine the slice objects covering each object in labels. Then we can find contours by searching only in the region containing each label followed by offsetting the contour coordinates by the start index of the ROI.

def _expand_slice(sl, n, size=None):
    """expand a slice by n elements on each end with truncation to range [0, size]"""
    start = max(sl.start - n, 0)
    if size is None:
        stop = sl.stop + n
    else:
        stop = min(sl.stop + n, size)
    return slice(start, stop, sl.step)

# determine slices to select each individual object
props = measure.regionprops_table(labels, properties=['slice'])
obj_slices = props['slice']

for label_i in range(1, labels.max()):
    # add one pixel border to the object slice
    local_region = tuple(_expand_slice(sl, 1, size)
                         for sl, size in zip(obj_slices[label_i], labels.shape))

    # find contour in the ROI
    contour = measure.find_contours(labels[local_region] == label_i, 0.5)[0]

    # offset coordinates by the starting coordinate of the ROI
    for d in range(labels.ndim):
        contour[:, d] += local_region[d].start

@grlee77
Copy link
Contributor

grlee77 commented Jun 1, 2022

This makes me wonder if we should add 'contour' as an object-based region property so it could be used directly via regionprops_table.

@rfezzani rfezzani added the 🫂 Support User help and QA label Jun 1, 2022
@GlassyWing
Copy link
Author

I found that the image method can directly get the slice related to the label, so the following method may be easier.

props_c = measure.regionprops(labels_c)
for i in range(1, len(props_c)):
    counter = measure.find_contours(props_c[i].image, 0.5)[0]

However, it is still worth considering obtaining the contours directly via the measure.label or regionprops methods.

@github-actions
Copy link

github-actions bot commented Dec 1, 2022

Hey, there hasn't been any activity on this issue for more than 180 days. For now, we have marked it as "dormant" until there is some new activity. You are welcome to reach out to people by mentioning them here or on our forum if you need more feedback! If you think that this issue is no longer relevant, you may close it by yourself; otherwise, we may do it at some point (either way, it will be done manually). In any case, thank you for your contributions so far!

@github-actions github-actions bot added the 😴 Dormant no recent activity label Dec 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🫂 Support User help and QA 😴 Dormant no recent activity
Projects
None yet
Development

No branches or pull requests

3 participants