8-OpenCVSharp--常见阈值分割算法使用方法(全局阈值分割、自适应阈值分割、Otsu 阈值分割、双阈值分割)

专栏地址:

《 OpenCV功能使用详解200篇 》

《 OpenCV算子使用详解300篇 》

《 Halcon算子使用详解300篇 》

#持续更新 点击订阅


在 OpenCVSharp 中,阈值分割是一个常见的图像处理任务,它用于将图像中的像素根据特定条件(如亮度值)分成不同的类别。以下是常见阈值分割算法的全面分析:


1. 全局阈值分割 (Cv2.Threshold())

1.1 核心原理公式

全局阈值分割的核心思想是对每个像素与给定的阈值进行比较:

[
g(x, y) =
\begin{cases}
\text{maxval}, & \text{if } f(x, y) \geq T \
0, & \text{if } f(x, y) < T
\end{cases}
]

  • (f(x, y)):原始图像的像素值
  • (T):给定的全局阈值
  • (\text{maxval}):当像素值大于等于阈值时赋予的最大值
1.2 算法功能

全局阈值分割可以将图像中的前景与背景区分开来,通常用于二值化图像,使其更适合于后续的处理步骤。

1.3 对应算子
  • Cv2.Threshold() 算子用于执行全局阈值分割。
1.4 算子参数
Cv2.Threshold(Mat src, Mat dst, double thresh, double maxval, ThresholdTypes type);
  • src:输入图像(单通道灰度图像)。
  • dst:输出图像(处理后的二值化图像)。
  • thresh:全局阈值。
  • maxval:大于阈值的像素值设定。
  • type:阈值类型,如二值化、Otsu 自动阈值等。
1.5 使用场景
  • 背景与前景具有明显亮度差异的图像。
  • 实时视频处理中进行简单的目标检测。
1.6 使用注意事项
  • 阈值选择非常关键,错误的阈值会导致分割效果差。
  • 需要确保输入图像为灰度图,彩色图需要先转换为灰度图。
1.7 优缺点
  • 优点:简单、快速。
  • 缺点:对光照变化和噪声敏感。
1.8 运行时间优化方法
  • 自适应阈值:对于不同区域使用不同阈值来提高鲁棒性,适应光照变化。
1.9 算法实际案例
using OpenCvSharp;

// 读取图像
Mat src = Cv2.ImRead("image.jpg", ImreadModes.Grayscale);

// 进行全局阈值分割
Mat dst = new Mat();
Cv2.Threshold(src, dst, 127, 255, ThresholdTypes.Binary);

// 显示结果
Cv2.ImShow("Threshold Binary", dst);
Cv2.WaitKey(0);
Cv2.DestroyAllWindows();
1.10 案例细节

在这个例子中,首先将彩色图像转换为灰度图(通过 ImreadModes.Grayscale),然后使用全局阈值分割,将阈值设为 127,所有大于 127 的像素将设置为 255(白色),其余设置为 0(黑色)。

1.11 结合其他相关算法搭配使用
  • 可以与 Cv2.MorphologyEx() 搭配使用进行后处理,如腐蚀、膨胀等操作。
  • Cv2.Canny() 边缘检测结合,进行进一步的图像分析。
1.12 相似或平替算法
  • Otsu’s Thresholding:通过自动选择最佳阈值来进行图像分割,尤其适合双峰分布的图像。

2. 自适应阈值分割 (Cv2.AdaptiveThreshold())

2.1 核心原理公式

自适应阈值分割通过局部区域的平均值(或加权平均)来确定每个像素的阈值:

[
T(x, y) = \text{mean}(I(x, y)) - C
]

  • (\text{mean}(I(x, y))):邻域区域内像素的平均值
  • (C):常数,用于调整阈值的灵敏度
2.2 算法功能

自适应阈值分割能处理图像中光照不均的情况,尤其适合处理背景和前景亮度差异较大的图像。

2.3 对应算子
  • Cv2.AdaptiveThreshold() 算子用于执行自适应阈值分割。
2.4 算子参数
Cv2.AdaptiveThreshold(Mat src, Mat dst, double maxValue, AdaptiveThresholdTypes adaptiveMethod, ThresholdTypes thresholdType, int blockSize, double C);
  • src:输入图像(单通道灰度图像)。
  • dst:输出图像(处理后的二值化图像)。
  • maxValue:当像素值大于局部阈值时的最大值。
  • adaptiveMethod:自适应方法,如 GaussianCMeanC
  • thresholdType:阈值类型,通常为 BinaryBinaryInv
  • blockSize:计算局部阈值时使用的邻域大小,必须是奇数。
  • C:常数,用于从局部均值中减去的值。
