前言:

灰度图(Gray Scale Image):是一种仅用灰度色阶表示图像亮度的非色彩图像,其像素值范围通常为0(纯黑)到255(纯白)之间的256个等级

图像二值化:是图像处理中的基础技术,通过设定阈值将灰度图像转换为仅含两个值的图像

在使用openCV时一定不要忘记导包:import cv2 as cv,在代码中我都用cv代替cv2

若使用了numpy 也需要导入:import numpy as np,以 np 取代 numpy。 

目录:

一、灰度图像

(一)最大值法 

(二)平均值法  

(三)加权平均值法  

(四)两个极端的灰度值 

二、图像二值化处理  

(一)全局阈值法:_,binary = cv.threshold(img,thresh,maxval,type)   

1、阈值法(THRESH_BINARY)   

2、反阈值法(THRESH_BINARY_INV)

3、截断阈值法(THRESH_TRUNC)   

4、低阈值零处理(THRESH_TOZERO)

5、超阈值零处理(THRESH_TOZERO_INV)

(二)非全局阈值

1、OTSU阈值法:计算整幅图的

   OTSU阈值法的代码:

2、自适应二值化

    (1)取均值

    (2)加权求和

一、灰度图像

灰度图与彩色图最大的不同就是:彩色图是由R、G、B三个通道组成,而灰度图只有一个通道,也称为单通道图像,所以彩色图转成灰度图的过程本质上就是将R、G、B三通道合并成一个通道的过程。

每个像素只有一个采样颜色的图像,这类图像通常显示为从最暗黑色到最亮的白色的灰度,尽管理论上这个采样可以任何颜色的不同深浅,甚至可以是不同亮度上的不同颜色。灰度图像与黑白图像不同,在计算机图像领域中黑白图像只有黑色与白色两种颜色;但是,灰度图像在黑色与白色之间还有许多级的颜色深度。灰度图像经常是在单个电磁波频谱如可见光内测量每个像素的亮度得到的,用于显示的灰度图像通常用每个采样像素8位的非线性尺度来保存,这样可以有256级灰度。

一副灰度图像:

接下来将介绍三种将彩色图合并为灰度图的方法,分别是最大值法、平均值法以及加权均值法。

(一)最大值法

对于彩色图像的每个像素,最大值法即从R、G、B三个通道的值中选出最大的一个,并将其作为灰度图像中对应位置的像素值。

例如某图像中某像素点的像素值如上图所示,那么在使用最大值法进行灰度化时,就会从该像素点对应的RGB通道中选取最大的像素值作为灰度值,所以在灰度图中的对应位置上,该像素点的像素值就是121。

最大值法代码:

(二)平均值法

对于彩色图像的每个像素,平均值法会将R、G、B三个通道的像素值全部加起来,然后再除以三,得到的平均值就是灰度图像中对应位置的像素值。

例如某图像中某像素点的像素值如上图所示,那么在使用平均值进行灰度化时,其计算结果就是(91+121+46)/3=86(对结果进行取整),所以在灰度图中的对应位置上,该像素点的像素值就是86。

平均值法代码:

(三)加权平均值法

对于彩色图像的每个像素,加权平均值是按照一定的权重去乘以每个通道的像素值,并将其相加,得到最后的值就是灰度图像中对应位置的像素值。权重的比例为: R乘以0.299,G乘以0.587,B乘以0.114,这是一个比较常用的权重比例。

所使用的权重之和应该等于1。这是为了确保生成的灰度图像素值保持在合理的亮度范围内,并且不会因为权重的比例不当导致整体过亮或过暗。

例如某图像中某像素点的像素值如上图所示,那么在使用加权平均值进行灰度化时,其计算结果就是10*0.299+121*0.587+46*0.114=79。所以在灰度图中的对应位置上,该像素点的像素值就是79。

加权平均值法代码:

​这是最常见的加权均值代码,其中将cv内置

(四)两个极端的灰度值

