【OpenCV + Python】图像阈值

一、介绍:
cv2.threshold()函数的作用是将一幅灰度图二值化,基本用法如下:
threshold(src, thresh, maxval, type[, dst])->ret,dst
src::灰度图
thresh:阈值,返回值ret等于thresh
maxval:最大值
type:阈值类型
对于最后一个参数,常见的阈值类型有:
THRESH_BINARY=0,THRESH_BINARY_INV,THRESH_TRUNC,THRESH_TOZERO,THRESH_TOZERO_INV,THRESH_OTSU,THRESH_TRIANGLE,THRESH_MASK
【OpenCV + Python】图像阈值_第1张图片
值得一说的是threshold_type可以使用CV_THRESH_OTSU类型,这样该函数就会使用 大律法OTSU得到的全局自适应阈值 来进行二值化图片,而参数中的threshold不再起作用。比如:cvThreshold( dst, dst,100, 255, CV_THRESH_OTSU | CV_THRESH_BINARY_INV);这种方法对于灰度直方图呈现二峰特征的图片 处理起来效果很好。当然你也可以使用已有的OTSU算法来计算该阈值。
例子:

import cv2
img=cv2.imread('5.jpg',0)
rows,cols=img.shape
ret1,mask1  = cv2.threshold(img,100, 255,cv2.THRESH_OTSU )  
ret2,mask2  = cv2.threshold(img,100, 255,cv2.THRESH_OTSU |1)  
ret3,mask3 = cv2.threshold(img,100,255,1)
cv2.imshow("img", img)
cv2.imshow("mask1", mask1)
cv2.imshow("mask2", mask2)
cv2.imshow("mask3", mask3)
cv2.waitKey()

【OpenCV + Python】图像阈值_第2张图片

(1)阈值类型1:二进制阈值化 cv2.THRESH_BINARY
在这里插入图片描述
【OpenCV + Python】图像阈值_第3张图片
解释:在运用该阈值类型的时候,先要选定一个特定的阈值量,比如:125,这样,新的阈值产生规则可以解释为大于125的像素点的灰度值设定为最大值(如8位灰度值最大为255),灰度值小于125的像素点的灰度值设定为0。

(2)阈值类型2:反二进制阈值化 cv2.THRESH_BINARY_INV
在这里插入图片描述
解释:该阈值化与二进制阈值化相似,先选定一个特定的灰度值作为阈值,不过最后的设定值相反。(在8位灰度图中,例如大于阈值的设定为0,而小于该阈值的设定为255)。

(3)阈值类型3:截断阈值化 cv2.THRESH_TRUNC
在这里插入图片描述
解释:同样首先需要选定一个阈值,图像中大于该阈值的像素点被设定为该阈值,小于该阈值的保持不变。 (例如:阈值选取为125,那小于125的阈值不改变,大于125的灰度值(230)的像素点就设定为该阈值)。
(4)阈值类型4:阈值化为0 cv2.THRESH_TOZERO
在这里插入图片描述
解释:先选定一个阈值,然后对图像做如下处理:1 像素点的灰度值大于该阈值的不进行任何改变;2 像素点的灰度值小于该阈值的,其灰度值全部变为0。

(5)阈值类型5:反阈值化为0 cv2.THRESH_TOZERO_INV
在这里插入图片描述
解释:原理类似于0阈值,但是在对图像做处理的时候相反,即:像素点的灰度值小于该阈值的不进行任何改变,而大于该阈值的部分,其灰度值全部变为0。

二、应用:
(1)效果展示:

import cv2
img=cv2.imread('3.jpg',0)
rows,cols=img.shape
ret1,mask1 = cv2.threshold(img,100,255,0)
ret2,mask2 = cv2.threshold(img,100,255,1)
ret3,mask3 = cv2.threshold(img,100,255,2)
ret4,mask4 = cv2.threshold(img,100,255,3)
ret5,mask5 = cv2.threshold(img,100,255,4)
cv2.imshow("img", img)
cv2.imshow("mask1", mask1)
cv2.imshow("mask2", mask2)
cv2.imshow("mask3", mask3)
cv2.imshow("mask4", mask4)
cv2.imshow("mask5", mask5)
cv2.waitKey()

【OpenCV + Python】图像阈值_第4张图片

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