2.5 使用场景
  • 适用于光照不均匀的图像,如文档图像、自然场景中的目标分割。
  • 常用于处理具有不同亮度条件的图像,如阳光直射或阴影区域。
2.6 使用注意事项
  • 块大小:选择合适的块大小非常重要,较小的块适合局部光照变化较小的图像,较大的块适合全图光照变化较大的图像。
  • 常数C:常数C决定了阈值的灵敏度,较大的C值使得算法更保守,较小的C值容易将背景判定为前景。
2.7 优缺点
  • 优点:适应光照变化强,能够自动调整阈值。
  • 缺点:计算复杂度较高,特别是大图像时会消耗较多的计算资源。
2.8 运行时间优化方法
  • 调整邻域块大小:使用较小的块大小可以减少计算量,但可能会损失一定的效果。
  • 并行处理:对于大图像,可以利用多线程或GPU加速来提高速度。
2.9 算法实际案例
using OpenCvSharp;

// 读取图像
Mat src = Cv2.ImRead("image.jpg", ImreadModes.Grayscale);

// 进行自适应阈值分割
Mat dst = new Mat();
Cv2.AdaptiveThreshold(src, dst, 255, AdaptiveThresholdTypes.GaussianC, ThresholdTypes.Binary, 11, 2);

// 显示结果
Cv2.ImShow("Adaptive Threshold", dst);
Cv2.WaitKey(0);
Cv2.DestroyAllWindows();
2.10 案例细节

在此例中,使用高斯加权均值计算局部区域的阈值,块大小为 11,常数C为2,这些参数适用于光照变化较大的图像。

2.11 结合其他相关算法搭配使用
  • 可与 Cv2.Canny() 边缘检测结合,进行图像的边缘提取。
  • 可与 Cv2.MorphologyEx() 的形态学操作结合,用于进一步处理自适应分割后的结果。
2.12 相似或平替算法
  • 局部二值模式 (Local Binary Pattern, LBP):可用于图像的纹理分类,虽然它与阈值分割不同,但可以用作另一种分割的替代方法。

3. Otsu 阈值分割 (Cv2.Threshold() with Otsu)

3.1 核心原理公式

Otsu 方法通过最大化类间方差来自动选择最佳的阈值。公式如下:

[
\sigma_B^2(T) = \frac{N_1(T)(\mu_1(T) - \mu_T)^2 + N_2(T)(\mu_2(T) - \mu_T)^2}{N_1(T) + N_2(T)}
]

其中:

  • (N_1(T)) 和 (N_2(T)) 是阈值 (T) 分割后的前景和背景区域的像素数目。
  • (\mu_1(T)) 和 (\mu_2(T)) 分别是前景和背景区域的均值。
  • (\mu_T) 是整个图像的平均值。

通过这个公式,Otsu 方法计算出一个最佳阈值 (T^*),使得前景和背景的类间方差最大,从而实现最优的图像分割。

3.2 算法功能

Otsu 阈值分割可以自动计算出图像的最佳阈值,而不需要人工选择阈值。适用于图像的前景和背景具有明显亮度差异的情况,且图像的灰度值分布呈双峰。

3.3 对应算子
  • Cv2.Threshold() 算子,配合 ThresholdTypes.Otsu 类型来实现 Otsu 阈值自动分割。
3.4 算子参数
Cv2.Threshold(Mat src, Mat dst, double thresh, double maxval, ThresholdTypes type);
  • src:输入图像(单通道灰度图像)。
  • dst:输出图像(经过分割的二值化图像)。
  • thresh:通常设为 0(Otsu 方法会自动计算)。
  • maxval:大于最佳阈值时的像素值。
  • typeThresholdTypes.Otsu,表示使用 Otsu 算法来计算阈值。
3.5 使用场景
  • 适用于图像灰度分布呈双峰的情况,通常是前景和背景有显著区分。
  • 用于医学图像、文档分析、二值化图像等领域。
3.6 使用注意事项
  • Otsu 方法通常适用于图像灰度值分布明确、双峰分布的图像。如果图像的灰度值分布不是双峰的,Otsu 方法的效果可能不佳。
  • 处理噪声较多的图像时,Otsu 方法可能会受到噪声的影响,导致不理想的分割结果。
3.7 优缺点
  • 优点
    • 无需人工选择阈值,自动计算。
    • 适用于双峰分布的图像。
  • 缺点
    • 对图像的噪声敏感。
    • 只适合单一阈值的分割,无法处理复杂的分割问题(如多区域分割)。
