Here are mainly four types of image segmentation based on OpenCV and Scikit-learn:
Based on K-means
based on Contour Detection
based on Thresholding
based on Color Masking HSV color space, it will not be demonstrated.
HSV color space threshold adjuster inside my opencv tool
Original image:
K-means
import numpy as np
import cv2
def cv_show(neme, img):
cv2.namedWindow(neme, cv2.WINDOW_NORMAL)
cv2.imshow(neme, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
path = 'image2.jpg'
img = cv2.imread(path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
twoDimage = img.reshape((-1, 3))
twoDimage = np.float32(twoDimage)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
K = 2
attempts = 10
# Kmeans
ret, label, center = cv2.kmeans(twoDimage, K, None, criteria, attempts, cv2.KMEANS_PP_CENTERS)
center = np.uint8(center)
res = center[label.flatten()]
result_image = res.reshape((img.shape))
cv_show('neme', result_image)
Effect:
Contour Detection
path = 'image2.jpg'
img = cv2.imread(path)
img = cv2.resize(img, (256, 256))
# 图像预处理
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
_, thresh = cv2.threshold(gray, np.mean(gray), 255, cv2.THRESH_BINARY_INV)
edges = cv2.dilate(cv2.Canny(thresh, 0, 255), None)
# 轮廓检测
cnt = sorted(cv2.findContours(edges, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[-2], key=cv2.contourArea)[-1] # 轮廓检测与排序
mask = np.zeros((256, 256), np.uint8)
masked = cv2.drawContours(mask, [cnt], -1, 255, -1)
# 区域分割
dst = cv2.bitwise_and(img, img, mask=mask)
segmented = cv2.cvtColor(dst, cv2.COLOR_BGR2RGB)
cv_show('neme', segmented)
Thresholding
pip install scikit-image
import numpy as np
from skimage.filters import threshold_otsu
import cv2
path = 'image2.jpg'
img = cv2.imread(path)
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2GRAY)
def filter_image(image, mask):
r = image[:, :, 0] * mask
g = image[:, :, 1] * mask
b = image[:, :, 2] * mask
return np.dstack([r, g, b])
thresh = threshold_otsu(img_gray) # 找阈值
img_otsu = img_gray < thresh
filtered = filter_image(img, img_otsu)
cv_show('neme', filtered)
Effect: