1 前言
上一篇介绍了用C++如何对一幅图像进行阈值处理,本篇接着用python来做同样的事情。
图像阈值处理是很多高级算法的底层逻辑之一,比如在做图形检测,轮廓识别时,常常会先对图像进行阈值处理,然后再进行具体的检测或识别。因此很有必要掌握图像的阈值处理技术。接下来我们一起探索一下OpenCV中的简单阈值处理、自适应阈值处理和Otsu阈值处理方法。
2 接口函数
使用Python调用OpenCV,实现阈值处理,主要使用了2个接口函数,以下是函数说明。
retval, dst = cv2.threshold(src, thresh, maxval, type)
参数说明:
参数1:待处理的图像,可以是彩色图像或灰度图像,建议使用灰度图像
参数2:阈值,一般在125~150之间取一个阈值,效果比较好
参数3:阈值处理采用的最大值
参数4:阈值处理类型,包括以下表格中的5种类型之一,表示简单的阈值处理;若要使用Otsu方法进行阈值处理,该参数在下列5种类型选择一个后,再加上THRESH_OTSU,比如THRESH_BINARY + THRESH_OTSU
返回值说明:
返回值1:处理是采用的阈值
返回值2:阈值处理后的图像
dst = cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C)
参数说明:
参数1:待处理的图像,必须使用灰度图像
参数2:阈值处理采用的最大值
参数3:自适应阈值计算方法,包括2种,如下表所示
枚举定义 | 意义 |
ADAPTIVE_THRESH_MEAN_C | 对一个正方形区域内的所有像素平均加权 |
ADAPTIVE_THRESH_GAUSSIAN_C | 根据高斯函数按照像素与中心点的距离对一个正方形区域内的所有像素进行加权计算 |
参数4:阈值处理类型,仅包括以下2种:THRESH_BINARY或THRESH_BINARY_INV
参数5:一个正方形区域的大小,例如11,就是11 x 11的矩阵区域
参数6:常量,阈值等于均值或加权值减去这个常量值
返回值:阈值处理后的图像
3 创建测试项目
创建测试项目、配置开发环境,具体可参考之前文章,这里就不多说了
Win10+Python3.10+OpenCV4.6.0加载显示图片_来灵的博客-CSDN博客_opencv-python4.6
这次测试项目名称img_threshold,VS2022种创建好的项目截图:
将下列代码编辑到img_threshold.py文件里,代码中有详细的注释:
# !usr/bin/env python
# -*- coding: utf-8 -*-
import cv2
#简单阈值处理
def SimpleThresholding(filePath):
print("start simple thresholding test...")
#以灰度图方式打开图像
src = cv2.imread(filePath, cv2.IMREAD_GRAYSCALE)
#打开失败
if src is None:
print("Error opening image...")
return
#显示原图
cv2.imshow('src', src)
#二值化处理
ret, dst = cv2.threshold(src, 127, 255, cv2.THRESH_BINARY)
cv2.imshow('binary', dst)
cv2.imwrite('binary.jpg', dst)
#反二值化处理
ret, dst = cv2.threshold(src, 127, 255, cv2.THRESH_BINARY_INV)
cv2.imshow('binary-inv', dst)
cv2.imwrite('binary-inv.jpg', dst)
#截断阈值处理
ret, dst = cv2.threshold(src, 127, 255, cv2.THRESH_TRUNC)
cv2.imshow('trunc', dst)
cv2.imwrite('trunc.jpg', dst)
#低于阈值0处理
ret, dst = cv2.threshold(src, 127, 255, cv2.THRESH_TOZERO)
cv2.imshow('tozero', dst)
cv2.imwrite('tozero.jpg', dst)
#超出阈值0处理
ret, dst = cv2.threshold(src, 127, 255, cv2.THRESH_TOZERO_INV)
cv2.imshow('to-zero-inv', dst)
cv2.imwrite('to-zero-inv.jpg', dst)
#按下任何键盘按键后退出
cv2.waitKey()
#销毁所有窗口
cv2.destroyAllWindows()
print("stop test...")
#自适应阈值处理
def AdaptiveThresholding(filePath):
print("start adaptive thresholding test...")
#以灰度图方式打开图像
src = cv2.imread(filePath, cv2.IMREAD_GRAYSCALE)
#打开失败
if src is None:
print("Error opening image...")
return
#显示原图
cv2.imshow('src', src)
#二值化处理
ret, dst = cv2.threshold(src, 127, 255, cv2.THRESH_BINARY)
cv2.imshow('binary', dst)
cv2.imwrite('binary.jpg', dst)
#自适应阈值
#阈值是邻近区域的平均值减去常数C
dst = cv2.adaptiveThreshold(src, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)
cv2.imshow('mean-binary', dst)
cv2.imwrite('mean-binary.jpg', dst)
#自适应阈值
#阈值是邻域值的高斯加权和减去常数C
dst = cv2.adaptiveThreshold(src, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
cv2.imshow('gauss-binary', dst)
cv2.imwrite('gauss-binary.jpg', dst)
#按下任何键盘按键后退出
cv2.waitKey()
#销毁所有窗口
cv2.destroyAllWindows()
print("stop test...")
#Otsu阈值处理
def OtsuThresholding(filePath):
print("start otsu thresholding test...")
#以灰度图方式打开图像
src = cv2.imread(filePath, cv2.IMREAD_GRAYSCALE)
#打开失败
if src is None:
print("Error opening image...")
return
#显示原图
cv2.imshow('src', src)
#二值化处理
ret, dst = cv2.threshold(src, 127, 255, cv2.THRESH_BINARY)
cv2.imshow('binary', dst)
cv2.imwrite('binary.jpg', dst)
#Otsu阈值
ret,dst = cv2.threshold(src, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
cv2.imshow('otsu-binary', dst)
cv2.imwrite('otsu-binary.jpg', dst)
#高斯去噪后使用Otsu阈值处理
blur = cv2.GaussianBlur(src, (5,5), 0)
ret,dst = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
cv2.imshow('gaussblur-binary', dst)
cv2.imwrite('gaussblur-binary.jpg', dst)
#按下任何键盘按键后退出
cv2.waitKey()
#销毁所有窗口
cv2.destroyAllWindows()
print("stop test...")
if __name__ == '__main__':
filePath = "test.jpg"
SimpleThresholding(filePath)
AdaptiveThresholding(filePath)
OtsuThresholding('gauss-noise.jpg')
编辑好代码的项目截图:
测试项目工程当前目录 :
4 效果截图
简单的阈值处理,以下图像,从左至右,从上到下,依次是原图灰度图像、二值化阈值处理、反二值化阈值处理、截断阈值处理、低于阈值0处理、超出阈值0处理对应的图像。
自适应阈值处理:
Otsu阈值处理:
彩色原图:
5 总结
- OpenCV中,对图像阈值处理有3种方法:简单的阈值处理、自适应阈值处理和Otsu阈值处理。其中简单的阈值处理又分为5种:二值化阈值处理、反二值化阈值处理、截断阈值处理、低于阈值0处理和超出阈值0处理。
- 简单的阈值处理,是选定一个全局的阈值,比如示例代码中的127。然后将图像中所有像素值与阈值做比较进行处理。这对于一幅明暗度分配不均匀的图像来说,并不友好。所以OpenCV提供了自适应阈值处理,自适应阈值处理,将一幅图像分为多个矩形区域,在每个区域,自动计算出一个合适的阈值,将该小区域内的所有像素与阈值比较进行处理。
- OpenCV的图像阈值处理接口使用比较简单,但作用很重要,它是很多高级算法的前置条件,比如图形检测,轮廓识别等。