3.8 运行时间优化方法
  • 噪声过滤:在应用 Otsu 阈值之前,进行噪声去除(如使用中值滤波、均值滤波等)可以提高其稳定性。
  • 多线程或GPU加速:对于大规模图像,可以使用并行计算来加速 Otsu 阈值的计算过程。
3.9 算法实际案例
using OpenCvSharp;

// 读取图像
Mat src = Cv2.ImRead("image.jpg", ImreadModes.Grayscale);

// 进行 Otsu 阈值分割
Mat dst = new Mat();
Cv2.Threshold(src, dst, 0, 255, ThresholdTypes.Binary | ThresholdTypes.Otsu);

// 显示结果
Cv2.ImShow("Otsu Threshold", dst);
Cv2.WaitKey(0);
Cv2.DestroyAllWindows();
3.10 案例细节

在这个例子中,阈值被设为 0,表示让 Otsu 算法自动计算最佳的阈值。在 ThresholdTypes.Binary | ThresholdTypes.Otsu 中,Binary 表示分割为二值图像,Otsu 表示自动选择最佳阈值。

3.11 结合其他相关算法搭配使用
  • 可以与 噪声去除算法(如中值滤波、Gaussian滤波)结合,先去噪再应用 Otsu 阈值分割。
  • 可以与 形态学操作(如膨胀、腐蚀)结合,进一步优化分割结果,去除小的噪点或连接分离的区域。
3.12 相似或平替算法
  • K-means 聚类:通过聚类分析进行分割,适用于复杂分布的图像,尤其是多峰分布的图像。
  • 最大熵阈值法:通过最大化图像熵来选择阈值,适用于光照不均的图像。

4. 迭代法(比如 K-means 聚类法)

4.1 核心原理公式

K-means 是一种聚类算法,通过迭代来最小化图像中每个像素点到其对应簇中心的距离,从而实现图像的分割。其基本公式为:

[
J = \sum_{i=1}^{N} \sum_{k=1}^{K} r_{ik} ||x_i - c_k||^2
]

其中:

  • (x_i) 是像素值,(c_k) 是簇中心。
  • (r_{ik}) 是指示函数,表示像素 (x_i) 是否属于簇 (k)。
  • (J) 是目标函数,表示簇内的距离平方和,目标是最小化这个值。
4.2 算法功能

K-means 聚类方法通过对像素进行聚类,将图像分为 K 个区域。对于阈值分割,可以将图像的灰度值进行聚类,基于聚类结果确定分割阈值。

4.3 对应算子
  • OpenCV 提供了 Cv2.Kmeans() 算子来执行 K-means 聚类,虽然它本身并非一个阈值分割方法,但可以用于图像的阈值分割。
4.4 算子参数
Cv2.Kmeans(Mat data, int K, Mat labels, TermCriteria criteria, int attempts, KMeansFlags flags, Mat centers);
  • data:输入数据,通常是图像的像素值。
  • K:簇的数量。
  • labels:每个数据点所属簇的标签。
  • criteria:停止条件,通常是迭代次数或变化的最小阈值。
  • attempts:算法运行的次数。
  • flags:使用的标志位。
  • centers:每个簇的中心。
4.5 使用场景
  • 适用于图像中像素值分布不均匀的情况。
  • 对于需要分割多个区域的图像,K-means 聚类方法可以有效地找到多个阈值。
4.6 使用注意事项
  • K-means 聚类方法要求输入数据是高维的,因此图像需要展开成一维数据进行处理,或者使用多通道数据进行多类分割。
  • 算法需要预先指定簇的数目(K值),选择合适的 K 值是关键。
4.7 优缺点
  • 优点
    • 适用于多区域的图像分割,能够处理复杂的图像。
    • 不依赖于图像的灰度分布,可以应对不规则图像。
  • 缺点
    • 对初始值敏感,容易陷入局部最优解。
    • 对噪声敏感,需要进行预处理。
4.8 运行时间优化方法
  • 减少簇数:选择合理的 K 值可以减少计算量。
  • 并行化计算:可以通过多线程或GPU加速来提高K-means的计算效率。
4.9 算法实际案例(续)
using OpenCvSharp;

// 读取图像并转换为单通道灰度图像
Mat src = Cv2.ImRead("image.jpg", ImreadModes.Grayscale);
src = src.Reshape(1, src.Rows * src.Cols);  // 将图像转换为一维数据,适合进行聚类

