Bootstrap

OpenCV入门——阈值处理

OpenCV入门——阈值处理

阈值处理在图像处理领域也是十分常见,常用于图像分割。是将数字图像划分成互不相交的区域的过程,在目标检测和提取方面有比较重要的地位。
OpenCV提供了函数*cv2.threshold()和函数cv2.adaptiveThreshold()*用于实现阈值处理。
threshold函数书写格式如下
retval,dst=cv2.threshold( src, thresh, maxval, type)

根据type参数的不同可分为一下几种
在这里插入图片描述
示例代码与结果图如下:
二值化

import cv2
img=cv2.imread("lena.bmp")
t,rst=cv2.threshold(img,127,255,cv2.THRESH_BINARY)
cv2.imshow("img",img)
cv2.imshow("rst",rst)
cv2.waitKey()
cv2.destroyAllWindows()

原图
在这里插入图片描述

二值化翻转
代码与二值化相同,只不过将cv2.THRESH_BINARY改成cv2.THRESH_BINARY_INV
结果图像如下,即二值化图中所有白色的部分变成了黑色,黑色部分变成了白色。
在这里插入图片描述

截断
代码同二值化,type值cv2.THRESH_BINARY改成cv2.THRESH_TRUNC
结果如下图,与前面的两个二值化相比更加柔和,像素值小于127的部分能表示更多细节
在这里插入图片描述

归零
该方法与二值化处理效果黑色部分相同,只不过大于127的地方纹理保存下来了,而二值化结果是将大于127位置变为白色。
在这里插入图片描述

归零翻转
在这里插入图片描述

自适应阈值处理

cv2.adaptiveThreshold()根据名字就可以看出这个函数是自适应(adaptive)阈值处理。
dst = cv2.adaptiveThreshold( src, maxValue,adaptiveMethod ,thresholdType,blockSize,C)

adaptiveMethod包含cv2.ADAPTIVE_THRESH_MEAN_C和cv2.ADAPTIVE_THRESH_GAUSSIAN_C两种不同的方法。
这两种方法都是逐个像素地计算自适应阈值,阈值等于每个像素由参数blockSize所指定邻域的加权平均值减去常量C。
cv2.ADAPTIVE_THRESH_MEAN_C:邻域所有像素点的权重值是一致的。
cv2.ADAPTIVE_THRESH_GAUSSIAN_C:与邻域各个像素点到中心点的距离有关,通过高斯方程得到各个点的权重值。
(个人理解会有类似滤波的效果)
虽然信息丢失了很多,但是背景基本上被去掉了。丢失的人物的信息可以通过位运算等恢复。在去除背景提取前景方面,自适应阈值函数要有效很多。

以下是代码和示例:

import cv2
img=cv2.imread("computer.jpg",0)
t1,thd=cv2.threshold(img,127,255,cv2.THRESH_BINARY)
athdMEAN=cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,3,5)
athdGAUS=cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,3,5)
cv2.imshow("img",img)
cv2.imshow("thd",thd)
cv2.imshow("athdMEAN",athdMEAN)
cv2.imshow("athdGAUS",athdGAUS)
cv2.waitKey()
cv2.destroyAllWindows()

结果
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

根据处理结果可以看到,给定数值很难做到将图片中想要的信息清晰地表达出来,而自适应只需要给定一个最大值即可自动得到较好的分割结果。而高斯和均值两种方式处理结果差距并不大。

Otsu处理
Otsu处理适用于图像灰度级的分布不均衡的时候。在处理效率上,Otsu方法效率偏低,因为需要遍历所有可能阈值,从而找到最佳的阈值。处理单幅图像还好,如果带入到神经网络中处理成千上万个样本图时,这种效率上的差别还是需要考虑的。
Otsu处理方式与其他阈值处理方法写法相同,在type参数上加上了cv2.THRESH_OTSU,阈值设为0,最大值设置为八位的最大值255,程序就会找到合适的阈值对图像进行分割

t,otsu=cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

示例代码和结果:

import cv2
img=cv2.imread("tiffany.bmp",0)
t1,thd=cv2.threshold(img,127,255,cv2.THRESH_BINARY)
t2,otsu=cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
cv2.imshow("img",img)
cv2.imshow("thd",thd)
cv2.imshow("otus",otsu)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

根据处理结果可以看到类似该图纹理信息较丰富仅使用阈值也是较容易抹掉很多信息,Otsu不论从结果上还是代码上都较为便捷。省去了反复试来找阈值的过程。

;