在灰度图像中,“极端”的灰度值指的是亮度的两个极端:最暗和最亮的值。

  • 最暗的灰度值:0。这代表完全黑色,在灰度图像中没有任何亮度。

  • 最亮的灰度值:255。这代表完全白色,在灰度图像中具有最大亮度。

               灰度值为0(纯黑)                                  灰度值为255(纯白)

二、图像二值化处理

二值图像:一副二值图像的二维矩阵仅由0、1两个值构成,“0”代表黑色,“1”代表白色,由于每一像素(矩阵中每一元素)取值仅有0、1两种可能,所以计算机中二值图像的数据类型通常为1个二进制位。二值图像通常用于文字、线条图的扫描识别(OCR)和掩膜图像的存储。

一副二值化后的图像:

       二值化处理的图像必须是灰度图。也就是说,二值化的过程是将一张灰度图上的像素根据某种规则修改为0和maxval(maxval表示最大值,一般为255:白色)两种像素值,使图像呈现黑白的效果,可以用来更好地分析图像中的形状、边缘和轮廓等特征,用于文字线条图的扫描识别(QCR)和掩膜图像的存储。

       \star 简便:降低计算量和计算需求,加快处理速度

       \star 节约资源:二值图像占用空间远小于彩色图

       \star 边缘检测:二值化常作为边缘检测的预处理步骤,因为简化后的图易于识别出轮廓和边界

(一)全局阈值法:_,binary = cv.threshold(img,thresh,maxval,type)

        img:输入图像,要进行二值化处理的灰度图

        thresh:设定的阈值。当像素值大于(或小于,取决于阈值类型)thresh时,该像素被赋予的值。

        type:阈值处理的类型

        返回值:

                 第一个值(通常用下划线表示):计算出的阈值,若使用自适应阈值会根据算法自动计算出这个值。

                第二个值(binary):二值化后的图像矩阵,与输入图像尺寸相同。

1、阈值法(THRESH_BINARY)

        阈值法就是通过设置一个阈值,将灰度图中的每一个像素值与阈值进行比较,小于等于阈值的被设置为0,大于阈值的被设置为maxval(代表前景),通常是255。

如图:二值化的设置

结果:

                        灰度图                                                   二值化图

上图可以看出,在灰度图中像素值较高的地方,如花瓣、花茎等地方的像素值比阈值高,那么在生成的二值化图中的对应位置的像素值就会被设置为255,也就是纯白色。

阈值法代码:

代码结果:

在进行二值化处理前必须要进行灰度化,除去代码中使用的灰度化方法,还可以使用cv.IMREAD_GRAYSCALE:OpenCV 中用于指定图像加载模式的一个标志,直接告诉 cv.imread() 函数以灰度格式读取图像。

2、反阈值法(THRESH_BINARY_INV)

顾名思义,就是与阈值法相反。反阈值法是当灰度图的像素值大于阈值时,该像素值将会变成0(黑),当灰度图的像素值小于等于阈值时,该像素值将会变成maxval。

如上图所示,使用反阈值法对灰度图进行二值化时,会将灰度图中像素值大于阈值的地方置为0(也就是黑),将灰度图中像素值小于阈值的地方置为255(也就是白)。

反阈值法代码:

3、截断阈值法(THRESH_TRUNC)

截断阈值法,指将灰度图中的所有像素与阈值进行比较,像素值大于阈值的部分将会被修改为阈值,小于等于阈值的部分不变。

换句话说,经过截断阈值法处理过的二值化图中的最大像素值就是阈值。

                           灰度图                                                      二值化图

当截断阈值为255时,如上图所示,可以看到灰度图与二值化图没有任何的区别。 使用截断阈值法进行图像二值化处理时,设置的maxval参数实际上是不起作用的。

截断阈值法代码:

4、低阈值零处理(THRESH_TOZERO)

低阈值零处理,字面意思,就是像素值小于等于阈值的部分被置为0(也就是黑色),大于阈值的部分不变。是少有的二值化处理中生成的图像像素值大于2的。

                     灰度图                                                      二值化图  

