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

update mask2segments and saving results #9785

Merged
merged 4 commits into from
Oct 12, 2022

Conversation

vladoossss
Copy link
Contributor

@vladoossss vladoossss commented Oct 12, 2022

PR for this issue: #9784

πŸ› οΈ PR Summary

Made with ❀️ by Ultralytics Actions

🌟 Summary

Enhances segmentation strategies in YOLOv5 by ensuring robust handling of images with no detectable segments.

πŸ“Š Key Changes

  • Added a conditional check to handle scenarios where no contours are found during segment processing.
  • Ensures that a zero-filled array is used as a fallback for images lacking any detectable segments.

🎯 Purpose & Impact

  • Purpose: The update aims to prevent errors that occur when the model processes an image without detectable segments by properly handling an empty contour list.
  • Impact: This change ensures greater stability for the segmentation functionality in YOLOv5, leading to a more reliable performance for developers and users working with diverse image datasets. πŸ“ˆ

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ‘‹ Hello @vladoossss, thank you for submitting a YOLOv5 πŸš€ PR! To allow your work to be integrated as seamlessly as possible, we advise you to:

  • βœ… Verify your PR is up-to-date with ultralytics/yolov5 master branch. If your PR is behind you can update your code by clicking the 'Update branch' button or by running git pull and git merge master locally.
  • βœ… Verify all YOLOv5 Continuous Integration (CI) checks are passing.
  • βœ… Reduce changes to the absolute minimum required for your bug fix or feature addition. "It is not daily increase but daily decrease, hack away the unessential. The closer to the source, the less wastage there is." β€” Bruce Lee

@glenn-jocher glenn-jocher linked an issue Oct 12, 2022 that may be closed by this pull request
2 tasks
@glenn-jocher
Copy link
Member

@vladoossss I'd like to minimize the code changes here. Are you saying that some detections produce no masks?

Is there a way I can reproduce the issue myself? I don't think it makes sense to add integers to a list of segment masks. Can you simply update masks2segments with an if and no else?

def masks2segments(masks, strategy='largest'):
    # Convert masks(n,160,160) into segments(n,xy)
    segments = []
    for x in masks.int().cpu().numpy().astype('uint8'):
        c = cv2.findContours(x, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]
        if c:
            if strategy == 'concat':  # concatenate all segments
                c = np.concatenate([x.reshape(-1, 2) for x in c])
            elif strategy == 'largest':  # select largest segment
                c = np.array(c[np.array([len(x) for x in c]).argmax()]).reshape(-1, 2)
            segments.append(c.astype('float32'))
    return segments

@glenn-jocher
Copy link
Member

@vladoossss ok took another look. I see we need to keep the output array the same length as the input masks, how about creating an empty nparray when there is no segment of the same 2 columns. Can you try this new function with no other changes anywhere (i.e. use master segments/predict.py etc.)

def masks2segments(masks, strategy='largest'):
    # Convert masks(n,160,160) into segments(n,xy)
    segments = []
    for x in masks.int().cpu().numpy().astype('uint8'):
        c = cv2.findContours(x, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]
        if c:
            if strategy == 'concat':  # concatenate all segments
                c = np.concatenate([x.reshape(-1, 2) for x in c])
            elif strategy == 'largest':  # select largest segment
                c = np.array(c[np.array([len(x) for x in c]).argmax()]).reshape(-1, 2)
        else:
            c = np.zeros((0, 2))  # no segments found
        segments.append(c.astype('float32'))
    return segments

Signed-off-by: Glenn Jocher <[email protected]>
Signed-off-by: Glenn Jocher <[email protected]>
@glenn-jocher glenn-jocher merged commit 85ae985 into ultralytics:master Oct 12, 2022
@vladoossss
Copy link
Contributor Author

@vladoossss ok took another look. I see we need to keep the output array the same length as the input masks, how about creating an empty nparray when there is no segment of the same 2 columns. Can you try this new function with no other changes anywhere (i.e. use master segments/predict.py etc.)

def masks2segments(masks, strategy='largest'):
    # Convert masks(n,160,160) into segments(n,xy)
    segments = []
    for x in masks.int().cpu().numpy().astype('uint8'):
        c = cv2.findContours(x, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]
        if c:
            if strategy == 'concat':  # concatenate all segments
                c = np.concatenate([x.reshape(-1, 2) for x in c])
            elif strategy == 'largest':  # select largest segment
                c = np.array(c[np.array([len(x) for x in c]).argmax()]).reshape(-1, 2)
        else:
            c = np.zeros((0, 2))  # no segments found
        segments.append(c.astype('float32'))
    return segments

Yes, modifying just this one function also works fine!

@glenn-jocher
Copy link
Member

@vladoossss great! PR is merged. Thank you for your contributions to YOLOv5 πŸš€ and Vision AI ⭐

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

masks2segments function does not always work correctly
2 participants