Image Segmentation in OpenCV Python with Watershed Algorithm


As passionate computer vision enthusiasts and Python programmers, we have always been captivated by the incredible capabilities of the OpenCV library. One technique that has particularly fascinated us is image segmentation, the process of dividing an image into distinct regions. This article will share our journey and insights on performing image segmentation using OpenCV Python with the Watershed algorithm. By leveraging the concept of water flow in a physical landscape, the Watershed algorithm has emerged as a powerful tool for accurately identifying boundaries and separating objects in an image. Together, we will dive into the step−by−step process, from preprocessing the picture to applying the Watershed algorithm, all while showcasing examples and outputs. Join us as we unravel the art of image segmentation using OpenCV Python and the Watershed algorithm.

Step 1: Importing Libraries and Loading the Image

To begin our journey, we import two essential libraries: OpenCV and NumPy. OpenCV is widely used for image processing, while NumPy is known for its numerical computation capabilities in Python. With these powerful tools at our disposal, we move on to the next step: loading the image we want to segment. Here's an example code:

import cv2
import numpy as np

# Load the image
image = cv2.imread('image.jpg')

Step 2: Preprocessing the Image

Now, we convert the loaded image into grayscale using the cv2.cvtColor() function from the OpenCV library. This conversion simplifies the image by representing it in shades of gray, making it easier to analyze and process. Here's the example for converting the image to grayscale:

# Convert the image to grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

In the above code, the image refers to the loaded image that we want to segment. The cv2.cvtColor() function takes two arguments: the image and the conversion flag cv2.COLOR_BGR2GRAY, which specifies the conversion from BGR color space to grayscale.

Step 3: Applying Thresholding

Thresholding is a key technique in image segmentation that converts a grayscale image into a binary image. It plays a crucial role in separating the objects we are interested in from the background. In the binary image, the objects are denoted by white pixels, while the background is represented by black pixels. This clear differentiation between objects and the background simplifies the subsequent steps of the segmentation process.

To apply thresholding to the grayscale image obtained in Step 2, we utilize the cv2.threshold() function. Here's an example code:

# Apply thresholding
ret, threshold = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

Step 4: Removing Noise with Morphological Operations

Step 4 involves removing noise from an image using morphological operations. In image processing, noise refers to unwanted random variations or irregularities that can affect the quality and accuracy of the image analysis. Morphological operations are a set of operations that modify the shape and structure of objects in an image. Then, we will perform morphological opening, which combines an erosion operation followed by a dilation operation. This operation helps remove noise while preserving the overall shape and size of the objects in the image.

Now, let's examine the code snippet that demonstrates how to remove noise using a morphological opening:

# Perform morphological opening to remove noise
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(threshold, cv2.MORPH_OPEN, kernel, iterations=2)

In the above code, we define a kernel using NumPy, which is a 3x3 matrix of ones. The kernel determines the neighborhood around each pixel that is considered during the morphological operation. A larger kernel size can help remove larger noise or irregularities, but it may also blur the image.

Step 5: Creating Marker Image

In image segmentation using the Watershed algorithm, creating a marker image plays a crucial role. The marker image is used to label the regions of interest in the image, which helps accurately segment the image into distinct regions. The following code snippet demonstrates how to create the marker image:

# Find background region
sure_bg = cv2.dilate(opening, kernel, iterations=3)

# Find foreground region
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
ret, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)

# Create marker image
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)

Step 6: Applying Watershed Algorithm

Now comes the exciting part – applying the Watershed algorithm for image segmentation. In this step, we mark the unknown regions as zero and utilize the Watershed algorithm to segment the image into distinct regions.

# Apply Watershed algorithm
ret, markers = cv2.connectedComponents(sure_fg)
markers = markers + 1
markers[unknown == 255] = 0
cv2.watershed(image, markers)

By executing these lines of code, we effectively apply the Watershed algorithm to segment the image based on the marked regions, creating a segmentation map that can be further visualized and analyzed.

Step 7: Visualizing the Segmented Image

After applying the Watershed algorithm for image segmentation, it's time to visualize the segmented image. This step involves assigning different colors to each segmented region and blending it with the original image.

Here’s an example code:

# Apply colormap to the markers
colored_markers = np.zeros_like(image)
colored_markers[markers == -1] = [255, 0, 0]  # Boundaries in blue color

# Display the segmented image
segmented_image = cv2.addWeighted(image, 0.7, colored_markers, 0.3, 0)
cv2.imshow("Segmented Image", segmented_image)
cv2.waitKey(0)

Finally, we use cv2.imshow() to display the segmented image while cv2.waitKey(0) is used to wait for a key press. The segmented image may now be viewed, and the Watershed algorithm's findings can be examined.

Conclusion

In conclusion, image segmentation using the Watershed algorithm in OpenCV Python offers a powerful and versatile approach to partitioning images into meaningful regions. By leveraging the concept of water flow and combining it with the capabilities of the OpenCV library, we can accurately identify boundaries and separate objects in an image.

Throughout this article, we have explored the step−by−step process of image segmentation using the Watershed algorithm. Starting from loading the image and preprocessing it to enhance the segmentation accuracy, we have covered essential steps such as thresholding, noise removal, creating marker images, and applying the Watershed algorithm itself. We can achieve reliable and visually appealing image segmentation results by following these steps.

Updated on: 25-Jul-2023

748 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements