OpenCV计算机视觉实战(8)——图像滤波详解

news2025/7/21 0:30:09

OpenCV计算机视觉实战(8)——图像滤波详解

    • 0. 前言
    • 1. 线性滤波
      • 1.1 均值滤波
      • 1.2 高斯滤波
      • 1.3 拉普拉斯滤波
      • 1.4 Sobel 滤波
    • 2. 非线性滤波
    • 3. 自定义卷积核
    • 小结
    • 系列链接

0. 前言

在本文中,我们将深入探索线性与非线性滤波的算法原理、性能优化及实战技巧,从最基础的均值与高斯滤波,到中值与双边滤波,最后介绍如何灵活运用自定义卷积核。

1. 线性滤波

在图像处理领域,线性滤波是一种常见的图像平滑和增强方法,通过对图像进行局部加权平均,从而达到去噪、平滑、边缘检测等目的。它通过在图像的每个像素周围应用一个滤波器(通常称为卷积核),将邻域像素的加权和作为目标像素的输出。
图像中的每个像素值 I ( x , y ) I(x,y) I(x,y) 都会被周围邻域的像素值加权平均后进行更新。假设有一个大小为 m × n m×n m×n 的滤波器(卷积核) H H H,它作用在输入图像的每个像素上。滤波过程可以表示为:
I ′ ( x , y ) = ∑ i = − k k ∑ ​ j = − l l ​ H ( i , j ) ⋅ I ( x + i , y + j ) I'(x,y)=\sum_{i=−k}^k∑_{​j=−l}^l​H(i,j)⋅I(x+i,y+j) I(x,y)=i=kkj=llH(i,j)I(x+i,y+j)
其中:

  • I ′ ( x , y ) I'(x,y) I(x,y) 是经过滤波后的图像像素值
  • I ( x + i , y + j ) I(x+i,y+j) I(x+i,y+j) 是原始图像的邻域像素值。
  • H ( i , j ) H(i,j) H(i,j) 是滤波器的权重值(通常是对称且以中心为最高权重)
  • k k k l l l 是滤波器的半宽度

1.1 均值滤波

均值滤波是最简单的线性滤波方法,通过计算每个像素的邻域平均值来平滑图像,能有效抑制随机噪声。滤波器通常是一个全 1 的矩阵,大小为 m × n m×n m×n。例如,对于一个 3 × 3 3×3 3×3 的滤波器:
H = 1 9 [ 1 1 1 1 1 1 1 1 1 ] H= \frac 1 9\begin{bmatrix} 1 & 1 &1 \\ 1 & 1 &1 \\1 & 1 &1\end{bmatrix} \quad H=91 111111111
每个像素的新值是它周围 8 个邻域像素和当前像素的平均值。

1.2 高斯滤波

高斯滤波器采用高斯函数作为权重对邻域像素加权平均,中心像素权重最高,远离中心的权重逐渐降低。相比于均值滤波,,其在频域上具有更好的低通特性(快速衰减高频),能够在平滑噪声的同时较好保留图像轮廓信息。OpenCV 在内部对高斯滤波采用了分离卷积优化,将二维卷积拆解为两个一维卷积,减小算法复杂度至 O ( n ) O(n) O(n) 级别,大幅提升大核尺寸时的性能。

例如,对于一个 3 × 3 3×3 3×3 的高斯滤波器:
H = 1 16 [ 1 2 1 2 4 2 1 2 1 ] H= \frac 1 {16}\begin{bmatrix} 1 & 2 &1 \\ 2 & 4 &2 \\1 & 2 &1\end{bmatrix} \quad H=161 121242121
该矩阵的元素是基于高斯分布计算的。核大小 (ksize) 与标准差 (sigma) 的选择直接影响滤波效果:较大的核或 sigma 会增强去噪效果,但也会丢失更多细节;工程中通常结合图像分辨率和噪声强度,在 3×3~7×7 之间调优
接下来,分别调用 cv2.blurcv2.GaussianBlur,通过调整 ksizesigmaX 观察平滑与细节保留的差异:

import cv2

img = cv2.imread('1.jpeg')

# 均值滤波
mean_blur = cv2.blur(img, ksize=(7, 7))

# 高斯滤波
gauss_blur = cv2.GaussianBlur(img, ksize=(7, 7), sigmaX=1.5)

cv2.imshow('Original', img)
cv2.imshow('Mean Blur', mean_blur)
cv2.imshow('Gaussian Blur', gauss_blur)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite('mean_blur.jpg', mean_blur)
cv2.imwrite('gauss_blur.jpg', gauss_blur)

输出结果

关键代码解析:

  • cv2.blur(src, ksize):均值滤波,对每个像素周围 ksize 窗口内取均值,简单快速但边缘模糊
  • cv2.GaussianBlur(src, ksize, sigmaX):高斯滤波,ksize 必须为奇数,sigmaX 控制高斯分布宽度,可设 0OpenCV 自行计算
  • 在边界处理 (borderType) 上,OpenCV 支持多种模式(如 BORDER_REPLICATE, BORDER_REFLECT 等),可根据噪声类型与目标应用选择最优策略,避免边缘伪影

1.3 拉普拉斯滤波

拉普拉斯滤波用于边缘检测,它通过强调图像的高频成分来突出边缘。通常使用类似于下列的滤波器:
H = [ 0 − 1 0 − 1 4 − 1 0 − 1 0 ] H= \begin{bmatrix} 0 & -1 &0 \\ -1 & 4 &-1 \\0 & -1 &0\end{bmatrix} \quad H= 010141010
拉普拉斯滤波可以帮助突出图像中的边缘细节。

1.4 Sobel 滤波

Sobel 滤波器是一种用于边缘检测的滤波器,通过计算图像中水平方向和垂直方向的梯度来检测边缘。Sobel 滤波器有两个常见版本,一个用于检测水平方向的边缘,另一个用于检测垂直方向的边缘。
水平边缘检测:
H x = [ − 1 0 1 − 2 0 2 − 1 0 1 ] H_x= \begin{bmatrix} -1 & 0 &1 \\ -2 & 0 &2 \\-1 & 0 &1\end{bmatrix} \quad Hx= 121000121
垂直边缘检测:
H y = [ − 1 − 2 − 1 0 0 0 1 2 1 ] H_y= \begin{bmatrix} -1 & -2 &-1 \\0 & 0 &0 \\1 & 2 &1\end{bmatrix} \quad Hy= 101202101

2. 非线性滤波

非线性滤波在图像处理中的应用非常重要,尤其是在去噪、边缘检测以及增强图像细节方面。与线性滤波不同,非线性滤波不会简单地对邻域像素进行加权平均,而是通过其他方式来选择或修改像素值,这使得非线性滤波能够有效地处理一些特定的问题,比如去除椒盐噪声、保留边缘等。常见的非线性滤波方法包括:

  • 中值滤波:是最常见的非线性滤波方法,主要通过将每个像素的值替换为其邻域内所有像素值的中位数来进行图像去噪

    • 应用:特别适合去除椒盐噪声,中值滤波能够有效去除噪声的同时,保持图像的边缘信息
  • 双边滤波:是一种结合空间距离和像素值相似度的非线性滤波方法,它不仅考虑像素的空间位置,还考虑像素的灰度差异,从而保留边缘信息,同时平滑图像

    • 应用:用于去噪的同时保留图像的边缘和细节,特别是在面部图像处理和医学图像处理中使用较多
    • 主要参数包括:d (邻域直径)、sigmaColor (灰度空间标准差)与 sigmaSpace (坐标空间标准差);合理配置可在去噪和边缘保留之间取得平衡
  • 自适应滤波:根据图像局部区域的统计特性动态调整滤波器的参数,自适应滤波器能够在不同的图像区域使用不同的滤波强度。

    • 应用:用于处理具有不均匀噪声的图像
  • 最大值和最小值滤波:

    • 最大值滤波:将每个像素的值替换为邻域内的最大值,通常用于增强图像中明亮的部分
    • 最小值滤波:将每个像素的值替换为邻域内的最小值,通常用于保留阴影部分的细节
    • 应用:适用于特定区域的增强,如边缘检测或提取暗部/亮部特征

