> 文章列表 > 白话文讲计算机视觉-第十讲-灰度阈值分割

白话文讲计算机视觉-第十讲-灰度阈值分割

白话文讲计算机视觉-第十讲-灰度阈值分割

        灰度阈值是啥意思呢?我们慢慢说。

1.灰度图

        我们现在有一张彩色图,我们给它用黑白的方式变现,就形成灰度图,如图所示。

图1

        那究竟怎么转换的呢?很简单,我们根据如下公式,把BGR三个通道换成一个Gray通道(0~255):

Gray = R*0.299 + G*0.587 + B*0.114

        其中,R,G,B分别代表的是R,G,B三个通道的值(0~255)。

        用python语句导入灰度图只需要在导入图像时候后面多一个0即可:

img = cv2.imread("linetest.jpg", 0)

2.灰度直方图

        灰度直方图很容易理解,就是我们有一张灰度图,如图1那张。这张图是800*858的尺寸的图。也就是说,该图里面有686400个像素点,每一个像素都对应一个值(0~255),然后我们统计一下0~255这些值共有多少个,并画出统计图:

图2

        看图2,输入色阶里面从左到右分别对应的是0~255这些数值的数目。我们发现,这里面亮的点不少(接近255),暗的很少(接近0),不亮不暗的占大多数(中间的值)

3.阈值分割

        我们选择0~255之间的一个值,比如150,然后小于等于150都给它变成0,大于150的都给他变为255,这样,我们的图里面就只有两个颜色(黑、白)了。分割后的图像为二值图像,如图3所示:

图3

        我们可以使用PYTHON代码来执行这个阈值分割:

ret, thresh = cv2.threshold(img, 150, 255, cv2.THRESH_BINARY)

        该语句表示:将灰度图像img进行二值化处理,灰度小于150的为0,大于的255

ret: 输入的阈值

thresh : 处理好的图片

cv2.THRESH_BINARY:表示根据灰度小于阈值的为0,大于的255。

        确定一个最佳阈值,使背景和目标之间的差异最大,能够有效地分离背景和前景。那么怎么找阈值呢,我们引入大津算法。

4大津算法

        有个小日子叫大津展之(おおつのぶゆき),他在1979年时候发明了一个针对二值化的确定最佳阈值有效方法。

 图4

        这个算法是怎么运行的呢,特别简单。

(1)假定我们灰度图是5*5的尺寸的图。也就是说,该图里面有25个像素点,那么我们设定一个N=25

(2)接下来,我们求一下个灰度值的概率。P_i=n_i/N,其中ni为灰度值i的像素个数。例如,灰度值为150的有5个,那么P_150=n_150/N=5/25=1/5=0.2。

(3)然后我们从阈值为0开始,进行阈值分割为{G1,G2}两组,分别为小于0组G1,大于等于0的组G2。(灰度值小于等于1的都为0,大于1的都为255。)就可以得到G1的总概率值w0,G2的总概率值w1:

         也可以得到G1、G2的平均值:

        整个图像的灰度平均值、方差可以通过如下式子求得:

                     

        当我们求完阈值为0的情况的方差之后,我们进行阈值为1,2,3。。。。。一直到254时候的平均值,方差。然后我们选择方差最大情况下的阈值T,作为我们最终的阈值。

上面的公式我们在其它阈值T下遍历时,可以改为:

 

        我们可以使用PYTHON代码来执行这个大津算法,执行的结果如图5所示:

ret2,thresh2= cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

图5

        最后奉上全部代码:

# 导入类库
import cv2
import numpy as npif __name__ == '__main__':# 读入灰度图片img1 = cv2.imread("linetest.jpg")img2 = cv2.imread("linetest.jpg", 0)# 显示图片cv2.imshow('orgin1', img1)cv2.imshow('orgin2', img2)#阈值分割ret1, thresh1 = cv2.threshold(img2, 150, 255, cv2.THRESH_BINARY)#大津算法ret2, thresh2 = cv2.threshold(img2, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)# 显示图片cv2.imshow('orgin3', thresh1)cv2.imshow('orgin4', thresh2)# 按任意键退出cv2.waitKey()cv2.destroyAllWindows()

以上就是阈值分割的所有内容啦!