如上图所示,在灰度图中较亮的部分,其像素值比阈值大,所以在二值化后其像素值并没有发生变化。而灰度图中较暗的部分,也就是像素值较低的地方,由于像素值比阈值小,就会被置为0,对应二值化图中的黑色部分。

低阈值零处理的代码:

5、超阈值零处理(THRESH_TOZERO_INV)

超阈值零处理就是将灰度图中的每个像素与阈值进行比较,像素值大于阈值的部分置为0(也就是黑色),像素值小于等于阈值的部分不变。

                      灰度图                                              二值化图

如上图所示,在灰度图中较亮的部分,其像素值比阈值大,所以在二值化后其像素值会被置为0(也就是黑色),对应二值化图中的黑色部分。而灰度图中较暗的部分,也就是像素值较低的地方,由于像素值比阈值小,将不会发生改变。

以上介绍的二值化方法都需要手动设置阈值,但是在不同的环境下,摄像头拍摄的图像可能存在差异,导致手动设置的阈值并不适用于所有图像,这可能会导致二值化效果不理想。

因此,我们需要一种能自动计算每张图片阈值的二值化方法,能够根据每张图像的特点自动计算出适合该图像的二值化阈值,从而达到更好的二值化效果。这种二值化方法可以在不同环境下适用,提高图像处理的准确性和鲁棒性。

(二)非全局阈值

1、OTSU阈值法:计算整幅图的

cv.THRESH_OTS 并不是一个有效的阈值类型或标。THRESH_OTSU 本身并不是一个独立的阈值化方法,而是与 OpenCV 中的二值化方法结合使用的一个标志。具体来说,THRESH_OTSU 通常与 THRESH_BINARYTHRESH_BINARY_INV 结合使用。在实际应用中,如果你使用 THRESH_OTSU 标志但没有指定其他二值化类型,默认情况下它会与 THRESH_BINARY 结合使用。也就是说,当你仅指定了 cv.THRESH_OTSU,实际上等同于同时指定了 cv.THRESH_BINARY + cv.THRESH_OTSU

在介绍OTSU阈值法之前,我们首先要了解一下双峰图片的概念。

双峰图片就是指灰度图的直方图上有两个峰值,直方图就是对灰度图中每个像素值的点的个数的统计图,如下图所示。

灰度图直方图的基础概念

  1. 灰度级

    • 在灰度图像中,每个像素的值代表其亮度,通常范围是 0 到 255(对于 8 位灰度图像)。

    • 0 表示黑色,255 表示白色,中间的值表示不同程度的灰色。

  2. 直方图定义

    • 直方图是一个柱状图,其中 x 轴表示灰度级(从 0 到 255),y 轴表示对应灰度级在图像中出现的次数(频率)。

    • 每个柱子的高度代表该灰度级在图像中出现的像素数量。

OTSU算法是通过一个值将这张图分前景色和背景色(也就是灰度图中小于这个值的是一类,大于这个值的是一类。例如,如果你设置阈值为128,则所有大于128的像素点可以被视作前景,而小于等于128的像素点则被视为背景。),通过统计学方法(最大类间方差)来验证该值的合理性,当根据该值进行分割时,使用最大类间方差计算得到的值最大时,该值就是二值化算法中所需要的阈值。通常该值是从灰度图中的最小值加1开始进行迭代计算,直到灰度图中的最大像素值减1,然后把得到的最大类间方差值进行比较,来得到二值化的阈值。以下是一些符号规定:

T:阈值

N_{0}:前景像素点数

N_{1}:背景像素点数

omega_{0}:前景的像素点数占整幅图像的比例

omega_{1}:背景的像素点数占整幅图像的比例

mathcal{U_{0}}:前景的平均像素值

mathcal{U_{1}}:背景的平均像素值

mathcal{U}:整幅图的平均像素值

rows×cols:图像的行数和列数

下面举个例子,有一张大小为4×4的图片,假设阈值T为1,那么:

