Image segmentation is a procedure that splits an image into multiple segments. The segments have similar color or intensity. The segments also usually have a meaning in the context of medicine, traffic, astronomy, or something else.
The easiest way to segment images is with a threshold value, which produces two segments (if values are equal to the threshold, we put them in one of the two segments). Otsu's thresholding method minimizes the weighted variance of the two segments (refer to the following equation):
If we segment images, it is a good idea to remove noise or foreign artifacts. With dilation (see the See also section) we can find parts of the image that belong to the background and the foreground. However, dilation leaves us with unidentified pixels.
import numpy as np import cv2 from matplotlib import pyplot as plt from sklearn.datasets import load_sample_image import dautil as dl from IPython.display import HTML
sp = dl.plotting.Subplotter(2, 2, context) img = load_sample_image('flower.jpg') dl.plotting.img_show(sp.ax, img) sp.label()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) _, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU) dl.plotting.img_show(sp.next_ax(), thresh) sp.label()
kernel = np.ones((3, 3), np.uint8) opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2) bg = cv2.dilate(opening, kernel, iterations=3) dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5) _, fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0) fg = np.uint8(fg) rest = cv2.subtract(bg, fg) dl.plotting.img_show(sp.next_ax(), rest) sp.label()
_, markers = cv2.connectedComponents(fg) markers += 1 markers[rest == 255] = 0 dl.plotting.img_show(sp.next_ax(), markers) sp.label() HTML(sp.exit())
Refer to the following screenshot for the end result:
The code is in the
extracting_patches.ipynb
file in this book's code bundle.