接下来,分别调用 cv2.medianBlur(ksize=5)cv2.bilateralFilter(d=9, sigmaColor=75, sigmaSpace=75) 观察对椒盐噪声和细节的不同处理效果:

import cv2

img = cv2.imread('1.jpeg')

# 中值滤波
median = cv2.medianBlur(img, ksize=5)

# 双边滤波
bilateral = cv2.bilateralFilter(img, d=9, sigmaColor=75, sigmaSpace=75)

cv2.imshow('Median Blur', median)
cv2.imshow('Bilateral Filter', bilateral)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite('median_blur.jpg', median)
cv2.imwrite('bilateral.jpg', bilateral)

输出结果
关键代码解析:

  • cv2.medianBlur(src, ksize):对 ksize×ksize 邻域内像素排序并取中值,ksize 必须为奇数
  • cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace):对每个像素计算空间和灰度两个高斯权重加权平均,d≤0 时由 sigmaSpace 推断

3. 自定义卷积核

使用 cv2.filter2 能够自定义任意卷积核,可实现锐化、边缘检测、浮雕、模糊等任意线性滤波效果。
自定义内核时需关注:归一化(核元素之和 ≠1 时可能导致图像亮度漂移)、锚点( anchor 决定核中心对应位置)、深度 (ddepth 决定输出图像的数据类型)、边界模式 (borderType 控制边缘像素如何卷积)。
常用锐化核示例:
H = [ 0 − 1 0 − 1 5 − 1 0 − 1 0 ] H= \begin{bmatrix} 0 & -1 &0 \\-1 & 5 &-1 \\ 0 & -1 &0\end{bmatrix} \quad H= 010151010
可在保留整体亮度的同时强化细节;Sobel 核则用于水平边缘检测,配合 cv2.convertScaleAbs 处理负值。
接下来,定义 2 种核,包括锐化核、Sobel X 核,并分别调用 cv2.filter2D

import cv2
import numpy as np

img = cv2.imread('1.jpeg')

# 定义卷积核
sharpen = np.array([[0, -1,  0],
                    [-1, 5, -1],
                    [0, -1,  0]], dtype=np.float32)
sobel_x = np.array([[-1, 0, 1],
                    [-2, 0, 2],
                    [-1, 0, 1]], dtype=np.float32)

# 应用 filter2D
out_sharpen  = cv2.filter2D(img, ddepth=-1, kernel=sharpen)
out_sobel    = cv2.filter2D(img, ddepth=cv2.CV_16S, kernel=sobel_x)
out_sobel    = cv2.convertScaleAbs(out_sobel)  # 转回 8-bit

cv2.imshow('Sharpen', out_sharpen)
cv2.imshow('Sobel X', out_sobel)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite('out_sharpen.jpg', out_sharpen)
cv2.imwrite('out_sobel.jpg', out_sobel)

输出结果
关键代码解析:

  • cv2.filter2D(src, ddepth, kernel, anchor=None, delta=0, borderType=cv2.BORDER_DEFAULT):对 src 与自定义 kernel 做二维卷积,ddepth=-1 表示输出与输入同类型;delta 可用于调整偏移
  • cv2.convertScaleAbs(src, alpha=1, beta=0):将带符号卷积结果(如 Sobel )映射到无符号 8-bit,并可通过 alphabeta 调整对比度与亮度

小结

在本节中,我们从线性滤波(均值/高斯)的原理与参数调优入手,紧接着以非线性滤波(中值/双边)为重点,探讨了它们在各自噪声模型下的卓越表现与局限,最后,通过自定义卷积核实践,介绍如何使用 cv2.filter2D 实现锐化、边缘检测等多样效果。

系列链接

