OpenCV 图像处理实战(上):阈值、平滑滤波与形态学操作从原理到代码

目录

一、阈值处理:像素级的二值化分割

[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))

5.滤波选型总结

[三、图像形态学操作:像素的 "变形术"](#三、图像形态学操作:像素的 “变形术”)

[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种常用方法,包括固定阈值法、自适应阈值法等,并通过实际代码示例展示了不同阈值对图像处理效果的影响。

在图像平滑部分,重点讲解了四种常用滤波器:

  1. 均值滤波(blur) - 通过邻域像素平均值实现平滑
  2. 高斯滤波(GaussianBlur) - 采用高斯加权平均进行平滑
  3. 中值滤波(medianBlur) - 取邻域像素中值来消除噪声
  4. 方框滤波(boxFilter) - 基于归一化或非归一化的邻域像素求和

形态学操作章节深入解析了:

  1. 膨胀(dilate)和腐蚀(erode)的基本原理及结构元素的选择
  2. 开运算(morphologyEx+MORPH_OPEN)和闭运算(morphologyEx+MORPH_CLOSE)的实际应用场景
  3. 形态学梯度(morphologyEx+MORPH_GRADIENT)在边缘检测中的应用
  4. 顶帽(morphologyEx+MORPH_TOPHAT)和黑帽(morphologyEx+MORPH_BLACKHAT)变换在特定场景下的使用技巧

每个技术点都配有对应的OpenCV函数调用示例和参数说明,并展示了不同参数设置下的处理效果对比图,帮助读者直观理解各种图像处理技术的适用场景和参数调节方法。

相关推荐
啦啦啦_99991 小时前
9. AI面试题之 功能代码实现
java·人工智能
Saniffer_SH1 小时前
【高清视频】4小时带你了解Saniffer公司针对PCIe Gen6测试的最新白皮书15.X
网络·人工智能·驱动开发·嵌入式硬件·测试工具·计算机外设·压力测试
EnCi Zheng2 小时前
11a. 阿里云大模型API调用基础
人工智能·python·阿里云·云计算
Lunar*2 小时前
用 Codex 在 WSL 里安装并配置 Claude Code:一次真实的 AI 代操作记录
人工智能
GEO_Huang2 小时前
想要排名稳?数谷 GEO 优化助力企业品牌升级
大数据·人工智能·百度·aigc·rpa·geo
说实话起个名字真难啊2 小时前
windows 安装openclaw的优势
人工智能·ai·openclaw
IT观测2 小时前
国内GPU算力服务哪家好——企业AI发展的核心支撑分析
人工智能·gpu算力
沸点小助手2 小时前
最近沉迷养龙虾Openclaw,决定让龙虾1号成为我的设计助理 | 掘金沸点周报3.13
人工智能
ComPDFKit2 小时前
法律文件自动化工具推荐:来自用户的真实口碑测评
人工智能