掘金 人工智能 2024年07月07日
OpenCV 笔记(35):频域低通滤波——高斯低通滤波器、巴特沃斯低通滤波器
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

高斯低通滤波器(GLPF)和巴特沃斯低通滤波器(BLPF)是图像处理中常用的滤波器,它们用于平滑图像、去除噪声。高斯低通滤波器具有平滑的频率响应,能够有效地去除高频噪声,并且能够较好地保持图像的边缘细节。巴特沃斯低通滤波器在通频带内的频率响应曲线最大限度平坦,没有起伏,在阻频带则逐渐下降为零,具有良好的截止频率附近衰减效果。

**高斯低通滤波器** 💫 是一种具有平滑频域特性、较慢衰减速度和良好截止频率附近衰减效果的滤波器。其频率响应曲线呈高斯形状,在截止频率附近平滑衰减,在截止频率以上迅速衰减至零,因此能够有效地去除高频噪声而又不失真低频信号。 💫 高斯低通滤波器具有良好的边缘保持能力,不会对图像的边缘造成明显的振铃效应,能够较好地保持图像的边缘细节。 💫 高斯低通滤波器的截止频率可以通过调整高斯函数的方差来控制,从而可以根据不同的应用需求来选择合适的截止频率。

**巴特沃斯低通滤波器** 💫 是一种经典的滤波器类型,其在通频带内的最大平坦幅度响应而得名,也称为最大平坦滤波器。其主要特点是通频带内的频率响应曲线最大限度平坦,没有起伏,而在阻频带则逐渐下降为零。 💫 巴特沃斯低通滤波器的阶数越高,其滤波特性越接近理想低通滤波器;阶数越低,其滤波特性越接近高斯低通滤波器。 💫 巴特沃斯低通滤波器可以根据需要选择不同的阶数来达到不同的滤波效果,例如,如果需要快速去除高频噪声,应选择较高的滤波器阶数;如果需要保留更多图像细节,应选择较低的滤波器阶数。

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

1. 高斯低通滤波器

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

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

$H(u,v)= e^{-D^2(u,v)/2\sigma^2}$

其中,D(u,v) 表示中心点到频域中心的距离,即 $D(u,v) = \sqrt{[(u-P/2)^2+(v-Q/2)^2]}$,

$\sigma$ 是关于中心分离度的测度。令 $\sigma = D_0$ ,则:$H(u,v)= e^{-D^2(u,v)/2D_0^2}$

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

当 $D(u,v) = D_0$时,高斯低通滤波器下降到它最大值的 0.607 处。

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

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

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

#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;    // 常量法扩充图像边界,常量 = 0    cv::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;}

2. 巴特沃斯低通滤波器

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

$H(u,v)=\frac{1}{1+[\frac{D(u,v)}{D_0}]^{2n}}$

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

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

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

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

#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;    // 常量法扩充图像边界,常量 = 0    cv::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;}

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

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

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

3. 总结

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

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

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

高斯低通滤波器 巴特沃斯低通滤波器 数字图像处理 滤波器
相关文章