OpenCV 笔记(35):频域低通滤波——高斯低通滤波器、巴特沃斯低通滤波器

1.  高斯低通滤波器

高斯低通滤波器(GLPF)是一种具有平滑频域特性、较慢衰减速度和良好截止频率附近衰减效果的滤波器。在图像处理中有着广泛的应用。

高斯低通滤波器的传播函数有如下的形式:

其中,D(u,v) 表示中心点到频域中心的距离,即 ,

是关于中心分离度的测度。令 ,则:

其中, 是截止频率,控制着滤波器的截止范围。

当 时,高斯低通滤波器下降到它最大值的 0.607 处。

值越大,允许通过的频率越高,滤波效果越弱; 值越小,允许通过的频率越低,滤波效果越强。

高斯低通滤波器具有以下特性:

  • 平滑的频率响应: GLPF 的频率响应曲线呈高斯形状,在截止频率附近平滑衰减,在截止频率以上迅速衰减至零。这种平滑的频率响应使得 GLPF 能够有效地去除高频噪声而又不失真低频信号。

  • 良好的边缘保持能力: 由于 GLPF 的频率响应在截止频率附近比较平滑,因此它不会对图像的边缘造成明显的振铃效应,从而能够较好地保持图像的边缘细节。

  • 可控的截止频率: GLPF 的截止频率可以通过调整高斯函数的方差来控制,从而可以根据不同的应用需求来选择合适的截止频率。

下面的例子,展示了高斯低通滤波器的实现代码

