当前位置:   article > 正文

OpenCV||超详细的图像分割

OpenCV||超详细的图像分割

图像分割是数字图像分析中的重要环节,在整个研究中起着承前启后的作用,既是对所有图像预处理效果的一个检验,也是后续进行图像分析与解译的基础!

图像分割是由图像处理到图像分析的关键步骤!

壹、图像分割的数学定义

  • 对一幅图像分割所得到的全部子区域的总和应能包括图像中所有的像素,或者说分割应将图像中的每一个像素都分进某个子区域中。
  • 在分割的结果中各个子区域是互不重叠的,也就是互相独立的;或者说在分割结果中一个像素不能同时属于两个子区域。
  • 在分隔结果中每一个子区域都有独特的特性,或者说属于同一个区域中的像素应该具有某些相同的特性。
  • 在分割结果中不同的子区域巨头不同的特性,没有公共的元素,或者说属于不同区域的像素应该具有一些不同的特性。
  • 分割结果中同一个子区域内的像素是联通的,即同一个子区域内任何两个像素在该子区域内互相连通,或者说分割得到的区域是一个连通单元。

贰、图像分割的分类方法

1、基于阈值化的分割方法

目标或背景的相邻像素间的灰度值是相似的,而不同的目标或背景的像素在灰度上有差异,反映在直方图上,不同目标和背景对应不同的峰,选区的阈值应位于两个峰之间的谷处。如果图像中具有多类目标,则直方图将呈现多峰特性,相邻两峰之间的谷即为多阈值分割的阈值。

阈值分割准则

  • P分位数(P-title法)
  • 最频值法(Mode法)
  • Ostu法
  • 最大熵方法
  • 最小误差法
  • 矩量保持法

 2、基于边缘的分割方法

参考图像边缘检测部分。

步骤:

  1. 加载图像:将待处理的图像加载到内存中。
  2. 预处理:根据需要,对图像进行预处理操作,如去噪、平滑、增强等,以提高边缘检测的效果。
  3. 边缘检测:应用边缘检测算法(如Canny边缘检测、Sobel算子等)检测图像中的边缘点。
  4. 边缘连接:根据一定的准则或规则,将边缘点连接成边缘曲线或轮廓。常用的边缘连接方法包括基于阈值、梯度方向等准则。
  5. 边缘细化:对边缘曲线进行细化处理,消除冗余的像素点,得到更准确的边界线。
  6. 区域填充:根据边界线将图像分割成不同的区域,可以使用基于种子点的区域生长算法等方法进行区域填充。
  7. 结果显示:将分割后的图像进行显示或保存。

3、基于区域的分割方法

  1. 区域生长法

    • 基本思想:从一组种子点开始,根据某种相似性准则(如灰度级、颜色、纹理等),将邻近的像素点加入到相应的种子点所在的区域中,直到没有更多的像素点可以加入为止。
    • 实现步骤
      1. 选择一组种子点。
      2. 设定相似性准则。
      3. 遍历图像的每个像素点,将其与种子点所在区域的像素点进行比较。
      4. 如果满足相似性准则,则将该像素点加入到相应的区域中。
      5. 重复步骤3和4,直到所有像素点都被分配到相应的区域中。
    • 特点:区域生长法对噪声相对不敏感,但计算复杂度较高,且需要预先确定种子点和相似性准则。
  2. 区域分裂与合并法

    • 基本思想:首先将图像分成若干个子区域,然后根据区域之间的相似性进行分裂或合并操作,直到满足某种停止准则为止。
    • 实现步骤
      1. 将图像分成若干初始子区域。
      2. 计算相邻子区域之间的相似性。
      3. 如果相邻子区域之间的相似性小于某个阈值,则进行分裂操作;如果相似性大于某个阈值,则进行合并操作。
      4. 重复步骤2和3,直到满足停止准则(如区域数量达到预设值、区域间的相似性达到预设阈值等)。
    • 特点:区域分裂与合并法能够处理具有复杂结构的图像,但计算复杂度也较高,且需要预先确定分裂和合并的准则。
  3. 水平集方法

    • 基本思想:将图像分割问题转化为求解能量函数最小化的问题。通过演化轮廓线(水平集)来逼近图像中的目标边界。
    • 实现步骤
      1. 定义能量函数,该函数与轮廓线的位置和形状有关。
      2. 初始化轮廓线(水平集)。
      3. 通过迭代优化算法(如梯度下降法)求解能量函数的最小值。
      4. 在迭代过程中,根据能量函数的变化更新轮廓线的位置和形状。
      5. 当能量函数达到最小值或满足某种停止准则时,停止迭代。
      6. 将最终得到的轮廓线作为图像分割的结果。
    • 特点:水平集方法能够处理具有复杂边界的图像,且对噪声和初始轮廓线的选择具有一定的鲁棒性。但该方法计算复杂度较高,且需要选择合适的能量函数和迭代优化算法。
  4. 图割方法

    • 基本思想:将图像表示为图的形式,其中像素作为图的顶点,像素之间的关系作为图的边。通过最小化图中顶点之间的权重(如基于像素的颜色差异、纹理差异等),将图像分割为不同的区域。
    • 实现步骤
      1. 构建图像的图表示。
      2. 定义顶点和边的权重。
      3. 使用图割算法(如最小割最大流算法)求解最优的分割方案。
      4. 将分割结果映射回原图像。
    • 特点:图割方法能够处理具有复杂结构和相互重叠的物体图像,且对噪声和光照变化具有一定的鲁棒性。但该方法计算复杂度较高,且需要选择合适的图割算法和权重函数。