OpenCV计算机视觉实战(1)——计算机视觉简介
OpenCV计算机视觉实战(2)——环境搭建与OpenCV简介
OpenCV计算机视觉实战(3)——计算机图像处理基础
OpenCV计算机视觉实战(4)——计算机视觉核心技术全解析
OpenCV计算机视觉实战(5)——图像基础操作全解析
OpenCV计算机视觉实战(6)——经典计算机视觉算法
OpenCV计算机视觉实战(7)——色彩空间详解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2391986.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自动化安全脚本学习

1.目录扫描器 目标:使用python编写一个自动化目录扫描工具,实现简单信息收集,判断目标网站是否存在常见路径。 import requests #用于发HTTP请求 from concurrent.futures import ThreadPoolExecutor #实现多线程扫描# 扫描目标 target h…

传输层协议TCP(上)

上一篇https://blog.csdn.net/Small_entreprene/article/details/148143494?fromshareblogdetail&sharetypeblogdetail&sharerId148143494&sharereferPC&sharesourceSmall_entreprene&sharefromfrom_link 上文学习了传输层的协议之一UDP,接下来…

Windows下安装并使用kubectl查看K8S日志

【1】安装kubectl 官网文档:https://kubernetes.io/zh-cn/docs/tasks/tools/install-kubectl-windows/ 下载后得到 kubectl.exe,放到一个目录下,然后配置环境变量。 此时CMD 进入DOS命令窗口 kubectl version【2】配置config文件 其实就是…

Android studio进阶开发(六)--如何用真机通过okhttp连接服务器

我们学过了如何通过okhttp查询网络上已经发布的网页,但我们还需要在做全栈时保证前后端能够交互。 前要课程 okhttp的使用 真机端口连接 安全认证 由于http的安全性较差,在没有安全协议的情况下,使用自己的后端连接会报错,所以…

WeakAuras Lua Script [ICC BOSS 11 - Sindragosa]

WeakAuras Lua Script [ICC BOSS 11 - Sindragosa] 冰冠堡垒Icecrown Citadel 冰龙 辛达苟萨(寒冰信标插件) 左 (绿,黄) 中(蓝,紫) 右(白,橙) lua script&…

电脑开机后出现bootmgr is conmpressed原因及解决方法

最近有网友问我为什么我电脑开机后出现BOOTMGR is compressed,这个提示意思是:意思是启动管理器被压缩了,即使重启也无法正常进入系统。原因有很多,大部分是引导出现问题,或选错了启动硬盘所导致的,下面我们来详细分析…

vite配置一个css插件

vite.config.js的plugins执行函数 该例子只是替换一些css,具体内容不重要,主要看形参的运用 // vite-plugin-css.js export default function cssPlugin() {return {name: vite-plugin-css-post, // 插件的名字,Vite 插件必须有名字enforce: post, // 设定插件执…

React+Taro 微信小程序做一个页面,背景图需贴手机屏幕最上边覆盖展示