也就是这张图片根据阈值1分为了前景(像素为2的部分)和背景(像素为0)的部分,并且计算出了OTSU算法所需要的各个数据,根据上面的数据,我们给出计算类间方差的公式:

g=\omega 0(\mu 0-\mu )+\omega 1(\mu 1-\mu )^{2}

g就是前景与背景两类之间的方差,这个值越大,说明前景和背景的差别就越大,效果就越好。OTSU算法就是在灰度图的像素值范围内遍历阈值T,使得g最大,基本上双峰图片的阈值T在两峰之间的谷底。

通过OTSU算法得到阈值之后,就可以结合上面的方法根据该阈值进行二值化,在本实验中有THRESH_OTSU和THRESH_INV_OTSU两种方法,就是在计算出阈值后结合了阈值法和反阈值法。

注意:使用OTSU算法计算阈值时,组件中的thresh参数将不再有任何作用。

通过OTSU算法得到阈值之后,就可以结合上面的方法根据该阈值进行二值化,在本实验中有THRESH_OTSU和THRESH_INV_OTSU两种方法,就是在计算出阈值后结合了阈值法和反阈值法。

注意:使用OTSU算法计算阈值时,组件中的thresh参数将不再有任何作用。

                方法                                                             效果

OTSU阈值法的代码:
2、自适应二值化

与二值化算法相比,自适应二值化更加适合用在明暗分布不均的图片,因为图片的明暗不均,导致图片上的每一小部分都要使用不同的阈值进行二值化处理,这时候传统的二值化算法就无法满足我们的需求了,于是就出现了自适应二值化。

自适应二值化方法会对图像中的所有像素点计算其各自的阈值,这样能够更好的保留图片里的一些信息。自适应二值化组件内容如下图所示:

cv.adaptiveThreshold(image_np_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 7, 10)

其中各个参数的含义如下:

maxval:最大阈值,一般为255

adaptiveMethod:小区域阈值的计算方式:

ADAPTIVE_THRESH_MEAN_C:小区域内取均值

ADAPTIVE_THRESH_GAUSSIAN_C:小区域内加权求和,权重是个高斯核

thresholdType:二值化方法,只能使用THRESH_BINARY、THRESH_BINARY_INV,也就是阈值法和反阈值法

blockSize:选取的小区域的面积,如7就是7*7的小块。

c:最终阈值等于小区域计算出的阈值再减去此值

下面介绍一下这两种方法。

(1)取均值

若一张图片的左上角像素值如下图所示:

假如我们使用的小区域是3*3的,那么就会从图片的左上角开始(也就是像素值为162的地方)计算其邻域内的平均值,如果处于边缘地区就会对边界进行填充,填充值就是边界的像素点,如下图所示:

那么对于左上角像素值为162的这个点,161(也就是上图中括号内的计算结果,结果会进行取整)就是根据平均值计算出来的阈值,接着减去一个固定值C,得到的结果就是左上角这个点的二值化阈值了,接着根据选取的是阈值法还是反阈值法进行二值化操作。紧接着,向右滑动计算每个点的邻域内的平均值,直到计算出右下角的点的阈值为止。我们所用到的不断滑动的小区域被称之为核,比如3*3的小区域叫做3*3的核,并且核的大小都是奇数个,也就是3*3、5*5、7*7等。

自适应二值化(Adaptive Thresholding)的核心思想就是为图像中的每个像素点计算一个局部阈值。这种方法与全局阈值化不同,后者对整个图像使用同一个固定的阈值。而在自适应二值化中,每个像素的阈值是基于其周围邻域内的像素值动态确定的。

(2)加权求和

对小区域内的像素进行加权求和得到新的阈值,其权重值来自于高斯分布。

高斯分布,通过概率密度函数来定义高斯分布,一维高斯概率分布函数为:

p(y)=\frac{1}{\sigma \sqrt{2\pi }}e^{\frac{-(y-\mu )^{2}}{2\sigma ^{2}}}

通过改变函数中和的值,我们可以得到如下图像,其中均值为\mu,标准差为\sigma ^{2}

