app开发者平台在数字化时代的重要性与发展趋势解析
635
2022-11-26
【OpenCV C++&Python】(四)图像阈值处理
文章目录
图像阈值处理
Python
简单阈值处理自适应阈值处理大津(Otsu)法
C++
简单阈值处理自适应阈值处理大津(Otsu)法
图像阈值处理
Python
简单阈值处理
OpenCV的cv.threshold用于简单阈值处理,它的第一个参数是灰度源图像src;第二个参数是阈值thresh;第三个参数是赋值给超过阈值的像素的最大值maxval;第四个参数则是阈值处理的类型:
cv.threshold返回两个输出。第一个是使用的阈值,第二个输出是阈值图像dst。下面比较不同类型的阈值处理方法:
import cv2 as cvfrom matplotlib import pyplot as pltimport numpy as npimg = cv.imread('threshold.jpg', 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') plt.title(titles[i]) plt.xticks([]), plt.yticks([])plt.show()
自适应阈值处理
简单阈值处理在图像全局都使用同一个阈值,如果图像在不同区域有不同的照明条件,这可能就不适用了。在这种情况下,自适应阈值处理更适合。自适应阈值处理根据像素周围的一个小区域来确定阈值。可以使用OpenCV的cv.adaptiveThreshold实现这个功能。
cv.adaptiveThreshold的第一个参数是灰度源图像src;第二个参数是赋值给超过阈值的像素的最大值maxval;
第三个参数adaptiveMethod决定如何计算阈值:
cv.ADAPTIVE_THRESH_MEAN_C:阈值是邻域内像素的平均值减去常数C。cv.ADAPTIVE_THRESH_GAUSSIAN_C:阈值是邻域内像素的高斯加权和减去常数C。
第四个参数则是阈值处理的类型;第五个参数 blockSize决定邻域区域的大小;第六个参数是常数C。
下面对比一下简单阈值处理和自适应阈值处理:
import cv2 as cvfrom matplotlib import pyplot as pltimg = cv.imread('adaptiveThreshold.jpg', 0)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)titles = ['Original Image', 'BINARY(v=127)', 'ADAPTIVE_THRESH_MEAN_C', 'ADAPTIVE_THRESH_GAUSSIAN_C']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)法
在普通阈值处理中,我们需要指定阈值。大津法则能够从图像直方图中自动确定一个最优的全局阈值,即使用大津法不用人工挑选阈值。
由上面式子可得:
类内方差(within-class variance) 定义为:
反映每一类样本方差的大小。(值越小,各类的样本越集中,越好分割)
类间方差(between-class variance) 定义为:
相当于以每一类的均值作为该类的代表值,以总体均值为均值计算方差。类间方差反映阈值两侧数据之间的差异程度。(值越大,类别越明显,越好分割)
再由:
得到:
即类内方差与类间方差之和为定值,最大化类间方差与最小化类内方差等价。
使用cv.threshold()函数,阈值处理的类型可以任意选择,THRESH_OTSU作为一个额外的flag即可使用大津法。下面以一个直方图包含两个峰的图像(双峰图像)为例:
import cv2 as cvfrom matplotlib import pyplot as pltimg = cv.imread('coins.png', 0)# 普通二值化ret1, th1 = cv.threshold(img, 127, 255, cv.THRESH_BINARY)# Otsu法二值化ret2, th2 = cv.threshold(img, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU) # 随便给个0为阈值images = [img, [], th1, img, [], th2]titles = ['Original Image', 'Histogram', 'BINARY (v=127)', 'Original Image', 'Histogram', 'OTSU(v=0)']for i in range(2): plt.subplot(2, 3, i * 3 + 1), plt.imshow(images[i * 3], 'gray') plt.title(titles[i * 3]), plt.xticks([]), plt.yticks([]) plt.subplot(2, 3, i * 3 + 2), plt.hist(images[i * 3].ravel(), 256) plt.title(titles[i * 3 + 1]), plt.xticks([]), plt.yticks([]) plt.subplot(2, 3, i * 3 + 3), plt.imshow(images[i * 3 + 2], 'gray') plt.title(titles[i * 3 + 2]), plt.xticks([]), plt.yticks([])plt.show()
大津法无需人工指定阈值即可达到较为理想的效果。
C++
简单阈值处理
#include
自适应阈值处理
#include
大津(Otsu)法
#include
代码: 人民邮电出版社
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~