#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <random>using namespace std;
using namespace cv;void addSaltNoise(Mat &src, int num, Mat &dst)
{dst = src.clone();// 随机数产生器std::random_device rd; //种子std::mt19937 gen(rd()); // 随机数引擎auto rows = src.rows; // 行数auto cols = src.cols * src.channels();for (int i = 0; i < num; i++){auto row = static_cast<int>(gen() % rows);auto col = static_cast<int>(gen() % cols);auto p = dst.ptr<uchar>(row);p[col++] = 255;p[col++] = 255;p[col] = 255;}
}// 高斯低通滤波核函数
cv::Mat gaussian_low_pass_kernel(cv::Mat scr, float sigma)
{cv::Mat gaussianBlur(scr.size(), CV_32FC1);float d0 = sigma;for (int i = 0; i < scr.rows; i++) {for (int j = 0; j < scr.cols; j++) {float d = pow(float(i - scr.rows / 2), 2) + pow(float(j - scr.cols / 2), 2);//分子,计算pow必须为float型gaussianBlur.at<float>(i, j) = expf(-d / (2 * d0*d0));}}return gaussianBlur;
}// fft 变换后进行频谱中心化
void fftshift(cv::Mat &plane0, cv::Mat &plane1)
{int cx = plane0.cols / 2;int cy = plane0.rows / 2;cv::Mat q0_r(plane0, cv::Rect(0, 0, cx, cy));  // 元素坐标表示为(cx, cy)cv::Mat q1_r(plane0, cv::Rect(cx, 0, cx, cy));cv::Mat q2_r(plane0, cv::Rect(0, cy, cx, cy));cv::Mat q3_r(plane0, cv::Rect(cx, cy, cx, cy));cv::Mat temp;q0_r.copyTo(temp);  //左上与右下交换位置(实部)q3_r.copyTo(q0_r);temp.copyTo(q3_r);q1_r.copyTo(temp);  //右上与左下交换位置(实部)q2_r.copyTo(q1_r);temp.copyTo(q2_r);cv::Mat q0_i(plane1, cv::Rect(0, 0, cx, cy));  //元素坐标(cx,cy)cv::Mat q1_i(plane1, cv::Rect(cx, 0, cx, cy));cv::Mat q2_i(plane1, cv::Rect(0, cy, cx, cy));cv::Mat q3_i(plane1, cv::Rect(cx, cy, cx, cy));q0_i.copyTo(temp);  //左上与右下交换位置(虚部)q3_i.copyTo(q0_i);temp.copyTo(q3_i);q1_i.copyTo(temp);  //右上与左下交换位置(虚部)q2_i.copyTo(q1_i);temp.copyTo(q2_i);
}// 频率域滤波
cv::Mat frequency_filter(cv::Mat &src, cv::Mat &blur)
{Mat mask = src == src;src.setTo(0.0f, ~mask);// 创建一个双通道矩阵 planes,用来储存复数的实部与虚部Mat planes[] = {src.clone(), cv::Mat::zeros(src.size() , CV_32FC1) };Mat complexI;merge(planes, 2, complexI); // 合并通道 (把两个矩阵合并为一个2通道的Mat类容器)dft(complexI, complexI); // 进行傅立叶变换,结果保存在自身// 分离通道(数组分离)cv::split(complexI, planes);// 频谱中心化fftshift(planes[0], planes[1]);//  H(u, v) * F(u, v)Mat blur_r, blur_i, dst;multiply(planes[0], blur, blur_r);  // 滤波(实部与滤波器模板对应元素相乘)multiply(planes[1], blur, blur_i);  // 滤波(虚部与滤波器模板对应元素相乘)Mat planes1[] = {blur_r, blur_i };// 频谱中心化fftshift(planes1[0], planes1[1]);merge(planes1, 2, dst); // 实部与虚部合并// 傅里叶逆变换idft(dst, dst);       // idft 结果也为复数dst = dst / dst.rows / dst.cols;split(dst, planes1);//分离通道,主要获取通道return planes1[0];
}int main()
{Mat src = imread(".../girl.jpg");imshow("src", src);Mat gray;cvtColor(src, gray, COLOR_BGR2GRAY);imshow("gray", gray);addSaltNoise(gray,100000,gray);imshow("add salt", gray);// 扩充边界int w = cv::getOptimalDFTSize(src.cols); // 获取DFT变换的最佳宽度int h = cv::getOptimalDFTSize(src.rows); // 获取DFT变换的最佳高度cv::Mat padded;// 常量法扩充图像边界,常量 = 0cv::copyMakeBorder(gray, padded, 0, h - src.rows, 0, w - src.cols, cv::BORDER_CONSTANT, cv::Scalar::all(0));padded.convertTo(padded, CV_32FC1);float d0 = 30.0f;cv::Mat gaussian_kernel = gaussian_low_pass_kernel(padded, d0);cv::Mat dst = frequency_filter(padded, gaussian_kernel);convertScaleAbs(dst, dst);imshow("dst", dst);waitKey(0);return 0;
}
35443a75b3ba6df934d72fa92b2d084d.jpeg
灰度图像vs椒盐噪声vs高斯低通滤波的效果.png

2. 巴特沃斯低通滤波器

巴特沃斯低通滤波器(BLPF)是一种经典的滤波器类型,因其在通频带内的最大平坦幅度响应而得名,也称为最大平坦滤波器。其主要特点是通频带内的频率响应曲线最大限度平坦,没有起伏,而在阻频带则逐渐下降为零。

巴特沃斯低通滤波器具有以下特性:

  • 在截止频率 以下的频率分量,其幅度基本保持不变,即滤波器对这些频率分量没有衰减;

  • 在截止频率 以上的频率分量,其幅度随着频率的增加而迅速衰减,衰减速度由滤波器阶数 n 决定。阶数越高,衰减速度越快。

  • 频域特性曲线平滑,没有振铃效应。

值越大,允许通过的频率越高,滤波效果越弱,图像越清晰; 值越小,允许通过的频率越低,滤波效果越强,图像越模糊。

巴特沃斯低通滤波器的阶数的选择取决于具体的应用需求。

  • 如果需要快速去除高频噪声,应选择较高的滤波器阶数。 较高的滤波器阶数可以使滤波器对高频分量的衰减速度更快,从而更有效地去除高频噪声。

  • 如果需要保留更多图像细节,应选择较低的滤波器阶数。 较低的滤波器阶数可以使滤波器对低频分量的衰减速度更慢,从而保留更多图像细节。

下面的例子,展示了巴特沃斯低通滤波器的实现代码

#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <random>using namespace std;
using namespace cv;void addSaltNoise(Mat &src, int num, Mat &dst)
{dst = src.clone();// 随机数产生器std::random_device rd; //种子std::mt19937 gen(rd()); // 随机数引擎auto rows = src.rows; // 行数auto cols = src.cols * src.channels();for (int i = 0; i < num; i++){auto row = static_cast<int>(gen() % rows);auto col = static_cast<int>(gen() % cols);auto p = dst.ptr<uchar>(row);p[col++] = 255;p[col++] = 255;p[col] = 255;}
}// 巴特沃斯低通滤波核函数
cv::Mat butterworth_low_kernel(cv::Mat &scr, float sigma, int n)
{cv::Mat butterworth_low_pass(scr.size(), CV_32FC1);float D0 = sigma;for (int i = 0; i < scr.rows; i++) {for (int j = 0; j < scr.cols; j++) {float d = sqrt(pow(float(i - scr.rows / 2), 2) + pow(float(j - scr.cols / 2), 2));butterworth_low_pass.at<float>(i, j) = 1.0f / (1.0f + pow(d / D0, 2 * n));}}return butterworth_low_pass;
}// fft 变换后进行频谱中心化
void fftshift(cv::Mat &plane0, cv::Mat &plane1)
{int cx = plane0.cols / 2;int cy = plane0.rows / 2;cv::Mat q0_r(plane0, cv::Rect(0, 0, cx, cy));  // 元素坐标表示为(cx, cy)cv::Mat q1_r(plane0, cv::Rect(cx, 0, cx, cy));cv::Mat q2_r(plane0, cv::Rect(0, cy, cx, cy));cv::Mat q3_r(plane0, cv::Rect(cx, cy, cx, cy));cv::Mat temp;q0_r.copyTo(temp);  //左上与右下交换位置(实部)q3_r.copyTo(q0_r);temp.copyTo(q3_r);q1_r.copyTo(temp);  //右上与左下交换位置(实部)q2_r.copyTo(q1_r);temp.copyTo(q2_r);cv::Mat q0_i(plane1, cv::Rect(0, 0, cx, cy));  //元素坐标(cx,cy)cv::Mat q1_i(plane1, cv::Rect(cx, 0, cx, cy));cv::Mat q2_i(plane1, cv::Rect(0, cy, cx, cy));cv::Mat q3_i(plane1, cv::Rect(cx, cy, cx, cy));q0_i.copyTo(temp);  //左上与右下交换位置(虚部)q3_i.copyTo(q0_i);temp.copyTo(q3_i);q1_i.copyTo(temp);  //右上与左下交换位置(虚部)q2_i.copyTo(q1_i);temp.copyTo(q2_i);
}// 频率域滤波
cv::Mat frequency_filter(cv::Mat &src, cv::Mat &blur)
{Mat mask = src == src;src.setTo(0.0f, ~mask);// 创建一个双通道矩阵 planes,用来储存复数的实部与虚部Mat planes[] = {src.clone(), cv::Mat::zeros(src.size() , CV_32FC1) };Mat complexI;merge(planes, 2, complexI); // 合并通道 (把两个矩阵合并为一个2通道的Mat类容器)dft(complexI, complexI); // 进行傅立叶变换,结果保存在自身// 分离通道(数组分离)cv::split(complexI, planes);// 频谱中心化fftshift(planes[0], planes[1]);//  H(u, v) * F(u, v)Mat blur_r, blur_i, dst;multiply(planes[0], blur, blur_r);  // 滤波(实部与滤波器模板对应元素相乘)multiply(planes[1], blur, blur_i);  // 滤波(虚部与滤波器模板对应元素相乘)Mat planes1[] = {blur_r, blur_i };// 频谱中心化fftshift(planes1[0], planes1[1]);merge(planes1, 2, dst); // 实部与虚部合并// 傅里叶逆变换idft(dst, dst);       // idft 结果也为复数dst = dst / dst.rows / dst.cols;split(dst, planes1);//分离通道,主要获取通道return planes1[0];
}int main()
{Mat src = imread(".../girl.jpg");imshow("src", src);Mat gray;cvtColor(src, gray, COLOR_BGR2GRAY);imshow("gray", gray);addSaltNoise(gray,100000,gray);imshow("add salt", gray);// 扩充边界int w = cv::getOptimalDFTSize(src.cols); // 获取DFT变换的最佳宽度int h = cv::getOptimalDFTSize(src.rows); // 获取DFT变换的最佳高度cv::Mat padded;// 常量法扩充图像边界,常量 = 0cv::copyMakeBorder(gray, padded, 0, h - src.rows, 0, w - src.cols, cv::BORDER_CONSTANT, cv::Scalar::all(0));padded.convertTo(padded, CV_32FC1);float d0 = 160.0f;int n = 2;cv::Mat kernel = butterworth_low_kernel(padded, d0, n);cv::Mat dst = frequency_filter(padded, kernel);convertScaleAbs(dst, dst);imshow("dst", dst);waitKey(0);return 0;
}
4378a5336df8c1bc2558d5c6e178b1d4.jpeg
灰度图像vs椒盐噪声vs巴特沃斯低通滤波的效果.png

巴特沃斯低通滤波器介于理想低通滤波器和高斯低通滤波器之间,阶数越高,其滤波特性越接近理想低通滤波器;阶数越低,其滤波特性越接近高斯低通滤波器。巴特沃斯低通滤波器可以根据需要选择不同的阶数来达到不同的滤波效果。

理想低通滤波器、高斯低通滤波器、巴特沃斯低通滤波器三者的区别:

滤波器频域特性优点缺点衰减速度截止频率附近衰减实现难度应用
理想低通滤波器矩形最快的衰减速度难以实现,存在振铃效应最快较少使用
高斯低通滤波器高斯函数没有振铃效应截止频率附近的衰减效果较弱平缓良好图像去噪、图像模糊
巴特沃斯低通滤波器平滑的衰减曲线没有振铃效应,截止频率附近的衰减效果好
中等更好中等图像去噪、图像模糊、边缘检测

3. 总结

高斯低通滤波器(GLPF)和巴特沃斯低通滤波器(BLPF)都是常用的数字图像处理滤波器,用于平滑图像、去除噪声。两种滤波器都具有平滑的频域特性和良好的截止频率附近衰减效果。

高斯低通滤波器的频域特性呈高斯函数形状,衰减速度平缓,没有振铃效应。巴特沃斯低通滤波的频域特性介于理想低通滤波器和高斯低通滤波器之间,具有平滑的衰减曲线,没有振铃效应,且在截止频率附近的衰减效果比高斯低通滤波器更好。

Java与Android技术栈】公众号

关注 Java/Kotlin 服务端、桌面端 、Android 、机器学习、端侧智能

更多精彩内容请关注:

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

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

相关文章

如何监控 PostgreSQL 中表空间的使用情况并进行合理的管理?

文章目录 如何监控 PostgreSQL 中表空间的使用情况并进行合理的管理 一、引言 在 PostgreSQL 数据库中&#xff0c;表空间&#xff08;Tablespace&#xff09;是用于管理数据库对象存储位置的逻辑存储区域。有效地监控和管理表空间的使用情况对于确保数据库的性能、优化存储资…

(一)、python程序--模拟电脑鼠走迷宫

一、绪论 1、简介 电脑鼠走迷宫是一种比赛&#xff0c;制作实物电脑鼠小车在迷宫找目标点&#xff0c;用时最短者获胜。考验参赛选手软硬件结合的能力。 2、走迷宫模拟软件中已实现功能 1、点击迷宫墙壁可编辑迷宫&#xff0c;并且可保存和加载迷宫形状文件&#xff1b; 2、…

聚观早报 | 蚁天鉴2.0发布;理想汽车推送无图NOA

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 7月8日消息 蚁天鉴2.0发布 理想汽车推送无图NOA 特斯拉推送FSD v12.4.3 iQOO Neo9s Pro配色公布 百川智能AI健康…

#数据结构 链表

单向链表 1. 概念 单向链表 单向循环链表 双向链表 双向循环链表 解决&#xff1a;长度固定的问题&#xff0c;插入和删除麻烦的问题 1、逻辑结构&#xff1a; 线性结构 2、存储结构&#xff1a; 链式存储 链表就是将 结点 用链串起来的线性表&#xff0c;链就是 结点 中的…

Banana Pi BPI-M5 Pro 低调 SBC 采用 Rockchip RK3576 八核 Cortex-A72/A53 AIoT SoC

Banana Pi BPI-M5 Pro&#xff0c;也称为 Armsom Sige5&#xff0c;是一款面向 AIoT 市场的低调单板计算机 (SBC)&#xff0c;由 Rockchip RK3576 八核 Cortex-A72/A53 SoC 驱动&#xff0c;提供Rockchip RK3588和RK3399 SoC 之间的中档产品。 该主板默认配备 16GB LPDDR4X 和…

力扣-双指针1

何为双指针 双指针指向同一数组&#xff0c;然后配合着进行搜索等活动。 滑动窗口的时候很好使用。 167.两数之和Ⅱ-输入有序数组 167. 两数之和 II - 输入有序数组 题目 给你一个下标从 1 开始的整数数组 numbers &#xff0c;该数组已按 非递减顺序排列 &#xff0c;请你从…

【力扣: 15题: 三数之和】

15题: 三数之和 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意: 答案中不可以包含重复的三元组。 …

AI集成工具平台一站式体验,零门槛使用国内外主流大模型

目录 0 写在前面1 AI艺术大师1.1 绘画制图1.2 智能作曲 2 AI科研助理2.1 学术搜索2.2 自动代码 3 AI智能对话3.1 聊天机器人3.2 模型竞技场 4 特别福利 0 写在前面 人工智能大模型浪潮滚滚&#xff0c;正推动着千行百业的数智化进程。随着技术演进&#xff0c;2024年被视为是大…

C++11中新特性介绍-之(二)

11.自动类型推导 (1) auto类型自动推导 auto自动推导变量的类型 auto并不代表某个实际的类型&#xff0c;只是一个类型声明的占位符 auto并不是万能的在任意场景下都能推导&#xff0c;使用auto声明的变量必须进行初始化&#xff0c;以让编译器推导出它的实际类型&#xff0c;…

深入探索 Python 中的数据维数:高维数据处理方法与应用

Python 数据维数 在数据科学和机器学习领域&#xff0c;理解数据的维度是至关重要的。Python作为一种强大而灵活的编程语言&#xff0c;提供了丰富的工具和库来处理各种维度的数据。本文将介绍Python中数据维数的概念&#xff0c;以及如何使用Python库来处理不同维度的数据。 什…

算法思想总结:优先级队列

一、最后一块石头的重量 . - 力扣&#xff08;LeetCode&#xff09; 我们每次都要快速找到前两个最大的石头进行抵消&#xff0c;这个时候用优先级队列&#xff08;建大堆&#xff09;,不断取堆顶元素是最好的&#xff01;每次删除堆顶元素后&#xff0c;可以自动调整&#xf…

爬虫怎么实现抓取的

1.4爬虫工程师常用的库通过图1-3我们了解到&#xff0c;爬虫程序的完整链条包括整理需求、分析目标、发出网络请求、文本解析、数据入库和数据出库。其中与代码紧密相关的有&#xff1a;发出网络请求、文本解析、数据入库和数据出库&#xff0c;接下来我们将学习不同阶段中爬虫…

SOAMANAGER 弹不出浏览器

SOAMANAGER 弹不出浏览器 一、打开SOAMANAGER的其他方法 使用事务码SICF打开SOAMANAGER,执行路径default_host/sap/bc/webdynpro/sap/appl_soap_management 使用SE24对类CL_GUI_HTML_VIEWER中的方法DETACH_URL_IN_BROWSER 打断点 在前台创建一个URL的链接。

数组算法(二):交替子数组计数

1. 官方描述 给你一个二进制数组nums 。如果一个子数组中 不存在 两个 相邻 元素的值 相同 的情况&#xff0c;我们称这样的子数组为 交替子数组 。 返回数组 nums 中交替子数组的数量。 示例 1&#xff1a; 输入&#xff1a; nums [0,1,1,1] 输出&#xff1a; 5 解释&#…

Spring IOC基于XML和注解管理Bean

IoC 是 Inversion of Control 的简写&#xff0c;译为“ 控制反转 ”&#xff0c;它不是一门技术&#xff0c;而是一种设计思想&#xff0c;是一个重要的面向对象编程法则&#xff0c;能够指导我们如何设计出 松耦合、更优良的程序。 Spring 通过 IoC 容器来管理所有 Java 对象…

【Unity】在Unity中制作一个小车游戏

目录 第一步&#xff1a;设置Unity项目 第二步&#xff1a;设置场景 第三步&#xff1a;添加车辆控制脚本 第四步&#xff1a;将脚本附加到车辆上 第五步&#xff1a;运行和测试 第六步&#xff1a;添加更多功能&#xff08;可选&#xff09; 在Unity中制作一个小车游戏…

webGL可用的14种3D文件格式,但要具体问题具体分析。

hello&#xff0c;我威斯数据&#xff0c;你在网上看到的各种炫酷的3d交互效果&#xff0c;背后都必须有三维文件支撑&#xff0c;就好比你网页的时候&#xff0c;得有设计稿源文件一样。WebGL是一种基于OpenGL ES 2.0标准的3D图形库&#xff0c;可以在网页上实现硬件加速的3D图…

MySQL之备份与恢复和MySQL用户工具(一)

备份与恢复 备份脚本化 为备份写一些脚本是标准做法。展示一个示例程序&#xff0c;其中必定有很多辅助内容&#xff0c;这只会增加篇幅&#xff0c;在这里我们更愿意列举一些典型的备份脚本功能&#xff0c;展示一些Perl脚本的代码片段。你可以把这些当作可重用的代码块&…

算法012:将x减到0的最小操作数

将x减到0的最小操作数. - 备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/minimum-operations-to-reduce-x-to-zero/ 这个题使用到的是滑动窗口。 乍一看&#xff0c…

web安全基础名词概念

本节内容根据小迪安全讲解制作 第一天 域名&#xff1a; 1.1什么是域名&#xff1f; 网域名称(英语&#xff1a;Domain Name&#xff0c;简称&#xff1a;Domain)&#xff0c;简称域名、网域&#xff0c;是由一串用点分隔的字符组成的互联网上某一台计算机或计算机组的名称&a…