【C++ OpenCV】阈值二值化、阈值反二值化、截断、阈值取零、阈值反取零、自适应阈值使用方法以及时机

图像二值化

一、阈值概念

阈值:简单来说就是一把分割图像像素的标尺,在二值化处理中有固定阈值和自适应阈值两种形式。

那么什么时候用固定阈值,什么时候使用自适应阈值呢?

答:当图像质量较好,且目标和背景容易区分时,可以采用固定阈值

当图像质量差,且有阴影过度,虽然使用大津法和三角形法也可以自己寻找阈值,但整个图像阈值都是相同,所以最终分割效果较差。

所以,可以用自适应,或者将整个图像分割成几行几列,对每个部分运用大津法或者三角形法,最后将图形整合,这样每一部分的阈值就不相同,分割效果也会更好。

二、固定阈值二值化threshold()

double**threshold**(    
​
InputArray src,
 OutputArray dst,
 double thresh,
 double maxval,
 int type     阈值类型如下
 );

2.1阈值类型

binary:二进制的

type 作用
THRESH_BINARY 灰度值高于阈值的为最大,其余为0
THRESH_BINARY_INV 灰度值高于阈值的为0,其余为最大
THRESH_TOZERO 高于阈值的为0,低于阈值的保留
THRESH_TOZERO_INV 高于阈值的保留,低于阈值的为0
THRESH_TRUNC 高于阈值的为阈值,低于阈值的保留
THRESH_OTSU 大津法自动求阈值 THRESH_OTUS 大津阈值算法配合其它阈值使用,最适用于双波峰。
THRESH_TRIANGLE 三角形法自动求阈值 根据直方图自行计算阈值,最适用于单个波峰,最开始用于医学分割细胞等

img

THRESH_OTUS  大津阈值算法配合其它阈值使用,最适用于双波峰。

THRESH_TRIANGLE  三角形的二值化法根据直方图自行计算阈值,最适用于单个波峰,最开始用于医学分割细胞等

大津法(Otsu's method)和三角形法(Triangle method)是两种常用于图像处理中自动确定阈值的方法。

2.2 大津法原理:

大津法是一种基于直方图的自适应阈值确定方法,其基本原理是寻找一个阈值,使得根据该阈值将图像分割成前景(目标)和背景两部分后,目标与背景之间的类间方差最大。类间方差用于衡量目标和背景之间的差异程度,方差越大表示目标和背景之间的差异越大,分割效果越好。

大津法的步骤如下: 1) 计算图像的灰度直方图。 2) 对每个可能的阈值t(0到255),计算目标和背景的像素数目和像素值的平均值。 3) 根据当前阈值t,计算类间方差作为衡量指标:类间方差 = 目标像素数目 * 背景像素数目 * (目标平均灰度值 - 背景平均灰度值)^2。 4) 找到使得类间方差最大的阈值作为最终阈值。

2.3 三角形法原理:

三角形法是一种基于直方图的阈值选择方法,其基本原理是找到直方图的峰值处对应的阈值,通过将直方图峰值对应的斜率定义为三角形的高,并找到使得该三角形面积最大的阈值作为最终阈值。

三角形法的步骤如下: 1) 计算图像的灰度直方图。 2) 找到直方图的峰值处,即直方图中像素数目最多的灰度级别。 3) 以峰值处对应的灰度级别为基准,向两侧寻找直方图中像素数目小于峰值处像素数目一半的两个灰度级别作为边界。 4) 计算基准灰度级别和两个边界之间的直方图的斜率,斜率定义为三角形的高。在这种情况下,可以将这两个边界之间的距离作为三角形的底部。 5) 找到使得三角形面积最大的斜率对应的阈值作为最终阈值。另一种做法是将直方图整体的范围作为底部,即使用整个直方图的最小和最大灰度级别之间的距离作为三角形的底部。

三、自适应阈值处理

上边固定阈值的方法适用于比较理想的场景,实际在使用时,由于图片的光线条件变化,固定的阈值往往不能很好的将目标与背景分离,这个时候就需要用到自适应阈值的方法,自适应阈值会根据一小片区域的值来动态调整阈值,使最后的输出更合理。用到的函数是adaptiveThreshold()

adaptiveThreshold(
    src, 
    dst,
    maxval, 
    thresh_type, //只能为BINARY或者其INV
    type, 
    Block 
    Size, 
    C             )
  • thresh_type: 阈值的计算方法,包含以下2种类型:

类型 含义
cv2.ADAPTIVE_THRESH_MEAN_C 计算均值时每个像素的权值是相等的
cv2.ADAPTIVE_THRESH_GAUSSIAN_C 计算均值时每个像素的权值根据其到中心点的距离通过高斯方程得到
  • Block Size: 图片中分块的大小

  • C :阈值计算方法中的常数项

