OpenCV-Python:图像分割

目录

1.本机环境

2.图像分割介绍

3.图像分割算法分类

4.OpenCV-Python的图像分割算法

5.分水岭算法

5.1算法原理

5.2算法改进 

5.3算法步骤

5.4 代码展示及分析


1.本机环境

win10  64位企业版系统

python版本:3.6.8 (x64)

opencv版本:3.4.2.16

IDE:pycharm2017(Ananconda  3.5.2)

2.图像分割介绍

        图像分割是指将图像划分为具有不同语义或特征的不同区域的过程。图像分割在计算机视觉和图像处理中是一个重要的任务,它可以用于目标检测、图像分析、图像增强、图像重建等应用。

3.图像分割算法分类

图像分割算法可以根据不同的原理和方法进行分类。下面是一些常见的图像分割算法:

1.阈值分割:基于像素灰度值的阈值进行分割。可以使用全局阈值、自适应阈值或多阈值来实现。

2.基于边缘的分割:通过检测图像中的边缘来实现分割。常见的边缘检测算法包括Sobel、Canny等。

3.基于区域的分割:将图像分割为具有相似属性的区域。常见的算法包括基于区域增长、分水岭算法等。

4.基于聚类的分割:将图像中的像素聚类为具有相似特征的群体。常见的算法包括K-means、Mean-shift等。

5.基于图论的分割:将图像中的像素表示为图的节点,并使用图论算法进行分割。常见的算法包括最小割、谱聚类等。

4.OpenCV-Python的图像分割算法

在opencv-python中,提供了一些常用的图像分割算法的实现。例如:

cv2.threshold()函数可以用于实现基于阈值的分割。

cv2.Canny()函数可以用于实现基于边缘的分割。

cv2.watershed()函数可以用于实现基于分水岭算法的分割。

cv2.kmeans()函数可以用于实现基于聚类的分割。

这些函数提供了一些参数来调整算法的性能和结果。可以根据具体的需求和图像特点选择合适的算法和参数来进行图像分割操作。

5.分水岭算法

        本节重点介绍一下“使用分水岭算法基于掩模的图像分割”相关技术,主要用到OpenCV-Python中的cv2.watershed()函数。

5.1算法原理

        任何一副灰度图像都可以看成拓扑平面,灰度值高的区域可以看成是山峰,灰度值低的区域可以看成是山谷。我们向每一个山谷中灌不同颜色的水。随着水位的升高,不同山谷的水就会相汇合,为了阻止不同山谷的水汇合,我们在水汇合的地方构建堤坝。不停的灌水不停的构建堤坝,直到所有的山峰都被水淹没。我们构建好的堤坝就是对图像的分割。这就是分水岭算法的大致原理。

5.2算法改进 

        原始的分水岭算法原理往往会得到过度分割的结果,这是由噪声或者图像中其他不规律的因素造成的。为了减少这种影响,OpenCV 使用了基于掩模的分水岭算法。在这种算法中我们需要设置哪些山谷点会汇合,哪些不会,这是一种交互式的图像分割。我们要做的就是给我们已知的对打上不同的标签。如果某个区域肯定是前景或对象,就使用某个颜色或灰度值标签标记它。如果某个
区域肯定不是对像而是背景就使用另外一个颜色标签标记。而剩下的不能确定是前景还是背景的区域就用0 标记,这就是我们的标签。然后实施分水岭算法,每一次灌水,我们的标签就会更新,当两个不同颜色的标签相遇时就构建堤坝,直到将所有山峰淹没,最后我们得到的边界对象(堤坝)的值为-1。

5.3算法步骤

1.预处理对原始图像进行平滑处理以减少噪声,并可能采用梯度算子来突出边缘信息。

2.计算梯度:计算图像的梯度图,该图表示图像亮度变化的强度和方向。梯度图用于模拟地形的高度。

3.标记标记物:在梯度图中标记一些"种子"点作为水源,即山谷的最低点。这些种子点可以是自动检测到的局部极小值,也可以是通过某种方式人为指定的。

4.模拟水的填充过程:从种子点开始,模拟水逐渐填充整个地形的过程。当不同水域相遇时,创建"分水岭",即分割线。

5.生成分割结果:利用分水岭边界,将图像划分为独立的区域。

5.4 代码展示及分析

在OpenCV-Python中,可以使用cv2.watershed函数来实现分水岭图像分割算法。以下是一个简单的示例代码:

import cv2
import numpy as np

# 读取图像
image = cv2.imread('image.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 预处理 - 二值化
_, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

# 形态学操作 - 开运算
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel, iterations=2)

# 寻找前景区域的标记
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
_, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)

# 寻找背景区域的标记
sure_bg = cv2.dilate(opening, kernel, iterations=3)

# 标记未知区域
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)

# 标记控制的分水岭算法
_, markers = cv2.connectedComponents(sure_fg)
markers = markers + 1
markers[unknown == 255] = 0
markers = cv2.watershed(image, markers)

# 将分割结果可视化
image[markers == -1] = [0, 0, 255]

cv2.imshow('Segmented Image', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

        这段代码首先读取一张图像,并将其转换为灰度图像。然后,通过二值化和形态学操作进行图像预处理。接下来,使用距离变换和阈值化找到前景区域的标记。然后,通过膨胀操作找到背景区域的标记。接着,通过减法操作找到未知区域的标记。最后,使用cv2.watershed函数进行分水岭算法,并将分割结果可视化。

你可能感兴趣的:(opencv-python,opencv,python,图像分割,分水岭算法)