OpenCV库的学习笔记(五)Image Thresholding

目标

 

  • 在本教程中,您将学习简单阈值化自适应阈值化大津二值化
  • 您将学习函数 cv.thresholdcv.adaptiveThreshold

简单阈值化

在这里,事情很简单。对于每个像素,应用相同的阈值。如果像素值小于阈值,则设置为0,否则设置为最大值。函数 cv.threshold 用于应用阈值化。第一个参数是源图像,应该是灰度图像。第二个参数是用于对像素值进行分类的阈值。第三个参数是分配给超过阈值的像素值的最大值。 OpenCV 提供不同类型的阈值,由函数的第四个参数给出。如上所述的基本阈值处理是通过使用类型 cv.THRESH_BINARY 完成的。

上述函数具体的表达式如下图所示:
 

该方法返回两个输出。第一个是使用的阈值,第二个输出是阈值图像
具体代码实例如下:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread('gradient.png',0)
ret,thresh1 = cv.threshold(img,127,255,cv.THRESH_BINARY)
ret,thresh2 = cv.threshold(img,127,255,cv.THRESH_BINARY_INV)
ret,thresh3 = cv.threshold(img,127,255,cv.THRESH_TRUNC)
ret,thresh4 = cv.threshold(img,127,255,cv.THRESH_TOZERO)
ret,thresh5 = cv.threshold(img,127,255,cv.THRESH_TOZERO_INV)
titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
for i in range(6):
    plt.subplot(2,3,i+1),plt.imshow(images[i],'gray',vmin=0,vmax=255)
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()

注意此处的代码书写,是特别简略得当的。

自适应阈值化

在上一节中,我们使用一个全局值作为阈值。但这可能并不适用于所有情况,例如如果图像在不同区域具有不同的照明条件。在这种情况下,自适应阈值可以提供帮助。在这里,算法根据像素周围的小区域确定像素的阈值。因此,我们为同一图像的不同区域获得不同的阈值,这为具有不同光照的图像提供了更好的结果。

除了上述参数外,方法 cv.adaptiveThreshold 还需要三个输入参数:

自适应方法决定如何计算阈值:

  • cv.ADAPTIVE_THRESH_MEAN_C:阈值是邻域面积的平均值减去常量C。
  • cv.ADAPTIVE_THRESH_GAUSSIAN_C:阈值是邻域值减去常量C的高斯加权和。

blockSize 确定邻域区域的大小,C 是从邻域像素的平均值或加权总和中减去的常数。

下面的代码比较了具有不同光照的图像的全局阈值和自适应阈值:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread('lisa.jpeg',0)
img = cv.medianBlur(img,5)
ret,th1 = cv.threshold(img,127,255,cv.THRESH_BINARY)
th2 = cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_MEAN_C,\
            cv.THRESH_BINARY,11,2)
th3 = cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,\
            cv.THRESH_BINARY,11,2)#11是块的大小,有3,5,7等
titles = ['Original Image', 'Global Thresholding (v = 127)',
            'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
images = [img, th1, th2, th3]
for i in range(4):
    plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()

自适应阈值化能够很好的把握图像的边缘特性,高斯阈值化能够清理一些均值阈值化的噪声。

大津二值化(Otsu's Binarization)

在全局阈值中,我们使用任意选择的值作为阈值。相反,Otsu 的方法避免了必须选择一个值并自动确定它。(可以自动选择阈值

考虑只有两个不同图像值的图像(双峰图像),其中直方图仅包含两个峰值。一个好的阈值应该在这两个值的中间。类似地,Otsu 的方法从图像直方图中确定最佳全局阈值。

为此,使用了 cv.threshold() 函数,其中 cv.THRESH_OTSU 作为额外标志传递。阈值可以任​​意选择。然后算法找到最佳阈值,该阈值作为第一个输出返回。

查看下面的示例。输入图像是有噪声的图像。在第一种情况下,应用值为 127 的全局阈值。在第二种情况下,直接应用 Otsu 的阈值。在第三种情况下,首先使用 5x5 高斯核对图像进行滤波以去除噪声,然后应用 Otsu 阈值处理。查看噪声过滤如何改善结果。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread('noisy2.png',0)
# global thresholding
ret1,th1 = cv.threshold(img,127,255,cv.THRESH_BINARY)
# Otsu's thresholding
ret2,th2 = cv.threshold(img,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
# Otsu's thresholding after Gaussian filtering
blur = cv.GaussianBlur(img,(5,5),0)
ret3,th3 = cv.threshold(blur,0,255,cv.THRESH_BINARY+cv.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()

注意一点是,灰度直方图如何表示:plt.hist(images[i*3].ravel(),256),.ravel()是将其拉成一维数组。

Otsu二值化是如何工作的呢?

本节演示 Otsu 二值化的 Python 实现,以展示它的实际工作原理。如果你不感兴趣,你可以跳过这个。

由于我们使用的是双峰图像,Otsu 的算法试图找到一个阈值 (t),它可以最小化由以下关系给出的加权类内方差:

 其中:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值