关于Block Size和C的取值,一般Block Size取3~17比较合适,C也不宜太大,可取3~9,具体的值需要自己测试调节。

下图为对一幅图片用不同方法进行阈值化时的效果,可以看到,相对于一般的阈值化操作,当图像中出现较大的明暗差异时,自适应阈值是非常有效的

img

函数cvAdaptiveThreshold的确可以将灰度图像二值化,但它的主要功能应该是边缘提取,并且参数C主要是用来控制边缘的类型和粗细的.

关键是里面的block_size参数,该参数是决定局部阈值的block的大小,

1)当block很小时,如block_size=3 or 5 or 7时,“自适应”的程度很高,即容易出现block里面的像素值都差不多,这样便无法二值化,而只能在边缘等梯度大的地方实现二值化,结果显得它是边缘提取函数。

2)当把block_size设为比较大的值时,如block_size=21 or 31 or41时,cvAdaptiveThreshold便是二值化函数了 3)src与dst 这两个都要是单通道的图像。 参数blockSize: 1.要取奇数,如果取偶数运行后就会报错!!原因看源码,发现要做一个掩模,所以参数必须是奇数。OpenCV也做了一个检测,在函数adaptiveThreshold一开始就有CV_Assert( blockSize %2 == 1 && blockSize > 1 )。

2.cvAdaptiveThreshold既可以做边缘提取,也可以实现二值化,是由你所选择的邻域所确定的,如果你所选择的邻域非常小(比如3×3),那么很显然阈值的“自适应程度”就非常高,这在结果图像中就表现为边缘检测的效果。如果邻域选择的比较大(比如31×31),那么阈值的“自适应程度”就比较低,这在结果图像中就表现为二值化的效果。

3.一般情况下,滤波器宽度应该大于被识别物体的宽度。block_size太小,无法代表背景,太大的话会影响到临近物体。

选定合适的block_size后,我们就可以选定一个更大的阈值param1,更好的抑制噪声

4.1 THRESH_BINARY和THRESH_BINARY_INV

Mat img = imread("lena.png");
    if (img.empty())
    {
        cout << "读取失败!"<<endl;
        return -1;
    }
    //GARY PICTURE
    Mat gary;
    cvtColor(img, gary, COLOR_BGR2GRAY);
​
    //ORINGIN'SBINARY
    Mat ori_bin, ori_bin_inv, gary_bin, gary_bin_inv;
    threshold(img,ori_bin, 125, 255, THRESH_BINARY);
    threshold(img, ori_bin_inv, 125, 255, THRESH_BINARY_INV);
    imshow("ori_bin", ori_bin);
    imshow("ori_bin_inv", ori_bin_inv);
​
​
    threshold(gary, gary_bin, 125, 255, THRESH_BINARY);
    threshold(gary, gary_bin_inv, 125, 255, THRESH_BINARY_INV);
    imshow("ori_bin", gary_bin);
    imshow("ori_bin_inv", gary_bin_inv);

这段代码将彩图原图和灰度化后的图像分别进行二进制二值化处理;得到下面四个图像。还有原图和灰度图略过:

 

可见多通道是将各个通道分离后进行二值化后再组合在一起,所以不是单纯的黑白图片而是一些带有特点的色彩的图片,RGB的组合

转化为单通道灰度图后可见左右两图片互补

4.2 THRESH_TOZERO和THRESH_TOZERO_INV

Mat img = imread("lena.png");
    if (img.empty())
    {
        cout << "读取失败!"<<endl;
        return -1;
    }
    
    Mat gary;
    cvtColor(img, gary, COLOR_BGR2GRAY);
​
    //ORINGIN'S
    Mat ori_tozero, ori_bin_tozero_inv, gary_tozero, gary_tozero_inv;
    threshold(img, ori_tozero, 125, 255, THRESH_TOZERO);
    threshold(img, ori_bin_tozero_inv, 125, 255, THRESH_TOZERO_INV);
    imshow("THRESH_TOZERO", THRESH_TOZERO);
    imshow("THRESH_TOZERO_INV", THRESH_TOZERO_INV);
​
​
    threshold(gary, gary_tozero, 125, 255, THRESH_TOZERO);
    threshold(gary, gary_tozero_inv, 125, 255, THRESH_TOZERO_INV);
    imshow("gary_tozero", gary_tozero);
    imshow("gary_tozero_inv", gary_tozero_inv);

从左到右分别为原图、zero、inv;可见zero是将高于阈值的保留,低于阈值的置位0,而inv则将高于阈值的置位0,低于阈值的保留

从左到右分别为灰度图、zero、inv;

4.3 THRESH_TRUNC

将高于阈值的设为阈值,低于阈值的保留,比较简单,就放两张图片的前后对比。

四、使用时机

