阈值处理在计算机视觉技术中占有十分重要的位置,他是很多高级算法的底层逻辑之一。本实验将练习使用图像阈值处理技术来处理不同的情况的图像,并获得图像轮廓。
完成本期内容,你可以:
-
了解图像阈值处理技术的定义和作用
-
掌握各阈值处理技术的原理
-
了解自适应阈值处理的使用场景
-
学会选择合适的阈值处理方式
若要运行案例代码,你需要有:
-
操作系统:Ubuntu 16 以上 或者 Windows10
-
工具软件:VScode 或者其他源码编辑器
-
硬件环境:无特殊要求
-
核心库:python 3.6.13, opencv-contrib-python 3.4.11.39,opencv-python 3.4.2.16
图像阈值处理函数
在图像处理过程中,阈值使得图像的像素值更单一,进而使得图像的效果更简单。首先把一幅彩色图像转换为灰度图像,这样图像的像素值的取值范围即可简化为0~255,然后通过阈值使用转换后的灰度图像呈现出只有黑色和宝白色的视觉效果。例如,当阈值为127时,把小于127的所有像素值都转换为0(即纯黑色),把大于127的像素值都转换为255(即纯白色),虽然会丢失一些灰度细节,但是会更明显的保留灰度图像主体的轮廓。
OpenCV中提供的对图像进行阈值处理的函数是cv2.threshold()。
函数原型: retval,dst = cv2.threshold(src, thresh, maxval, type);
retval为处理时所采用的阈值。
dst为转换后的图像。
参数描述如下:
参数 | 描述 |
---|---|
src | 原始图像 |
thresh | 阈值,阈值在125~150范围内取值的效果最好 |
maxval | 阈值处理采用的最大值 |
type | 阈值处理类型 |
阈值处理类型,如下:
类型 | 含义 |
---|---|
cv2.THRESH_BINARY | 二值化 |
cv2.THRESH_BINARY_INV | 反二值化阈值处理 |
cv2.THRESH_TOZERO | 低于阈值零处理 |
cv2.THRESH_TOZERO_INV | 超出阈值零处理 |
cv2.THRESH_TRUNC | 截断阈值处理 |
二值化处理
“非黑即白”的图像
二值化处理会将灰度图像的像素值两极分化,使得灰度图像呈现出只有纯黑色和纯白色的视觉效果。经过阈值处理后的图像轮廓分明、对比明显,因此二值化处理常用于图像识别。
if 像素值 <= 阈值:
像素值 = 0
if 像素值 > 阈值:
像素值 = 最大值
反二值化处理
反二值化处理也叫反二值化阈值处理,其结果为二值化处理的相反的结果。将大于阈值的像素值变为0,将小于或等于阈值的像素值变为最大值。原图中白色的部分会变成黑色,黑色的部分会变成白色。
if 像素值 <= 阈值:
像素值 = 像素值
if 像素值 > 阈值:
像素值 = 0
零处理
零处理会将某一个范围内的像素值变为0,并允许范围之外的像素保留原值。零处理包括低于阈值零处理和超出阈值零处理。
低于阈值零处理
低于阈值进行零处理也叫零阈值零处理,该处理会将低于或等于阈值的像素值变为0,大于阈值的像素值保持原值。
if 像素值 <= 阈值:
像素值 = 0
if 像素值 > 阈值:
像素值 = 原值
超出阈值零处理
超出阈值进行零处理也叫超阈值零处理,该处理会将大于阈值的像素值变为0,小于或等于阈值的像素值保持原值。
if 像素值 <= 阈值:
像素值 = 原值
if 像素值 > 阈值:
像素值 = 0
截断处理
截断处理也叫截断阈值处理,该处理会将图像中大于阈值的像素值变为和阈值一样的值,小于或等于阈值的像素保持原值。
if 像素值 <= 阈值:
像素值 = 原值
if 像素值 > 阈值:
像素值 = 阈值
自适应处理
OpenCV提供了一种改进的阈值处理技术:图像中不同区域使用不同的阈值,把这种改进的阈值处理技术称作自适应阈值处理,自适应阈值是根据图像中某一正方形区域内的所有像素值按照指定的算法计算得到的。与上文讲解的5中阈值处理类型相比,自适应阈值处理能更好地处理明暗分布不均的图像,获得更简单的图像。
if 像素值 <= 阈值:
像素值 = 原值
if 像素值 > 阈值:
像素值 = 阈值
OpenCV中提供的对图像进行自适应阈值处理的函数是cv2.adaptiveThreshold()。
函数原型: dst = cv2.adaptiveThreshold(src,maxValue,adaptiveMethod, threshholdType, blockSize, C);
dst为转换后的图像。
参数描述如下:
参数 | 描述 |
---|---|
src | 需要被处理的图像,该图像须是灰度图像 |
maxValue | 阈值处理采用的最大值 |
threshholdType | 阈值处理类型;需要注意的是,阈值处理类型必须是cv2.THRESH_BINARY或者cv2.THRESH_BINARY_INV中的一个。 |
blockSize | 一个正方形区域的大小。 |
C | 常量。阈值等于均值或者加权值减去这个常量 |
adaptiveMethod | 自适应阈值的计算方法。 |
自适应阈值的计算方法,如下:
类型 | 含义 |
---|---|
cv2.ADAPTIVE_THRESH_MEAN_C | 对一个正方形区域内的所有像素平均加权 |
cv2.ADAPTIVE_THRESH_GAUSSIAN_C | 根据高斯函数按照像素与中心点的距离对一个正方形区域内的所有像素进行加权计算 |
Otsu方法
对于有些图像,当主观去设置阈值时,可能得到的效果并不好,这时就需要一个个的去尝试,知道找到最合适的阈值。逐个寻找最合适的阈值不仅工作量大,而且效率低。为此。OpenCV提供了Otsu方法,Otsu方法能够遍历所有可能的阈值,从中找到最合适的阈值。Otsu方法的语法和threshold()方法的语法基本一致。只不过在为type传递参数时,要多传递一个参数,cv2.THRESH_OTSU的作用是实现Otsu方法的阈值处理。
OpenCV中提供的对图像进行Otsu的函数是cv2.threshold()。
函数原型:retval,dst = cv2.threshold(src, thresh, maxval, type);
retval为处理时所采用的阈值。
dst为转换后的图像。
参数描述如下:
参数 | 描述 |
---|---|
src | 原始图像 |
thresh | 阈值,阈值在125~150范围内取值的效果最好 |
maxval | 阈值处理采用的最大值 |
type | 阈值处理类型 |
阈值处理类型,如下:
类型 | 含义 |
---|---|
cv2.THRESH_BINARY | 二值化 |
cv2.THRESH_BINARY_INV | 反二值化阈值处理 |
cv2.THRESH_TOZERO | 低于阈值零处理 |
cv2.THRESH_TOZERO_INV | 超出阈值零处理 |
cv2.THRESH_TRUNC | 截断阈值处理 |
具体步骤
1. 创建项目结构
创建项目名为利用阈值勾勒建筑轮廓
,项目根目录下新建code
文件夹储存代码,新建dataset
文件夹储存数据,项目结构如下:
利用阈值勾勒建筑轮廓 # 项目名称
├── code # 储存代码文件
├── dataset # 储存数据文件
注:如项目结构已存在,无需再创建。
2. 利用二值化阈值处理勾勒别墅轮廓图
- 在
code
文件夹下创建binary.py
- 读取
dataset
文件夹下的villa.png
图片,并进行展示 ; - 将图片进行二值化处理,并进行展示,标题为
BINARY
; - 将图片进行反二值化处理,并进行展示,标题为
BINARY_INV
; - 无限等待用户输入按键,按下按键后销毁所有窗口。
代码实现
# 导入OpenCV
import cv2
# 读取图像
img = cv2.imread("../dataset/villa.png")
# 转为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值化阈值处理
t1, dst1 = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
# 反二值化阈值处理
t2, dst2 = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV)
cv2.imshow("img", img) # 显示图像
cv2.imshow("BINARY", dst1)
cv2.imshow("BINARY_INV", dst2)
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体
3. 利用Otsu方法勾勒图像轮廓
- 在
code
文件夹下创建otsu.py
- 读取
dataset
文件夹下的tower.png
图片,并进行展示 ; - 将图片进行二值化处理,并进行展示,标题为
BINARY
; - 将图片进行Otsu处理,并进行展示,标题为
Otsu
; - 在图像上显示最合适的阈值;
- 无限等待用户输入按键,按下按键后销毁所有窗口。
代码实现
# 导入OpenCV
import cv2
# 读取图片
image = cv2.imread("../dataset/tower.png")
# 步骤一: 对图像进行二值化处理
image_Gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) #转换为灰度图
t1, dst1 = cv2.threshold(image_Gray, 127, 255, cv2.THRESH_BINARY) # 二值化阈值处理
# 步骤二: 实现Otsu方法的阈值处理
t2, dst2 = cv2.threshold(image_Gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
cv2.putText(dst2, "best threshold: " + str(t2), (0, 30),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2) # 在图像上绘制最合适的阈值
cv2.imshow("img", image) # 显示原始图像图像
cv2.imshow("BINARY", dst1) # 显示二值化阈值处理的图像
cv2.imshow("OTSU", dst2) # 显示实现Otsu方法的阈值处理
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 销毁所有窗口
阈值处理在计算机视觉 技术中占有十分重要的位置,他是很多高级算法的底层逻辑之一。因为二值图像会忽略细节,放大特征,而很多高级算法要根据物体的轮廓来分析物体的特征,所以二值图像非常适合做复杂的识别运算,在进行识别运算之前,应先将图像转为灰度图像,再进行二值化阈值处理,这样就得到了算法所需要的物体(大致)轮廓图像。