机器学习与计算机视觉Artificial Intelligence互联网科技

opencv入门11:图像阀值-thresholding

2018-03-09  本文已影响94人  HaveyYeung

一个简单的阈值例子就是选择一个像素值p,然后将小于p的所有像素强度设置为零,并且将所有像素值大于p设置为255.以这种方式,我们能够创建图像的二进制表示。

一、阈值化的类型:

OpenCV中提供了阈值(threshold)函数: threshold 。这个函数有5种阈值化类型:

为了解释阈值分割的过程,我们来看一个简单有关像素灰度的图片,该图如下。该图中的蓝色水平线代表着具体的一个阈值。


图·1

阈值类型1:二进制阈值化 cv2.THRESH_BINARY

阈值类型2:反二进制阈值化 cv2.THRESH_BINARY_INV

阈值类型3:截断阈值化 cv2.THRESH_TRUNC

阈值类型4:阈值化为0 cv2.THRESH_TOZERO

阈值类型5:反阈值化为0 cv2.THRESH_TOZERO_INV

二、simple thresholding 简单的阈值方法:

应用简单的阈值方法需要人为干预。
我们必须指定一个阈值T.低于T的所有像素强度都被设置为0.而所有大于T的像素强度被设置为255。

cv2.threshold( src_gray, dst, threshold_value, max_BINARY_value,threshold_type )

图·8

三、adaptive thresholding 自适应阀值

在前面的部分我们使用是全局阈值,整幅图像采用同一个数作为阈值。当时这种方法并不适应与所有情况,尤其是当同一幅图像上的不同部分的具有不同亮度时。这种情况下我们需要采用自适应阈值。此时的阈值是根据图像上的每一个小区域计算与其对应的阈值。因此在同一幅图像上的不同区域采用的是不同的阈值,从而使我们能在亮度不同的情况下得到更好的结果。

cv2.adaptiveThreshold(image,max_BINARY_value,Adaptive_Method,threshold_type,Block_Size,C)

这种方法需要我们指定三个参数,返回值只有一个。

一般来说,在平均自适应阈值和高斯自适应阈值之间进行选择需要在您的最后进行一些实验。要改变的最重要的参数是邻域大小和C,即从平均值中减去的值。通过试验这个值,你将能够显着地改变你的阈值的结果。

import numpy as np 
import argparse
import cv2

ap = argparse.ArgumentParser()
ap.add_argument("-i","--image",required =True, help="Path to the image")
args = vars(ap.parse_args())

image = cv2.imread(args["image"])
image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
blured = cv2.GaussianBlur(image,(5,5),0)
cv2.imshow("Image",image)

thresh =cv2.adaptiveThreshold(blured, 255 ,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY_INV,11,4)
cv2.imshow("mean thresh",thresh)

thresh =cv2.adaptiveThreshold(blured, 255 ,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,15,3)
cv2.imshow("GAUSSIAN thresh",thresh)
cv2.waitKey(0) 

图·9

四、Otsu’s 二值化 和 Riddler-Calvard

在使用全局阈值时,我们就是随便给了一个数来做阈值,那我们怎么知道
我们选取的这个数的好坏呢?答案就是不停的尝试。如果是一副双峰图像(简
单来说双峰图像是指图像直方图中存在两个峰)呢?我们岂不是应该在两个峰
之间的峰谷选一个值作为阈值?这就是Otsu 二值化要做的。简单来说就是对
一副双峰图像自动根据其直方图计算出一个阈值。(对于非双峰图像,这种方法
得到的结果可能会不理想)。

mahotas.thresholding.otsu() 和 mahotas.thresholding.rc()

from __future__ import print_function
import numpy as np 
import argparse
import mahotas
import cv2

ap = argparse.ArgumentParser()
ap.add_argument("-i","--image",required =True, help="Path to the image")
args = vars(ap.parse_args())

image = cv2.imread(args["image"])
image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(image,(5,5),0)
cv2.imshow("Image",image)

T = mahotas.thresholding.otsu(blurred)
#为了计算T的最优值,我们使用mahotas.thresholding包中的otsu函数
print("Otsu`s threshold:{}".format(T))
thresh = image.copy()
thresh[thresh>T] = 255
thresh[thresh<T] = 0
thresh = cv2.bitwise_not(thresh)
# 首先,我们制作灰度图像的副本,以便使图像达到阈值。
# 第20行然后使任何值大于T white,
# 而第21行将所有剩余的不是白色的像素变成黑色像素。
# 然后我们通过使用cv2.bitwise_not来反转我们的阈值。
# 这相当于在本章前面的例子中应用cv2.THRESH_BINARY_INV阈值类型。
cv2.imshow("Ostu",thresh)

T = mahotas.thresholding.rc(blurred)
# 另一种方法找到最优值T 时要牢记Riddler-Calvard方法。
# 使用mahotas.thresholding中的rc函数
print("Riddler-Calvard:{}".format(T))
thresh = image.copy()
thresh[thresh>T] = 255
thresh[thresh<255] = 0
thresh = cv2.bitwise_not(thresh)
cv2.imshow("Riddler-Calvard",thresh)
cv2.waitKey(0)

图·10

努力常态化。
更多文章请关注我的博客:https://harveyyeung.github.io

上一篇 下一篇

猜你喜欢

热点阅读