From:4 Image Segmentation Techniques in OpenCV Python - 2021.09.07
图像分割
图像分割任务是,将图像分割或分区到多个区域,且具有相同特性的像素被划分到相同区域.
图像分割有两种形式,
- 局部分割(Local segmentation) - 关注于图像的特定区域
- 全局分割(Global segmentation)- 关注于图像的全部区域
图像分割技术
[1] - 不连续性检测(Discontinuity detection)
基于 discontinuity,将图像划分为不同区域. 边缘检测的用武之地.
由于强度而产生的边缘不连续性被识别,并用于建立区域边界,如,直方图过滤(Histogram filtering) 和轮廓检测(contour detection).
[2] - 相似性检测(Similarity detection)
基于相似性(resemblance)将图像划分为不同区域.
阈值化(Thresholding)、区域扩展(area expansion)、区域拆分和合并(region splitting and merging)等,都属于该类.
根据既定规则,将图片话费为一组具有可区分特征的集群(cluster),如,Kmeans、颜色检测/分类.
[3] - 神经网络方法
这里主要基于 OpenCV 和 Scikit-learn 实现四种图像分割:
- 基于 K-means
- 基于 Contour Detection
- 基于 Thresholding
- 基于 Color Masking
测试例示图片,
基于 K-means 图像分割
import matplotlib as plt
import numpy as np
import cv2
path = 'image.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))
输出如:
基于轮廓检测(Contour Detection)
import cv2
import matplotlib.pyplot as plt
import numpy as np
path = 'image.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)
输出如:
基于阈值(Thresholding)
import numpy as np
import matplotlib.pyplot as plt
from skimage.filters import threshold_otsu
import cv2
path ='image.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)
输出如:
基于颜色掩码(color mask)
import cv2
path ='image.jpg'
img = cv2.imread(path)
rgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
hsv_img = cv2.cvtColor(rgb_img, cv2.COLOR_RGB2HSV)
#定义HSV颜色区间范围
#blue
light_blue = (90, 70, 50)
dark_blue = (128, 255, 255)
#green
# light_green = (40, 40, 40)
# dark_greek = (70, 255, 255)
mask = cv2.inRange(hsv_img, light_blue, dark_blue)
result = cv2.bitwise_and(img, img, mask=mask)
输出如,