// 转换数据类型为浮动类型
src.ConvertTo(src, MatType.CV_32F);

// 设定K值(簇数)和聚类的参数
int K = 2;  // 设定为2个簇(背景和前景)
Mat labels = new Mat();  // 用于存储每个像素的标签
Mat centers = new Mat();  // 用于存储每个簇的中心

// 设置终止条件:最多迭代100次,或者当簇中心的变化小于1e-4时停止
TermCriteria criteria = new TermCriteria(CriteriaTypes.Eps | CriteriaTypes.MaxIter, 100, 1e-4);

// 执行 K-means 聚类算法
Cv2.Kmeans(src, K, labels, criteria, 10, KMeansFlags.PpCenters, centers);

// 将聚类结果还原为图像
Mat clusteredImage = new Mat(src.Rows, src.Cols, MatType.CV_8U);
for (int i = 0; i < src.Rows * src.Cols; i++)
{
    int label = labels.At<int>(i);
    clusteredImage.Set(i / src.Cols, i % src.Cols, label == 0 ? 0 : 255);  // 根据标签设定前景或背景
}

// 显示结果
Cv2.ImShow("Clustered Image", clusteredImage);
Cv2.WaitKey(0);
Cv2.DestroyAllWindows();
4.10 案例细节
  • 这里将原图像展开为一维数组,转换为浮动类型(CV_32F),这是因为 K-means 聚类算法需要处理浮动类型数据。
  • TermCriteria 设置了终止条件,算法最多迭代 100 次,或者当簇中心变化小于 1e-4 时停止。
  • KMeansFlags.PpCenters 是选择聚类中心的初始化方法之一,表示使用 K-means++ 方法初始化中心点。
  • src.Rows * src.Cols 是图像的像素总数,用来表示一维数组的大小。
  • 最后,通过 labels 中的每个像素标签来决定其属于哪个簇,按照标签值将图像重构为聚类后的二值图像。
4.11 使用场景

K-means 聚类广泛应用于:

  • 图像分割,尤其是需要多区域分割时。
  • 噪声较大的图像,K-means 能够自动将不同区域分开。
  • 复杂图像,例如图像中有多个前景或背景区域的情况。
4.12 使用注意事项
  • 选择 K 值:K-means 聚类方法需要手动选择 K 值,即聚类簇的数量。对于简单的二值化任务,K 值通常为 2。但对于复杂的图像,可能需要选择更多的簇,并通过实验来优化 K 值。
  • 聚类初始值敏感性:K-means 算法对初始簇中心点的选择比较敏感,使用 K-means++ 方法可以缓解这个问题。
  • 噪声和离群点的处理:K-means 对噪声和离群点较为敏感,因此在进行聚类前,最好先对图像进行去噪处理。
4.13 优缺点
  • 优点
    • 能处理多类的图像分割,不仅仅局限于二值化。
    • 可适应复杂的图像结构,尤其是在多个区域分离的场景下表现良好。
    • 聚类的过程可以自动分组,并且基于距离度量,聚类效果较为直观。
  • 缺点
    • 算法对初始簇中心比较敏感,可能导致局部最优解。
    • 必须事先指定簇数 K,对于某些情况下簇数的选择可能不太直观。
    • 对噪声较为敏感,可能影响分割的准确性。
4.14 运行时间优化方法
  • 并行化计算:K-means 可以通过并行计算加速,特别是在处理大规模图像时,使用多线程或 GPU 加速可以显著提升性能。
  • 提前过滤:对图像进行初步的预处理,去除噪声或进行降维,能够减少 K-means 的计算复杂度。
  • 减少 K 值:对于简单的二值图像,选择 K=2,可以大大减少计算时间。

总结

  • Otsu 阈值分割 是一个非常高效的自动分割方法,适用于图像具有明显的双峰灰度分布时。它通过最大化类间方差来自动选择最佳阈值,简便易用。
  • K-means 聚类 是一种基于距离的聚类算法,通过对像素进行分组,实现图像分割。它适用于复杂场景,能够分割多区域的图像,但需要预先确定聚类簇的数量 K。

在实际应用中,Otsu 通常适用于简单的二值化任务,而 K-means 则适用于多区域或复杂图像分割。可以根据具体的任务需求选择合适的算法,或结合使用这两种方法来提升图像分割的精度和效果。

专栏地址:

《 OpenCV功能使用详解200篇 》

《 OpenCV算子使用详解300篇 》

《 Halcon算子使用详解300篇 》

#持续更新 点击订阅

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

观视界

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值