How to create a binary mask from a yolo8 segmentation result – Python

by
Ali Hasan
image-segmentation llama-cpp-python semantic-segmentation yolov8

The Problem:

Given a YOLO8 segmentation result, I need to create a binary mask representing all objects belonging to a specific class within the image. Additionally, I seek an efficient and elegant solution, potentially using a provided utility function or avoiding explicit looping mechanisms.

The Solutions:

Solution 1: Using torch operations

To create a mask from a YOLO8 segmentation result, you can use the following steps:

  1. Get the segmentation mask from the result.
  2. Convert the segmentation mask to a binary mask by thresholding it at 0.5.
  3. Resize the binary mask to the size of the original image.
  4. Multiply the binary mask with the original image to create the final mask.

Here is an example code that demonstrates these steps:

import cv2
import numpy as np
import torch

# Load the YOLO8 model and image
model = YOLOv8(weights='yolov8m-seg.pt')
image = cv2.imread('image.jpg')

# Get the segmentation result
result = model(image)

# Get the segmentation mask
mask = result.segmentation_mask()

# Convert the segmentation mask to a binary mask
binary_mask = np.where(mask > 0.5, 1, 0)

# Resize the binary mask
resized_mask = cv2.resize(binary_mask, (image.shape[1], image.shape[0]))

# Multiply the binary mask with the original image
final_mask = resized_mask * image

# Save the final mask
cv2.imwrite('mask.jpg', final_mask)

This code will create a mask that contains the segmented objects in the image. The mask will be saved as a JPEG file.

Solution 2: How to create a binary mask from a yolo8 segmentation result without loop

The given code can be improved by using the torch.any() function to create a binary mask without a loop. Here’s the revised code:

from ultralytics import YOLO
import cv2
import torch
from pathlib import Path

# Load a pretrained YOLOv8n-seg Segment model
model = YOLO("weights/best.pt")

# Run inference on an image
results = model("images/img (1).jpg")  # results list

# Extract the masks and classes
masks = results[0].masks.data
classes = results[0].boxes.data[:, 5]

# Create a binary mask for all objects with a specific class (e.g., class 0)
# Check if class 0 exists in the predictions
class_0_indices = torch.where(classes == 0)
if class_0_indices[0].shape[0] > 0:
    class_0_masks = masks[class_0_indices]
    class_0_mask = torch.any(class_0_masks, dim=0).int() * 255
    cv2.imwrite("class_0_mask.jpg", class_0_mask.cpu().numpy())

This code will create a binary mask for all objects with class 0 without the need for a loop.

Q&A

How can I make a binary mask out of a yolo8 segmentation result?

Extract the people segmentations using the bbox classes. You will get an array of shape [channels, w, h]. Then you can use any over the channel dimension (which is equal to the number of people) to flatten the multi-channel array into a single channel array.

Is there a utility function in the yolo8 library that can create a binary mask from a segmentation result?

No, there is no utility function in the yolo8 library to create a binary mask from a segmentation result.

Video Explanation:

The following video, titled "Image segmentation with Yolov8 custom dataset | Computer vision ...", provides additional insights and in-depth exploration related to the topics discussed in this post.

Play video

Image segmentation with Yolov8 custom dataset | Computer vision tutorial. 41K views · 10 months ago #yolov8 #computervision #python ...more ...