此时我们拓展到二维图像,一般情况下我们使x轴和y轴的相等并且,此时我们可以得到二维高斯函数的表达式为:

g(x,y)=\frac{1}{2\pi \sigma ^{2}}e^{-\frac{(x^{2}+y^{2})}{2\sigma ^{2}}}

高斯概率函数是相对于二维坐标产生的,其中(x,y)为点坐标,要得到一个高斯滤波器模板,应先对高斯函数进行离散化,将得到的值作为模板的系数。例如:要产生一个3*3的高斯权重核,以核的中心位置为坐标原点进行取样,其周围的坐标如下图所示(x轴水平向右,y轴竖直向上)

                                                   

将坐标带入上面的公式中,即可得到一个高斯权重核。

而在opencv里,当kernel(小区域)的尺寸为1、3、5、7并且用户没有设置\sigma的时候(\sigma <= 0),核值就会取固定的系数,这是一种默认的值是高斯函数的近似。

比如kernel的尺寸为3*3时,使用

进行矩阵的乘法,就会得到如下的权重值,其他的类似。

通过这个高斯核,即可对图片中的每个像素去计算其阈值,并将该阈值减去固定值得到最终阈值,然后根据二值化规则进行二值化。

而当kernels尺寸超过7的时候,如果sigma设置合法(用户设置了\sigma),则按照高斯公式计算.当sigma不合法(用户没有设置\sigma),则按照如下公式计算\sigma的值:

某像素点的阈值计算过程如下图所示:

首先还是对边界进行填充,然后计算原图中的左上角(也就是162像素值的位置)的二值化阈值,其计算过程如上图所示,再然后根据选择的二值化方法对左上角的像素点进行二值化,之后核向右继续计算第二个像素点的阈值,第三个像素点的阈值…直到右下角(也就是155像素值的位置)为止。

当核的大小不同时,仅仅是核的参数会发生变化,计算过程与此是一样的。

自适应二值化代码:

cv.adaptiveThreshold参数解释:

1. image_np_gray: 输入图像,这里必须是灰度图像(单通道)。

2. 255: 输出图像的最大值。在二值化后,超过自适应阈值的像素会被设置为该最大值,通常为255表示白色;未超过阈值的像素将被设置为0,表示黑色。

3. cv.ADAPTIVE_THRESH_GAUSSIAN_C: 自适应阈值类型。在这个例子中,使用的是高斯加权的累计分布函数(CDF),并添加一个常数 C 来计算阈值。另一种可选类型是 cv.ADAPTIVE_THRESH_MEAN_C,它使用邻域内的平均值加上常数 C 计算阈值。

4. cv.THRESH_BINARY: 输出图像的类型。这意味着输出图像将会是一个二值图像(binary image),其中每个像素要么是0要么是最大值(在这里是255)。另外还有其他选项如 cv.THRESH_BINARY_INV 会得到相反的二值图像。

5. 7: blockSize 参数,表示计算每个像素阈值时所考虑的7x7邻域大小(正方形区域的宽度和高度),其值必须是奇数。

6. 10: C 参数,即上面提到的常数值,在计算自适应阈值时与平均值或高斯加权值相加。正值增加阈值,负值降低阈值,具体效果取决于应用场景。

小结:

生成灰度图像:

最大值法, 适用于需要突出图像亮部细节的场景,但可能丢失暗部信息。

平均值法,适用于图像整体均衡的情况,但可能导致对比度降低。

加权平均值法,适用于需要符合人眼感知的通用场景,能保留更多视觉重要性信息。

二值化处理:

阈值法与反阈值法是将图像像素值与设定的阈值比较,无论高于还是低于阈值,都要发生改变,阈值法高于阈值的像素设为最大值(如255),低于的设为最小值(如0),反阈值则相反

截断阈值法仅对高于阈值的像素进行处理,将其截断为阈值,其余保持不变。

低阈值零处理低于阈值的像素置零,高于的保留原值。

超阈值零处理高于阈值的像素置零,低于的保留原值

 

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