OpenCV 学习笔记

OpenCV 笔记(36):频域高通滤波——理想高通滤波器

2024-08-26  本文已影响0人  fengzhizi715

1. 频域高通滤波

频域高通滤波是一种数字图像处理技术,通过在频域中对图像进行处理增强图像的高频成分,从而达到锐化图像边缘和细节的目的。

高频成分: 图像中的高频成分对应着图像的边缘、纹理等细节信息。
低频成分: 图像中的低频成分对应着图像的平滑区域。

1.1 频域高通滤波和空域高通滤波

频域高通滤波和空域高通滤波都是为了增强图像的边缘和细节,但它们在工作原理、实现方式、滤波效果等很多地方有所不同。

  1. 处理域的不同
  1. 实现方式不同
  1. 滤波效果不同
  1. 应用场景不同

简单归纳一下频域高通滤波和空域高通滤波的区别:

特征 频域高通滤波 空域高通滤波
原理 频域变换,增强高频 空间域卷积
实现 傅里叶变换,逆变换 卷积运算
滤波效果 锐化效果好,易产生振铃 锐化效果较好,对噪声鲁棒
应用 高精度锐化,边缘检测 实时处理,特征提取

1.2 频域高通滤波分类

常用的频域高通滤波器包括:

2. 理想高通滤波器

理想高通滤波器的传播函数可以表示为:

H(u,v)= \begin{cases} 1, & D(u,v) > D_0 \\ 0, & D(u,v) \le D_0 \end{cases}

其中,D_0 是截止频率,D(u,v) 表示频域中一点到频域中心的距离。

理想高通滤波器的特点如下:

#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <random>

using namespace std;
using namespace cv;

// 理想高通滤波核函数
cv::Mat ideal_high_kernel(cv::Mat &scr, float d0)
{
    cv::Mat ideal_high_pass(scr.size(), CV_32FC1);
    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));//分子,计算pow必须为float型
            if (d <= d0) {
                ideal_high_pass.at<float>(i, j) = 0;
            }
            else {
                ideal_high_pass.at<float>(i, j) = 1;
            }
        }
    }
    return ideal_high_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);

    // 扩充边界
    int w = getOptimalDFTSize(gray.cols);
    int h = getOptimalDFTSize(gray.rows);

    Mat padded;
    // 常量法扩充图像边界,常量 = 0
    cv::copyMakeBorder(gray, padded, 0, h - gray.rows, 0, w - gray.cols, cv::BORDER_CONSTANT, cv::Scalar::all(0));
    padded.convertTo(padded, CV_32FC1);

    float D0 = 5.0f;
    Mat kernel = ideal_high_kernel(padded, D0);
    Mat dst = frequency_filter(padded, kernel);

    convertScaleAbs(dst, dst);
    imshow("dst", dst);

    waitKey(0);
    return 0;
}
灰度图像vs理想高通滤波的效果.png

3. 总结

本文介绍了频域高通滤波、理想低通滤波器,以及频域高通滤波和空域高通滤波的区别。

理想高通滤波器也是在理论上具有完美的滤波效果,但在实际应用中却存在着严重的振铃现象和对噪声敏感的问题。因此,在实际图像处理中会采用一些近似的滤波器,如巴特沃斯高通滤波器、高斯高通滤波器等来替代理想高通滤波器。

上一篇 下一篇

猜你喜欢

热点阅读