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)

输出如,

Last modification:December 14th, 2021 at 01:12 pm