大家好,欢迎来到IT知识分享网。
什么是图像二值化
在认识二值化前,我们先简单介绍一下几个概念:
-
彩色图像
彩色图像有blue,green,red三个通道,取值范围均为0-255
-
灰度图
灰度图:只有一个通道,取值范围在0-255,所以一共有256种颜色
-
二值图像
二值图像,只有两种颜色,既黑色和白色
图像二值化
图像的二值化也很简单,大概二步就可以完成,具体如下
-
第一步:获取阈值
获取阈值很简单,OpenCv的threshold函数进行全局阈值,也可通过OpenCv的adaptiveThreshold获取局部阈值,同时也可以自定义阈值。下面就简单介绍一下这三种阈值。
-
全局阈值
全局阈值可以通过OpenCv的threshold函数进行全局阈值,函数如下:cv.threshold(src, thresh, maxval, type[, dst]) -> retval, dst)
参数说明:
# src: 表示输入图像(多通道,8位或32位浮点)。 # thresh: 表示阈值。 # maxval: 与THRESH_BINARY和THRESH_BINARY_INV阈值类型一起使用设置的最大值。 # type: 阈值的类型 # retval: 返回的阈值。若是全局固定阈值算法,则返回thresh参数值。若是全局自适应阈值算法,则返回自适应计算得出的合适阈值。 # dst: 输出与src相同大小和类型以及相同通道数的图像。
注意: 阈值的类型也包括如下几种
-
类型 | 说明 |
---|---|
THRESH_BINARY | 超过阈值的值为最大值,其他值是0 |
THRESH_BINARY_INV | 超过阈值的值为0,其他值为最大值 |
THRESH_TRUNC | 超过阈值的值等于阈值,其他值不变 |
THRESH_TOZERO | 超过阈值的值不变,其他值为0 |
THRESH_TOZERO_INV | 超过阈值的值为0,其他值不变 |
下面就意义讲解这几种阈值的代码简单实现:
- 全局阈值THRESH_BINARY 阈值的实现
def threshold_By_OTSU(input_img_file):
image=cv2.imread(input_img_file)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) ##要二值化图像,必须先将图像转为灰度图
ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
print("threshold value %s" % ret) #打印阈值,超过阈值显示为白色,低于该阈值显示为黑色
cv2.imshow("threshold", binary) #显示二值化图像
cv2.waitKey(0)
cv2.destroyAllWindows()
好了,看一下效果图:
- 全局阈值THRESH_TRIANGLE,三角形算法
def threshold_By_THRESH_TRIANGLE(input_img_file):
image=cv2.imread(input_img_file)
cv2.imshow("image", image) # 显示二值化图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) ##要二值化图像,必须先将图像转为灰度图
ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_TRIANGLE)
print("threshold value %s" % ret) #打印阈值,超过阈值显示为白色,低于该阈值显示为黑色
cv2.imshow("threshold", binary) #显示二值化图像
cv2.waitKey(0)
cv2.destroyAllWindows()
看一下效果图如下:
- 全局阈值THRESH_BINARY_INV 阈值的实现
def threshold_By_THRESH_BINARY_INV(input_img_file):
image=cv2.imread(input_img_file)
cv2.imshow("image", image) # 显示二值化图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) ##要二值化图像,必须先将图像转为灰度图
ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_BINARY_INV)
print("threshold value %s" % ret) #打印阈值,超过阈值显示为白色,低于该阈值显示为黑色
cv2.imshow("threshold", binary) #显示二值化图像
cv2.waitKey(0)
cv2.destroyAllWindows()
看一下效果图:
同理,这里就不用了在讲其他几种类型了,只需要修改threshold函数的type参数类型就可以了,看了这三种效果,我们可以得出一下结论:
cv.THRESH_OTSU和cv.THRESH_TRAINGLE都是自动获取阈值
THRESH_OTSU:适用于双波峰
THRESH_TRIANGLE:适用于单个波峰,最开始用于医学分割细胞等
好了,了解了系统提供的全局阈值,下面我就简单介绍一下自定义全局阈值,自定义全局阈值很简单,就是自己定义threshold函数的参数。
- 自定义全局阈值
(1)THRESH_BINARY_INV大于阈值的都为0ret, binary = cv.threshold(gray, 127, 255, cv.THRESH_BINARY)
代码如下:
def threshold_By_Avto(input_img_file): image=cv2.imread(input_img_file) cv2.imshow("image", image) # 显示二值化图像 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) ##要二值化图像,必须先将图像转为灰度图 ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)#自定义阈值 print("threshold value %s" % ret) #打印阈值,超过阈值显示为白色,低于该阈值显示为黑色 cv2.imshow("threshold", binary) #显示二值化图像 cv2.waitKey(0) cv2.destroyAllWindows()
看一下效果图如下:
(2)THRESH_TRUNC截断大于127的值都为127,其他值不变
def threshold_By_Avto(input_img_file):
image=cv2.imread(input_img_file)
cv2.imshow("image", image) # 显示二值化图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) ##要二值化图像,必须先将图像转为灰度图
ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_TRUNC)#自定义阈值
print("threshold value %s" % ret) #打印阈值,超过阈值显示为白色,低于该阈值显示为黑色
cv2.imshow("threshold", binary) #显示二值化图像
cv2.waitKey(0)
cv2.destroyAllWindows()
看一下效果图:
(3)THRESH_TOZERO 超过阈值的值不变,小于阈值的为0
def threshold_By_Avto(input_img_file):
image=cv2.imread(input_img_file)
cv2.imshow("image", image) # 显示二值化图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) ##要二值化图像,必须先将图像转为灰度图
ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_TOZERO)#自定义阈值
print("threshold value %s" % ret) #打印阈值,超过阈值显示为白色,低于该阈值显示为黑色
cv2.imshow("threshold", binary) #显示二值化图像
cv2.waitKey(0)
cv2.destroyAllWindows()
好了,再看一下THRESH_TOZERO 的效果图:
全局阈值和自定义全局阈值说完,下面我们来讲解一下局部阈值。
-
局部阈值
局部阈值可以使图片更加清晰,而局部阈值可以使用OpenCV的adaptiveThreshold函数进行局部阈值,函数以及参数说明如下:adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize,C[, dst]) -> dst)
参数说明:
src:输入图像(8位单通道图像)。
maxValue:使用THRESH_BINARY和THRESH_BINARY_INV的最大值.
adaptiveMethod参数表示自适应阈值算法,平均 (ADAPTIVE_THRESH_MEAN_C)或高斯 (ADAPTIVE_THRESH_GAUSSIAN_C)。
thresholdType:阈值类型,必须为THRESH_BINARY或THRESH_BINARY_INV的阈值类型。
blockSize: 块大小(奇数且大于1,比如3,5,7… )。
C: 常数,表示从平均值或加权平均值中减去的数。 通常情况下,这是正值,但也可能为零或负值
在使用平均和高斯两种算法情况下,通过计算每个像素周围blockSize x blockSize大小像素块的加权均值并减去常量C即可得到自适应阈值。如果使用平均的方法,则所有像素周围的权值相同;如果使用高斯的方法,则每个像素周围像素的权值则根据其到中心点的距离通过高斯方程得到:
def jubuThreshold(input_img_file):
image = cv2.imread(input_img_file)
cv2.imshow("image", image) # 显示二值化图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
binary = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 25, 10)
cv2.imshow("binary", binary)
cv2.waitKey(0)
cv2.destroyAllWindows()
好了,看一下效果图:
当然,我们还可以自己计算阈值,自己计算阈值就是计算图像的均值,用均值作为阈值,来分割图像。代码如下:
def custom_Threshold(input_img_file):
image = cv2.imread(input_img_file)
cv2.imshow("image", image) # 显示二值化图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
h, w = gray.shape[:2]
m = np.reshape(gray, [1, h*w]) #将图像转为1行h*w列
mean = m.sum() / (h*w) #计算图像的均值,用均值作为阈值,来分割图像
ret, binary = cv2.threshold(gray, mean, 255, cv2.THRESH_BINARY)
print("threshold value %s" % ret)
cv2.imshow("cudtom_binary", binary)
cv2.waitKey(0)
cv2.destroyAllWindows()
好了,看一下效果图如下:
而自己计算阈值所得到的阈值如下:
好了,至此关于常用的阈值和定义阈值基本讲述完毕,下面就讲如何根据阈值去二值化图像。
-
第二步:根据阈值去二值化图像
前面讲的那么多都是如何获取阈值的,获取阈值的方式有很多,具体就根据实际开发情况使用,得到阈值后就是开启二值化了,到了这里就非常简单,其实在上面已经列出了,只是为了方便大家看到效果而已。
cv2.threshold和cv2.adaptiveThreshold这俩个函数就已经实现了二值化并且返回了阈值给我们。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/10169.html