请问THERSH_BINARY、THRESH_TRUNC、THRESH_TOZERO、THRESH_OTSU、 THRESH_TRIANGLE、ADAPTIVE_THRESH_MEAN_C、ADAPTIVE_THRESH_GAUSSIAN_C都是二值化处理方法,我怎么知道什么时候用哪一个合适?

:对于选择合适的二值化处理方法,以下是一些指导原则:

  1. THRESH_BINARY:将图像灰度值大于阈值的像素设置为最大值(通常为255),小于等于阈值的像素设置为0。适用于对比度明显的图像,目标与背景之间有明显的灰度差异。

  2. THRESH_TRUNC:将图像灰度值大于阈值的像素设置为阈值,小于等于阈值的像素保持不变。适用于希望保留目标灰度信息同时进行部分抑制的情况。

  3. THRESH_TOZERO:将图像灰度值大于阈值的像素保持不变,小于等于阈值的像素设置为0。适用于希望保留亮度较高区域的细节信息的情况。

  4. THRESH_OTSU:利用大津法(Otsu's method)自动计算阈值,使得目标与背景之间的类间方差最大化。适用于图像的目标与背景之间有明显的灰度分离,但具体阈值不确定的情况。

  5. THRESH_TRIANGLE:利用三角形法(Triangle method)自动计算阈值,使得基于直方图的三角形面积最大化。适用于图像的目标与背景之间有明显的灰度分离,但具体阈值不确定的情况。

  6. ADAPTIVE_THRESH_MEAN_C:基于局部图像均值的自适应阈值方法,根据每个像素周围的邻域计算阈值。适用于图像中不同区域具有不同光照条件的情况

  7. ADAPTIVE_THRESH_GAUSSIAN_C:基于局部图像加权平均的自适应阈值方法,根据每个像素周围的邻域计算阈值。使用高斯权重来计算局部平均值,适用于图像中不同区域具有不同光照条件的情况。

选择合适的方法取决于图像的特点和应用需求。如果图像具有明显的目标与背景分离,可以尝试使用THRESH_BINARY、THRESH_OTSU或THRESH_TRIANGLE。如果图像具有不同光照条件或需要保留细节信息,可以考虑使用自适应阈值方法(ADAPTIVE_THRESH_MEAN_C或ADAPTIVE_THRESH_GAUSSIAN_C)。

ADAPTIVE_THRESH_GAUSSIAN_C和ADAPTIVE_THRESH_MEAN_C在底层实现过程有什么区别?

:ADAPTIVE_THRESH_MEAN_C和ADAPTIVE_THRESH_GAUSSIAN_C是两种不同的自适应阈值方法,在底层实现过程中有以下区别:

ADAPTIVE_THRESH_MEAN_C(基于局部均值的自适应阈值方法)的实现过程如下:

  1. 对于图像中的每个像素,确定一个局部邻域(大小由指定的块大小参数决定)。

  2. 计算该邻域内像素的平均值(局部均值)。

  3. 将该局部均值作为当前像素的阈值。

  4. 根据当前像素的灰度值与其对应的局部均值进行比较,将像素设置为白色或黑色。

ADAPTIVE_THRESH_GAUSSIAN_C(基于局部加权平均的自适应阈值方法)的实现过程如下:

  1. 对于图像中的每个像素,确定一个局部邻域(大小由指定的块大小参数决定)。

  2. 计算该邻域内像素的加权平均值,其中权重由高斯窗口函数计算得出(离中心像素距离越近,权重越大)。

  3. 将加权平均值作为当前像素的阈值。

  4. 根据当前像素的灰度值与其对应的阈值进行比较,将像素设置为白色或黑色。

区别:

  1. 计算阈值的方式不同:ADAPTIVE_THRESH_MEAN_C使用局部均值作为阈值,而ADAPTIVE_THRESH_GAUSSIAN_C使用局部加权平均值作为阈值。

  2. 权重计算方式不同:ADAPTIVE_THRESH_MEAN_C不考虑像素之间的权重,而ADAPTIVE_THRESH_GAUSSIAN_C使用高斯窗口函数计算权重,使得距离中心像素更近的像素具有更高的权重。

  3. 效果不同:由于权重计算的差异,ADAPTIVE_THRESH_GAUSSIAN_C对于图像的平滑和噪声抑制效果较好,而ADAPTIVE_THRESH_MEAN_C则更加简单直接。

选择使用哪种方法取决于图像的特点和应用需求。如果图像中有明显的噪声或需要更好的平滑效果,可以考虑使用ADAPTIVE_THRESH_GAUSSIAN_C。如果简单的平均处理足以满足需求,或者需要更快的计算速度,可以选择ADAPTIVE_THRESH_MEAN_C。

猜你喜欢

转载自blog.csdn.net/dagengen12138/article/details/131196730
今日推荐