目录
[1. 核心 API 与原理](#1. 核心 API 与原理)
[2. 实战代码示例](#2. 实战代码示例)
[3. 应用场景](#3. 应用场景)
[1. 均值滤波(cv2.blur)](#1. 均值滤波(cv2.blur))
[2. 方框滤波(cv2.boxFilter)](#2. 方框滤波(cv2.boxFilter))
[3. 高斯滤波(cv2.GaussianBlur)](#3. 高斯滤波(cv2.GaussianBlur))
[4. 中值滤波(cv2.medianBlur)](#4. 中值滤波(cv2.medianBlur))
[三、图像形态学操作:像素的 "变形术"](#三、图像形态学操作:像素的 “变形术”)
[1. 基础操作:腐蚀与膨胀](#1. 基础操作:腐蚀与膨胀)
[2. 组合操作:开运算与闭运算](#2. 组合操作:开运算与闭运算)
[3. 进阶操作:梯度、顶帽、黑帽](#3. 进阶操作:梯度、顶帽、黑帽)
前言
OpenCV 作为计算机视觉领域的经典库,提供了丰富的图像处理接口。本文将从阈值处理开始,结合实战代码,拆解图像阈值分割、平滑去噪、形态学操作、边缘检测、轮廓提取等核心技法,帮你快速掌握 OpenCV 图像处理的核心逻辑。
一、阈值处理:像素级的二值化分割
阈值处理是图像处理中最基础的像素筛选手段,核心是通过设定阈值,将图像像素划分为 "高于阈值" 和 "低于阈值" 两类,实现图像的二值化或灰度映射。
1. 核心 API 与原理
OpenCV 中阈值处理的核心函数是cv2.threshold(),函数定义如下:
python
retval, dst = cv2.threshold(src, thresh, maxval, type)
'''参数说明:
src:输入图像(推荐灰度图,处理效果更直观);
thresh:设定的阈值(0~255);
maxval:二值化类型下的最大值(通常设为 255);
type:阈值分割类型,核心类型如下:
类型 像素值 > 阈值 其他情况 效果说明
cv2.THRESH_BINARY maxval 0 亮区纯白,暗区纯黑
cv2.THRESH_BINARY_INV 0 maxval 亮区纯黑,暗区纯白(反向)
cv2.THRESH_TRUNC thresh 原灰度值 超过阈值的像素统一为阈值
cv2.THRESH_TOZERO 原灰度值 0 低于阈值的像素置 0,其余保留
cv2.THRESH_TOZERO_INV 0 原灰度值 高于阈值的像素置 0,其余保留
'''
2. 实战代码示例
python
import cv2
# 读取灰度图
image = cv2.imread('zl.png', 0)
# 不同阈值类型处理
ret, binary = cv2.threshold(image, 175, 255, cv2.THRESH_BINARY)
ret1, binaryinv = cv2.threshold(image, 175, 255, cv2.THRESH_BINARY_INV)
ret2, trunc = cv2.threshold(image, 175, 255, cv2.THRESH_TRUNC)
ret3, tozero = cv2.threshold(image, 175, 255, cv2.THRESH_TOZERO)
ret4, tozeroinv = cv2.threshold(image, 175, 255, cv2.THRESH_TOZERO_INV)
# 展示效果
cv2.imshow('原始灰度图', image)
cv2.imshow('THRESH_BINARY', binary)
cv2.imshow('THRESH_BINARY_INV', binaryinv)
cv2.imshow('THRESH_TRUNC', trunc)
cv2.imshow('THRESH_TOZERO', tozero)
cv2.imshow('THRESH_TOZERO_INV', tozeroinv)
cv2.waitKey(0)
cv2.destroyAllWindows()

3. 应用场景
阈值处理常用于++文档扫描++ (提取文字)、++车牌识别++ (分割车牌区域)、++目标轮廓粗提取++等场景,是后续复杂处理的基础。
二、图像平滑:去除噪声的四大滤波手段
图像平滑(模糊处理)的核心是压制图像中的噪声、弱化细节,OpenCV 提供了四种常用滤波方式,适用于不同噪声场景。
1. 均值滤波(cv2.blur)
python'''均值滤波 # dst=cv2.blur(src,ksize,anchor,borderType) # dst是返回值 # src是需要处理的图像 # kszie是滤波核(卷积核)的大小 # anchor是锚点,默认值是(-1,-1)一般无需更改 # borderType是边界样式,一般无需更改 # 一般情况下,使用dst=cv2.blur(src,ksize)即可 '''
原理:以目标像素为中心,取邻域内所有像素的平均值作为新像素值,对椒盐噪声有一定抑制效果,但会导致图像模糊。
python
import cv2
import numpy as np
def add_peppersalt_noise(image, n=10000):
result = image.copy()
h, w = image.shape[:2] # 获取图片的高和宽
for i in range(n): # 生成n个椒盐噪声
x = np.random.randint(1, h)
y= np.random.randint(1, w)
if np.random.randint(0, 2) == 0:
result[x, y] = 0
else:
result[x,y] = 255
return result
image = cv2.imread('zl.png')
cv2.imshow('sro',image)
cv2.waitKey(0)
noise = add_peppersalt_noise(image)
cv2.imshow('noise',noise)
cv2.waitKey(0)
#
# # 均值滤波 blur
blur_1 = cv2.blur(noise,(3,3)) #卷积核为3,3 效果一般,清晰度一般
cv2.imshow('blur_1',blur_1)
cv2.waitKey(0)
blur_2 = cv2.blur(noise,(5,5))#卷积核为5,5 效果稍好但模糊
cv2.imshow('blur_2',blur_2)
cv2.waitKey(0)
cv2.destroyAllWindows()

2. 方框滤波(cv2.boxFilter)
原理:与均值滤波类似,但可选择是否归一化:
归一化(
normalize=True):等价于均值滤波;不归一化(
normalize=False):直接取邻域像素和,超过 255 则置 255,易出现过曝。
python''' dst=cv2.boxFilter(src,ddepth,ksize,anchor,normalize,borderType)式中: ● dst是返回值,表示进行方框滤波后得到的处理结果。 ● src 是需要处理的图像,即原始图像。 ● ddepth是处理结果图像的图像深度,一般使用-1表示与原始图像使用相同的图像深度。(可以理解为数据类型) ● ksize 是滤波核的大小。滤波核大小是指在滤波处理过程中所选择的邻域图像的高 度和宽度。 ● anchor 是锚点,(指对应哪个区域) ● normalize 表示在滤波时是否进行归一化。 1.当值为True时,归一化,用邻域像素值的和除以面积。 此时方框滤波与 均值滤波 效果相同。 2.当值为False时,不归一化,直接使用邻域像素值的和。和>255时使用255 '''
python
# 方框滤波示例
box_norm = cv2.boxFilter(noise_image, -1, (3, 3), normalize=True)
box_unnorm = cv2.boxFilter(noise_image, -1, (3, 3), normalize=False)
cv2.imshow('归一化方框滤波', box_norm)
cv2.imshow('不归一化方框滤波', box_unnorm)
cv2.waitKey(0)

3. 高斯滤波(cv2.GaussianBlur)
原理:对邻域像素加权平均(距离中心越近,权重越大),更贴合人眼视觉,去噪同时保留更多细节,是最常用的平滑手段。
python''' cv2.GaussianBlur(src, ksize[, sigmaX[, sigmaY[, dst]]])高斯滤波 # 参数说明: # src:输入图像,通常是一个NumPy数组。 # ksize:滤波器的大小,它是一个元组,表示在水平和垂直方向上的像素数量。例如,(5, 5)表示一个5x5的滤波器。 # sigmaX和sigmaY:分别表示在X轴和Y轴方向上的标准差。这些值与滤波器大小相同。默认情况下,它们都等于0,这意味着没有高斯模糊。 # dst:输出图像,通常是一个NumPy数组。如果为None,则会创建一个新的数组来存储结果。 '''
python
# 高斯滤波(sigma越大,模糊越强)
gaussian_blur = cv2.GaussianBlur(noise_image, (3, 3), 1)
cv2.imshow('高斯滤波', gaussian_blur)
cv2.waitKey(0)

4. 中值滤波(cv2.medianBlur)
原理:取邻域像素的中值作为新像素值,对椒盐噪声抑制效果极佳(秒杀均值 / 高斯滤波),但处理速度稍慢。
python''' cv2.medianBlur(src, ksize[, dst])中值滤波 # 参数说明: # src:输入图像。 # ksize:滤波器的大小,它是一个整数,表示在水平和垂直方向上的像素数量。例如,5表示一个5x5的滤波器。 # dst:输出图像,通常是一个NumPy数组。如果为None,则会创建一个新的数组来存储结果。 '''
python
# 中值滤波(核必须是奇数)
median_blur = cv2.medianBlur(noise_image, 5)
cv2.imshow('中值滤波', median_blur)
cv2.waitKey(0)
cv2.destroyAllWindows()

5.滤波选型总结
| 滤波类型 | 核心优势 | 适用场景 |
|---|---|---|
| 均值滤波 | 速度快 | 轻度噪声、对模糊不敏感的场景 |
| 方框滤波 | 灵活(可归一化) | 自定义权重的简单场景 |
| 高斯滤波 | 去噪 + 保细节 | 通用场景(推荐首选) |
| 中值滤波 | 椒盐噪声克星 | 图像含大量椒盐噪声(如相机噪点) |
三、图像形态学操作:像素的 "变形术"
形态学操作基于像素的邻域形状,实现图像的 "腐蚀""膨胀" 等变形,核心用于轮廓修正、噪声去除、边缘提取。
1. 基础操作:腐蚀与膨胀
- 腐蚀(cv2.erode):收缩图像中的亮区,可去除小的亮噪声、细化轮廓;
python''' # cv2.erode(src, kernel, dst,anchor,iterations,borderType,borderValue) # src: 输入的图像 # kernel: 用于腐蚀的结构元件如果element = Mat(),则使用3 × 3的矩形结构单元。 # dst: 它是与src相同大小和类型的输出图像。 # iterations:腐蚀操作的迭代次数,默认为1。次数越多, 腐蚀操作执行的次数越多,腐蚀效果越明显 '''
- 膨胀(cv2.dilate):扩张图像中的亮区,可填补轮廓缺口、加粗线条。
python''' # cv2.dilate(img, kernel, iteration) # 参数含义: # img -- 目标图片 # kernel -- 进行操作的内核,默认为3×3的矩阵 # iterations -- 膨胀次数,默认为1 '''
python
import cv2
import numpy as np
# 1. 腐蚀操作
sun = cv2.imread('sun.png')
kernel = np.ones((3, 3), np.uint8) # 结构核(越大效果越明显)
erosion = cv2.erode(sun, kernel, iterations=5) # iterations:迭代次数
cv2.imshow('src', sun)
cv2.imshow('erosion_1', erosion)
cv2.waitKey(0)
# 2. 膨胀操作
text = cv2.imread('wenzi.png')
kernel = np.ones((2, 2), np.uint8)
dilate = cv2.dilate(text, kernel, iterations=2)
cv2.imshow('wenzi', text)
cv2.imshow('wenzi_new', dilate)
cv2.waitKey(0)

2. 组合操作:开运算与闭运算
- 开运算(先腐蚀后膨胀):去除亮噪声、分离相邻的亮区;
- 闭运算(先膨胀后腐蚀):填补暗缺口、连接断开的暗区。
python
# 开运算(去除指纹噪声)
fingerprint = cv2.imread('zhiwen.png')
kernel = np.ones((2, 2), np.uint8)
open_op = cv2.morphologyEx(fingerprint, cv2.MORPH_OPEN, kernel)
cv2.imshow('yuan', fingerprint)
cv2.imshow('zhiwen_new_open', open_op)
cv2.waitKey(0)
# 闭运算(填补指纹缺口)
fingerprint_break = cv2.imread('zhiwen_duan.png')
kernel = np.ones((4, 4), np.uint8)
close_op = cv2.morphologyEx(fingerprint_break, cv2.MORPH_CLOSE, kernel)
cv2.imshow('po', fingerprint_break)
cv2.imshow('zhiwen_new_close', close_op)
cv2.waitKey(0)

3. 进阶操作:梯度、顶帽、黑帽
梯度运算:膨胀 - 腐蚀,提取图像轮廓;
顶帽运算 :原始图 - 开运算结果,突出亮噪声;顶帽 = 原始图像 - 开运算结果(先腐蚀后膨胀)
黑帽运算 :闭运算结果 - 原始图,突出暗缺口。黑帽 = 闭运算(先膨胀后腐蚀) - 原始图像
python
'''4梯度运算: 膨胀-腐蚀'''
wenzi = cv2.imread('wenzi.png')
cv2.imshow('yuan',wenzi)
cv2.waitKey(0)
kernel = np.ones((2,2),np.uint8) #设置kenenel大小
# # 膨胀
pz_wenzi=cv2.dilate(wenzi,kernel,iterations=2)
cv2.imshow('pz_wenzi',pz_wenzi)
cv2.waitKey(0)
# #腐蚀
fs_wenzi=cv2.erode(wenzi,kernel,iterations=1)
cv2.imshow('fs_wenzi',fs_wenzi)
cv2.waitKey(0)
# # 膨胀-腐蚀
bianyuan = cv2.morphologyEx(wenzi,cv2.MORPH_GRADIENT,kernel)
cv2.imshow('bianyuan',bianyuan)
cv2.waitKey(0)
# # 5、顶帽和黑帽
# # 顶帽 = 原始图像 - 开运算结果(先腐蚀后膨胀)
# # 黑帽 = 闭运算(先膨胀后腐蚀) - 原始图像
sun = cv2.imread('sun.png')
cv2.imshow('sun_yuantu',sun)
cv2.waitKey(0)
kernel = np.ones((2,2),np.uint8) #设置kenenel大小
# #开运算
open_sun=cv2.morphologyEx(sun,cv2.MORPH_OPEN,kernel)
cv2.imshow('open_sun',open_sun)
cv2.waitKey(0)
# #顶帽
tophat = cv2.morphologyEx(sun,cv2.MORPH_TOPHAT,kernel)
cv2.imshow('TOPHAT',tophat)
cv2.waitKey(0)
# #闭运算
close_sun=cv2.morphologyEx(sun,cv2.MORPH_CLOSE,kernel)
cv2.imshow('close_sun',close_sun)
cv2.waitKey(0)
# #黑帽
blackhat = cv2.morphologyEx(sun,cv2.MORPH_BLACKHAT,kernel)
cv2.imshow('BLACKHAT',blackhat)
cv2.waitKey(0)

四、总结
本文从基础的图像阈值处理出发,系统地讲解了 OpenCV 中的核心图像处理技术。首先详细介绍了二值化阈值处理(thresholding)的5种常用方法,包括固定阈值法、自适应阈值法等,并通过实际代码示例展示了不同阈值对图像处理效果的影响。
在图像平滑部分,重点讲解了四种常用滤波器:
- 均值滤波(blur) - 通过邻域像素平均值实现平滑
- 高斯滤波(GaussianBlur) - 采用高斯加权平均进行平滑
- 中值滤波(medianBlur) - 取邻域像素中值来消除噪声
- 方框滤波(boxFilter) - 基于归一化或非归一化的邻域像素求和
形态学操作章节深入解析了:
- 膨胀(dilate)和腐蚀(erode)的基本原理及结构元素的选择
- 开运算(morphologyEx+MORPH_OPEN)和闭运算(morphologyEx+MORPH_CLOSE)的实际应用场景
- 形态学梯度(morphologyEx+MORPH_GRADIENT)在边缘检测中的应用
- 顶帽(morphologyEx+MORPH_TOPHAT)和黑帽(morphologyEx+MORPH_BLACKHAT)变换在特定场景下的使用技巧
每个技术点都配有对应的OpenCV函数调用示例和参数说明,并展示了不同参数设置下的处理效果对比图,帮助读者直观理解各种图像处理技术的适用场景和参数调节方法。