4、基于神经网络的分割方法

参考以下几篇文章:

基于神经网络的图像分割_基于图神经网络的医学图像分割-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/weixin_55073640/article/details/123039854基于CNN卷积神经网络的图像分割matlab仿真 - 知乎 (zhihu.com)icon-default.png?t=N7T8https://zhuanlan.zhihu.com/p/648715632基于深度学习技术的图像分割 (baidu.com)icon-default.png?t=N7T8https://baijiahao.baidu.com/s?id=1783952474192487844&wfr=spider&for=pc

5、基于聚类的分割方法

3个要点:

①选定某种距离度量作为样本间的相似性度量;

②确定某个评价聚类结果质量的准则函数;

③给定某个初始分类,然后通过迭代算法找出使准则函数取得极值的最好聚类结果。

分类:

  • 硬聚类算法
  • 模糊聚类算法
  • 可能性聚类算法

叄、OpenCV进行图像分割

1、固定阈值分割

API:

retval, dst = cv2.threshold(src, thresh, maxval, type[, dst])

 前五个enum的数学实现原理:

 示例:

  1. import cv2
  2. import numpy as np
  3. # 读取图像
  4. image = cv2.imread('image.jpg')
  5. # 转换为灰度图
  6. gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  7. # 应用阈值分割
  8. _, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
  9. # 显示结果
  10. cv2.imshow('Original Image', image)
  11. cv2.imshow('Threshold Image', thresh)
  12. cv2.waitKey(0)
  13. cv2.destroyAllWindows()

 2、自适应阈值分割

  1. import cv2
  2. # 读取图像
  3. image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE) # 以灰度模式读取图像
  4. # 应用自适应阈值分割
  5. # 参数:
  6. # src: 源图像,必须是8位单通道图像
  7. # maxValue: 最大值,用于阈值化后的像素值(通常为255
  8. # adaptiveMethod: 自适应阈值算法
  9. # - cv2.ADAPTIVE_THRESH_MEAN_C: 阈值设置为邻近区域的平均值减去C
  10. # - cv2.ADAPTIVE_THRESH_GAUSSIAN_C: 阈值设置为邻近区域的加权和(高斯加权)减去C
  11. # thresholdType: 阈值类型
  12. # - cv2.THRESH_BINARY
  13. # - cv2.THRESH_BINARY_INV
  14. # blockSize: 块的大小(必须是正奇数)
  15. # C: 从平均值或加权平均值中减去的常数
  16. thresh = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
  17. cv2.THRESH_BINARY, 11, 2)
  18. # 显示结果
  19. cv2.imshow('Original Image', image)
  20. cv2.imshow('Adaptive Threshold Image', thresh)
  21. cv2.waitKey(0)
  22. cv2.destroyAllWindows()