前面看到简单阈值是一种全局性的阈值,只需要规定一个阈值值,整个图像都和这个阈值比较。而自适应阈值可以看成一种局部性的阈值,通过规定一个区域大小,比较这个点与区域大小里面像素点的平均值(或者其他特征)的大小关系确定这个像素点是属于黑或者白(如果是二值情况)。
dst = cv2.adaptiveThreshold(src, maxval, thresh_type, type, Block Size, C)
参数含义:
src: 输入图,只能输入单通道图像,通常来说为灰度图
dst: 输出图
maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定)所赋予的灰度值
thresh_type: 阈值的计算方法,包含以下2种类型:cv2.ADAPTIVE_THRESH_MEAN_C(阈值取自相邻区域的平均值); cv2.ADAPTIVE_THRESH_GAUSSIAN_C(阈值取值相邻区域的加权和,权重为一个高斯窗口).
type:二值化操作的类型,与固定阈值函数相同,从上面提到的5种中选择出的结果。
Block Size: 图片中分块的大小,表明我们要检查图像的11×11像素区域,而不是像在简单的阈值方法中那样尝试对图像进行全局阈值
C :阈值计算方法中的常数项,这就是是一个常数,阈值就等于的平均值或者加权平均值减去这个常数。我们提供一个简单的叫做C的参数。这个值是一个从平均值中减去的整数,使我们可以微调我们的阈值

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

import cv2
image=cv2.imread('3.jpg',0)
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,11,4)
cv2.imshow("GAUSSIAN thresh",thresh)
cv2.waitKey(0)

【OpenCV + Python】图像阈值_第5张图片
四、Otsu’s Binarization: 基于直方图的二值化
Otsu’s Binarization是一种基于直方图的二值化方法,它需要和threshold函数配合使用。Otsu过程:

  1. 计算图像直方图;
  2. 设定一阈值,把直方图强度大于阈值的像素分成一组,把小于阈值的像素分成另外一组;
  3. 分别计算两组内的偏移数,并把偏移数相加;
  4. 把0~255依照顺序多为阈值,重复1-3的步骤,直到得到最小偏移数,其所对应的值即为结果阈值。
import cv2
from matplotlib import pyplot as plt
img=cv2.imread('drawing.png',0)
# global thresholding
ret1,th1 = cv2.threshold(img,150,255,cv2.THRESH_BINARY)
# Otsu's thresholding
ret2,th2 = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# Otsu's thresholding after Gaussian filtering
#(5,5)为高斯核的大小,0 为标准差
blur = cv2.GaussianBlur(img,(5,5),0)
# 阈值一定要设为0!
ret3,th3 = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# plot all the images and their histograms
images = [img, 0, th1,img, 0, th2,blur, 0, th3]
titles = ['Original Noisy Image','Histogram','Global Thresholding (v=127)',
'Original Noisy Image','Histogram',"Otsu's Thresholding",
'Gaussian filtered Image','Histogram',"Otsu's Thresholding"]
for i in range(3):
    plt.subplot(3,3,i*3+1),plt.imshow(images[i*3],'gray')
    plt.title(titles[i*3]), plt.xticks([]), plt.yticks([])
    plt.subplot(3,3,i*3+2),plt.hist(images[i*3].ravel(),256)
    plt.title(titles[i*3+1]), plt.xticks([]), plt.yticks([])
    plt.subplot(3,3,i*3+3),plt.imshow(images[i*3+2],'gray')
    plt.title(titles[i*3+2]), plt.xticks([]), plt.yticks([])
plt.show()

【OpenCV + Python】图像阈值_第6张图片
符号对比(+与 |)结果是一样的,两个叠加效果:
import cv2
img=cv2.imread(‘5.jpg’,0)
rows,cols=img.shape
ret2,mask2 = cv2.threshold(img,23, 255,cv2.THRESH_OTSU | 1)
ret2,mask3 = cv2.threshold(img,0,255,1+ cv2.THRESH_OTSU)

cv2.namedWindow(“enhanced”,0)
cv2.namedWindow(“enhanced”,0)
cv2.resizeWindow(“mask3”, 400, 480)
cv2.resizeWindow(“mask2”, 400, 480)
cv2.resizeWindow(“img”, 400, 480)

cv2.imshow(“img”, img)
cv2.imshow(“mask3”, mask3)
cv2.imshow(“mask2”, mask2)
cv2.waitKey()

【OpenCV + Python】图像阈值_第7张图片

你可能感兴趣的:(opencv,python,PYTHON,opencv,图像阈值,Otsu’s,二值化,自适应阈值)