雾看OpenCV(5)——图像阈值
目录
- 前言
- 正文
- 简单阈值
- cv2.threshhold()
- 自适应阈值
- cv2.adaptiveThreshold
- Otsu二值化
- 参考
前言
本节你将学到简单阈值,自适应阈值,Otsu’s 二值化等 • 将要学习的函数有 cv2.threshold,cv2.adaptiveThreshold 等。
正文
简单阈值
与名字一样,这种方法非常简单。但像素值高于阈值时,我们给这个像素 赋予一个新值(可能是白色),否则我们给它赋予另外一种颜色(也许是黑色)。 这个函数就是 cv2.threshhold()。
效果图
code
import cv2
import numpy as np
from matplotlib import pyplot as plt
img=cv2.imread('../images/lena.jpg',0)
ret,thresh1=cv2.threshold(img,127,255,cv2.THRESH_BINARY)
ret,thresh2=cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
ret,thresh3=cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
ret,thresh4=cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
ret,thresh5=cv2.threshold(img,127,255,cv2.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')plt.title(titles[i])plt.xticks([]),plt.yticks([])
plt.show()
cv2.threshhold()
这个函数的第一个参数就是原图像,原图 像应该是灰度图。
第二个参数就是用来对像素值进行分类的阈值。
第三个参数 就是当像素值高于(有时是小于)阈值时应该被赋予的新的像素值。
OpenCV 提供了多种不同的阈值方法,这是有第四个参数来决定的。
这第四个参数的方法我这里列举一些:
cv2.THRESH_BINARY
cv2.THRESH_BINARY_INV
cv2.THRESH_TRUNC
cv2.THRESH_TOZERO
cv2.THRESH_TOZERO_INV
自适应阈值
当同一幅图像上的不同部分的具有不 同亮度时,我们需要采用自适应阈值。此时的阈值是根据图像上的 每一个小区域计算与其对应的阈值。因此在同一幅图像上的不同区域采用的是 不同的阈值,从而使我们能在亮度不同的情况下得到更好的结果。
效果图
code
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt# img = cv2.imread('dave.jpg', 0)
src = cv.imread('../../images/lena.jpg', 0)
# 中值滤波
img = cv.medianBlur(src, 5)
ret, th1 = cv.threshold(img, 127, 255, cv.THRESH_BINARY)# 11 为 Block size 邻域大小 用来计算阈值的区域大小 ,
# 2 为 C值,常数, 阈值就等于的平均值或者加权平均值减去这个常数。
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)titles = ['Origin Image','Global threshold','Adaptive Gaussian','Adaptive Mean']
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()# cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
# cv.imshow('input image', src)
cv.waitKey(0) # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口cv.destroyAllWindows()
cv2.adaptiveThreshold
cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None)
1.src:原图像
2. maxValue:满足条件的像素点需要设置的灰度值。(将要设置的灰度值)
3. adaptiveMethod:自适应阈值算法。可选ADAPTIVE_THRESH_MEAN_C 或 ADAPTIVE_THRESH_GAUSSIAN_C
4. blockSize:要分成的区域大小,上面的N值,一般取奇数
5. C:常数,每个区域计算出的阈值的基础上在减去这个常数作为这个区域的最终阈值,可以为负数
6. dst=None:输出图像,可以忽略
Otsu二值化
如果是一副双峰图像(简 单来说双峰图像是指图像直方图中存在两个峰)呢?我们岂不是应该在两个峰 之间的峰谷选一个值作为阈值?这就是 Otsu 二值化要做的。简单来说就是对 一副双峰图像自动根据其直方图计算出一个阈值。
效果图
code
import cv2 as cv
import numpy as np
from matplotlib import pyplot as pltsrc = cv.imread("../../images/noisy2.png")
img = cv.cvtColor(src,cv.COLOR_BGR2GRAY)
## 全局阈值
ret1,th1 = cv.threshold(img,127,255,cv.THRESH_BINARY)
## OTSU阈值
ret,th2 = cv.threshold(img,0,255,cv.THRESH_BINARY + cv.THRESH_OTSU)
blur = cv.GaussianBlur(img,(5,5),0)#阈值一定要设为0
ret3,th3 = cv.threshold(blur,0,255,cv.THRESH_BINARY + cv.THRESH_OTSU)images = [src, 0, th1,src, 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([])print(i)
plt.show()# cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
# cv.imshow('input image', src)
# cv.waitKey(0) # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口
#
# cv.destroyAllWindows()
参考
雾看OpenCV(5)——图像阈值
目录
- 前言
- 正文
- 简单阈值
- cv2.threshhold()
- 自适应阈值
- cv2.adaptiveThreshold
- Otsu二值化
- 参考
前言
本节你将学到简单阈值,自适应阈值,Otsu’s 二值化等 • 将要学习的函数有 cv2.threshold,cv2.adaptiveThreshold 等。
正文
简单阈值
与名字一样,这种方法非常简单。但像素值高于阈值时,我们给这个像素 赋予一个新值(可能是白色),否则我们给它赋予另外一种颜色(也许是黑色)。 这个函数就是 cv2.threshhold()。
效果图
code
import cv2
import numpy as np
from matplotlib import pyplot as plt
img=cv2.imread('../images/lena.jpg',0)
ret,thresh1=cv2.threshold(img,127,255,cv2.THRESH_BINARY)
ret,thresh2=cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
ret,thresh3=cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
ret,thresh4=cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
ret,thresh5=cv2.threshold(img,127,255,cv2.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')plt.title(titles[i])plt.xticks([]),plt.yticks([])
plt.show()
cv2.threshhold()
这个函数的第一个参数就是原图像,原图 像应该是灰度图。
第二个参数就是用来对像素值进行分类的阈值。
第三个参数 就是当像素值高于(有时是小于)阈值时应该被赋予的新的像素值。
OpenCV 提供了多种不同的阈值方法,这是有第四个参数来决定的。
这第四个参数的方法我这里列举一些:
cv2.THRESH_BINARY
cv2.THRESH_BINARY_INV
cv2.THRESH_TRUNC
cv2.THRESH_TOZERO
cv2.THRESH_TOZERO_INV
自适应阈值
当同一幅图像上的不同部分的具有不 同亮度时,我们需要采用自适应阈值。此时的阈值是根据图像上的 每一个小区域计算与其对应的阈值。因此在同一幅图像上的不同区域采用的是 不同的阈值,从而使我们能在亮度不同的情况下得到更好的结果。
效果图
code
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt# img = cv2.imread('dave.jpg', 0)
src = cv.imread('../../images/lena.jpg', 0)
# 中值滤波
img = cv.medianBlur(src, 5)
ret, th1 = cv.threshold(img, 127, 255, cv.THRESH_BINARY)# 11 为 Block size 邻域大小 用来计算阈值的区域大小 ,
# 2 为 C值,常数, 阈值就等于的平均值或者加权平均值减去这个常数。
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)titles = ['Origin Image','Global threshold','Adaptive Gaussian','Adaptive Mean']
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()# cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
# cv.imshow('input image', src)
cv.waitKey(0) # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口cv.destroyAllWindows()
cv2.adaptiveThreshold
cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None)
1.src:原图像
2. maxValue:满足条件的像素点需要设置的灰度值。(将要设置的灰度值)
3. adaptiveMethod:自适应阈值算法。可选ADAPTIVE_THRESH_MEAN_C 或 ADAPTIVE_THRESH_GAUSSIAN_C
4. blockSize:要分成的区域大小,上面的N值,一般取奇数
5. C:常数,每个区域计算出的阈值的基础上在减去这个常数作为这个区域的最终阈值,可以为负数
6. dst=None:输出图像,可以忽略
Otsu二值化
如果是一副双峰图像(简 单来说双峰图像是指图像直方图中存在两个峰)呢?我们岂不是应该在两个峰 之间的峰谷选一个值作为阈值?这就是 Otsu 二值化要做的。简单来说就是对 一副双峰图像自动根据其直方图计算出一个阈值。
效果图
code
import cv2 as cv
import numpy as np
from matplotlib import pyplot as pltsrc = cv.imread("../../images/noisy2.png")
img = cv.cvtColor(src,cv.COLOR_BGR2GRAY)
## 全局阈值
ret1,th1 = cv.threshold(img,127,255,cv.THRESH_BINARY)
## OTSU阈值
ret,th2 = cv.threshold(img,0,255,cv.THRESH_BINARY + cv.THRESH_OTSU)
blur = cv.GaussianBlur(img,(5,5),0)#阈值一定要设为0
ret3,th3 = cv.threshold(blur,0,255,cv.THRESH_BINARY + cv.THRESH_OTSU)images = [src, 0, th1,src, 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([])print(i)
plt.show()# cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
# cv.imshow('input image', src)
# cv.waitKey(0) # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口
#
# cv.destroyAllWindows()