3、基于K-means聚类

  1. import cv2
  2. import numpy as np
  3. # 读取图像
  4. image = cv2.imread('image.jpg')
  5. data = image.reshape((-1, 3)) # 重塑成二维数组
  6. # 应用K-means算法
  7. criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 0.1)
  8. K = 3 # 假设我们想将图像分割成3个颜色区域
  9. _, labels, centers = cv2.kmeans(data, K, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
  10. # 将聚类标签转换回图像形式
  11. segmented_image = labels.reshape(image.shape[:2])
  12. # 显示结果
  13. cv2.imshow('Segmented Image', segmented_image.astype(np.uint8))
  14. cv2.waitKey(0)
  15. cv2.destroyAllWindows()
  16. # 注意:这里的结果是一个颜色标签图,你可能需要根据centers数组将标签映射回具体的颜色值。

肆、OpenCV进行彩色图像分割

1. 使用颜色范围进行分割

通过指定颜色空间(如HSV)中的颜色范围来分割特定颜色的对象。HSV颜色空间对于颜色分割来说比RGB更加直观和有效,因为它将颜色信息分解为色调(Hue)、饱和度(Saturation)和亮度(Value)三个独立的分量。

  1. import cv2
  2. import numpy as np
  3. # 读取图像
  4. image = cv2.imread('image.jpg')
  5. # 转换到HSV颜色空间
  6. hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
  7. # 定义蓝色的范围
  8. # 注意:HSV值在0-180, 0-255, 0-255之间,但在OpenCV中,Hue被归一化到0-179
  9. lower_blue = np.array([110, 50, 50])
  10. upper_blue = np.array([130, 255, 255])
  11. # 根据颜色范围创建掩模
  12. mask = cv2.inRange(hsv, lower_blue, upper_blue)
  13. # 使用掩模对原图像进行位运算,提取蓝色部分
  14. result = cv2.bitwise_and(image, image, mask=mask)
  15. # 显示结果
  16. cv2.imshow('Original Image', image)
  17. cv2.imshow('Mask', mask)
  18. cv2.imshow('Result', result)
  19. cv2.waitKey(0)
  20. cv2.destroyAllWindows()

2. 使用K-means聚类进行分割

虽然K-means本身不是直接用于图像分割的算法,但它可以用于将图像中的像素聚类成K个不同的颜色组,从而可以用于图像分割的预处理步骤或后续分析。

  1. import cv2
  2. import numpy as np
  3. # 读取图像并重塑为二维数组
  4. image = cv2.imread('image.jpg')
  5. data = image.reshape((-1, 3))
  6. # 应用K-means算法
  7. criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 0.1)
  8. K = 3 # 假设我们想将图像分割成3个颜色区域
  9. _, labels, centers = cv2.kmeans(data, K, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
  10. # 将聚类标签转换回图像形式
  11. segmented_image = labels.reshape(image.shape[:2])
  12. # 为了可视化,我们可以将标签映射回具体的颜色值(这里为了简单起见,我们直接显示标签)
  13. segmented_image = segmented_image.astype(np.uint8) * 255 / K
  14. # 显示结果
  15. cv2.imshow('Segmented Image', segmented_image)
  16. cv2.waitKey(0)
  17. cv2.destroyAllWindows()
  18. # 注意:这里的结果是一个颜色标签图,你可能需要根据centers数组将标签映射回具体的颜色值。

伍、grabCut算法分割图像

陆、floodFill漫水填充分割

柒、分水岭分割法

末、基于kohonen网络的snake图像分割法

基于Kohonen网络的Snake图像分割法是一种结合了自组织映射(Self-Organizing Map, SOM)网络和Snake模型(也称为主动轮廓模型或动态轮廓模型)的图像分割技术。这种方法通过整合SOM网络的学习能力和Snake模型的轮廓变形能力,实现了对图像中目标区域的有效分割。

1. Kohonen网络(SOM网络)

基本原理
Kohonen网络,也称为自组织映射网络,是一种无监督学习算法,用于将高维输入数据映射到低维空间(通常是二维网格),同时保持数据的拓扑关系。在SOM网络中,每个神经元(或称为节点)代表一个权重向量,这些权重向量通过竞争学习过程逐渐调整到与输入数据的特定部分相匹配。

在图像分割中的应用
在图像分割中,SOM网络可以用于将图像像素或特征映射到不同的类别或区域,从而实现对图像内容的初步划分。通过训练SOM网络,可以将具有相似特征的像素或区域聚类到一起,为后续的Snake模型提供初始轮廓或分割区域的指导。

2. Snake模型

基本原理
Snake模型是一种基于能量最小化的主动轮廓模型,它通过定义一个能量函数来控制轮廓线的变形,使得轮廓线能够收敛到图像中的目标边缘。Snake模型的能量函数通常由内部能量和外部能量两部分组成,内部能量控制轮廓线的平滑性和连续性,而外部能量则使轮廓线向图像中的特征边缘靠拢。

在图像分割中的应用
Snake模型在图像分割中表现出色,特别是在处理复杂背景和不规则形状的目标时。通过初始化一个大致的轮廓线,Snake模型能够自动调整轮廓线的形状和位置,以准确分割出目标区域。然而,Snake模型对初始轮廓的位置较为敏感,且容易陷入局部最优解。

3. 基于Kohonen网络的Snake图像分割法

结合方式
基于Kohonen网络的Snake图像分割法通过以下方式结合SOM网络和Snake模型:

  • 初始轮廓提取:首先,利用SOM网络对图像进行预处理和聚类分析,提取出与目标区域相关的初步轮廓或分割区域。这些轮廓或区域可以作为Snake模型的初始轮廓。
  • 轮廓优化:然后,利用Snake模型的能量最小化原理,对初始轮廓进行进一步的优化和调整。通过不断迭代计算能量函数并更新轮廓线的位置,使得轮廓线能够逐渐收敛到图像中的目标边缘。

优势

  • 提高分割准确性:通过SOM网络的初步聚类分析,可以为Snake模型提供更为准确的初始轮廓,从而提高分割的准确性。
  • 增强鲁棒性:SOM网络的自学习能力使得该方法能够适应不同的图像特征和分割需求,增强了算法的鲁棒性。
  • 自动化程度高:整个分割过程可以自动完成,无需人工干预,提高了图像处理的效率。

具体参考这篇文章:

图像分割—Snake模型 - 知乎 (zhihu.com)icon-default.png?t=N7T8https://zhuanlan.zhihu.com/p/621254952 

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/958406
推荐阅读
相关标签
  

闽ICP备14008679号