话不多说 直接上图 第一步 import { getSystemInfoSync } from tarojs/taro;第二步 render() {const cardBanner getImageUrlByGlobal(member-merge-bg.png);const { safeArea, statusBarHeight } getSystemInfoSync();const NAV_BAR_HEIGHT 44;const navBarHeight NAV…

Spring框架学习day4--Spring集成Mybatis(IOC)

Spring集成Mybatis1.添加jar包(pom.xml)2.配置sqlSessionFactiory(spring.xml)3.再service类中注入Dao代理接口4.测试类5文件结构 Spring集成Mybatis Spring集成Mybatis其核心是将SqlSessionFactory交由Spring管理,并由 Spring管理…

【C++ Qt】容器类(GroupBox、TabWidget)内附思维导图 通俗易懂

每日激励:“不设限和自我肯定的心态:I can do all things。 — Stephen Curry” ✍️绪论​: 本章主要介绍了 Qt 中 QGroupBox 与 QTabWidget 控件。QGroupBox 是带标题的分组框,能容纳其他控件,有标题、对齐方式、是否…

SOC-ESP32S3部分:18-串口

飞书文档https://x509p6c8to.feishu.cn/wiki/NqrMw6X8Si6sSqkyPbxcFRxGnid UART全称是通用异步接收器/发送器,ESP32-S3 芯片有 3 个 UART 控制器。每个 UART 控制器可以独立配置波特率、数据位长度、位顺序、停止位位数、奇偶校验位等参数。 串口文档参考&#xf…

https下git拉取gitlab仓库源码

git init 创建仓库 参考下面创建公私秘钥对 注意不要以root用户身份创建公私钥,确保保存在/home/username GitLab配置ssh key - 阿豪聊干货 - 博客园 Your identification has been saved in /home/xxx/.ssh/id_ed25519 Your public key has been saved in /ho…

距离计算范围查找距离排序

一 使用场景 目前基于某个位置查附近的人,附近的商家等等,查出来的结果添加距离,或者查附近多大范围内的人或者商家,然后按距离排序已经是IT界一个很通用的功能了。 二 距离计算搜索(百万点集以下) 2.1 球的定义 2.2 两点之…

PS linux 基础篇1-AXI_DMA

系列文章目录 文章目录 系列文章目录前言一、AXI DMA ip核二、BD工程三、PS linux工程1.使用开源的xilinx_axidma-master工程验证驱动2.按照其他的开源进行就行,没什么写的了 前言 PL与PS之间快速的接口,本文为LOOP回环测试 一、AXI DMA ip核 MM2S mem…

AI大模型学习三十、ubuntu安装comfyui,安装插件,修改返回405 bug,值得一看喔

一、说明 ComfyUI是一个开源的、基于节点的Web应用。它允许用户根据一系列文本提示(Prompt)生成图像。 ComfyUI使用扩散模型作为基础模型,并结合 ControlNet、Lora和LCM低阶自适应等模型,每个工具都由程序中的一个节点表示 二、开…

Collection集合遍历的三种方法

1.foreach循环遍历 格式&#xff1a;for&#xff08;元素的数据类型 变量名&#xff1a;数组或集合&#xff09;{ } 2.使用迭代器遍历 方法名称&#xff1a;Iterator<E> iterator&#xff08;&#xff09; 说明&#xff1a;返回集合中的迭代器对象&#xff0c;该迭代…

Taro on Harmony C-API 版本正式开源

Taro 是由京东发起并维护的开放式跨端跨框架解决方案&#xff0c;支持以 Web 的开发范式来实现小程序、H5、原生 APP 的跨端统一开发&#xff0c;从 18 年开源至今&#xff0c;在 GitHub 已累计获得 36,000 Stars。 Taro x 纯血鸿蒙 在过去的一年中&#xff0c;Taro 经历了显…

知识隔离的视觉-语言-动作模型:训练更快、运行更快、泛化更好

25年5月来自PI的论文“Knowledge Insulating Vision-Language-Action Models: Train Fast, Run Fast, Generalize Better”。 视觉-语言-动作 (VLA) 模型通过将端到端学习与来自网络规模视觉-语言模型 (VLM) 训练的语义知识迁移相结合&#xff0c;为机器人等物理系统训练控制策…

[ARM][架构] 02.AArch32 程序状态

目录 参考资料 1.程序状态 - PSTATE 2.用户模式的 PSTATE 信息 2.1.状态标志 2.2.溢出/饱和标志 2.3.大于等于标志 2.4.指令集状态 2.5.IT 块状态 2.6.端序控制 2.7.指令执行时间控制 3.用户模式访问 PSTATE - APSR 寄存器 4.系统模式的 PSTATE 信息 4.1.状态标志…

React---day4

3、React脚手架 生成的脚手架的目录结构 什么是PWA PWA全称Progressive Web App&#xff0c;即渐进式WEB应用&#xff1b;一个 PWA 应用首先是一个网页, 可以通过 Web 技术编写出一个网页应用&#xff1b;随后添加上 App Manifest 和 Service Worker 来实现 PWA 的安装和离线…