opencv的频域滤波

频域滤波流程总结如下:

    1. 给定一幅大小为M×N的输入图像f(x,y),从式(6.1-25)和式(6.1-26)得到填充参数P和Q。典型地,我们选择P=2M和Q=2N;
    2. 对f(x,y)添加必要数量的0,形成大小为P×Q填充后的图像
    3. 用(-1)(x+y)乘以fp(x,y),进行频谱中心化的预处理;
    4. 计算中心化预处理过的fp(x,y)的傅里叶变换,得到Fp(u,v);
    5. 生成一个实的、对称的滤波函数H(u,v),其大小为P×Q,频谱零点位于(P/2,Q/2)处。用阵列相乘形成乘积G(u,v)=F(u,v)H(u,v);
    6. 经过频域滤波后的图像:
            gp(x,y)={real[fft-1[G(u,v)]]}(-1)(x+y)
      其中,为忽略由于计算不准确导致的寄生复分量,选择了实部,下标P指出我们处理的是填充后的阵列;
    7. 通过从 gp(x,y)的左上象限提取M×N区域,得到最终处理结果g(x,y)。
下面是频域滤波示例程序:

在本程序中,共有四个自定义函数,分别是:
1. myMagnitude(),在该函数中封装了Opencv中的
magnitude函数,实现对于复数图像的幅值计算。
2. dftshift(),该函数实现对图像四个象限的对角互换,
相当于MatLab中 fftshift()。
3. displayDftSpectrum(),该函数用于显示复数图像。
4. makeFilter(),用于制作频域滤波器,该函数利用了ptr()
   指针遍历图像的方法,实现了圆等滤波函数。
在主程序内容,参见注释。
#include <iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;

void myMagnitude(Mat & complexImg,Mat & mI)
{
    Mat planes[2];
    split(complexImg,planes);
    magnitude(planes[0],planes[1],mI);
}
void dftshift(Mat& ds)
{
    int cx=ds.cols/2;//图像的中心点x 坐标
    int cy=ds.rows/2;//图像的中心点y 坐标
    Mat q0=ds(Rect(0,0,cx,cy));//左上
    Mat q1=ds(Rect(cx,0,cx,cy));//右上
    Mat q2=ds(Rect(0,cy,cx,cy));//左下
    Mat q3=ds(Rect(cx,cy,cx,cy));//右下
    Mat tmp;
    q0.copyTo(tmp);
    q3.copyTo(q0);
    tmp.copyTo(q3);
    q1.copyTo(tmp);
    q2.copyTo(q1);
    tmp.copyTo(q2);
}
void displayDftSpectrum(Mat&dftDst,String winName,bool inverseSpectrum)
{
    Mat magI;
    myMagnitude(dftDst,magI);
    if(!inverseSpectrum)//如果是正向傅里叶变换谱
    {
        magI+=Scalar::all(1);
        log(magI,magI);
    }
    normalize(magI,magI,0,1,NORM_MINMAX);
    imshow(winName,magI);
}
void makeFilter(Mat&filter,int R,bool isLowPassFilter)
{
    int cx=filter.cols/2,cy=filter.rows/2;
    int R2=R*R;

    for(int i=0;i<filter.rows;i++)
    {
        Vec2d* pf=filter.ptr<Vec2d>(i);
        for(int j=0;j<filter.cols;j++)
        {
            int r2=(j-cx)*(j-cx)+(i-cy)*(i-cy);
            if(r2<R2)
            {
                pf[j][0]=1;
                pf[j][1]=pf[j][0];
            }
        }
    }
    if(!isLowPassFilter)
    {
     filter =Scalar::all(1)-filter;
    }
    Mat displayFilter;
    extractChannel(filter,displayFilter,0);
    imshow("filter image",displayFilter);
}

int main()
{
    ///读入灰度图像
    Mat src=imread("D:\\Qt\\MyImage\\baboon.jpg",0);
    int ny=src.rows,nx=src.cols;
    cv::copyMakeBorder(src,src,0,ny,0,nx,BORDER_CONSTANT);
    imshow("original image",src);
    /***************傅里叶变换*************/
    src.convertTo(src,CV_64FC1);//转成浮点数据类型
    Mat dftDst(src.size(),CV_64FC2);//预设dft的输出结果矩阵
    dft(src,dftDst,DFT_COMPLEX_OUTPUT,0);//离散傅立叶变换
    dftshift(dftDst);//将傅里叶变换的结果,四象限对角互换
    displayDftSpectrum(dftDst,"dftSpectrum display",false);//显示傅里叶频谱图

    /***************频域滤波*************/
    Mat filter(src.size(),CV_64FC2,Scalar::all(0));
    makeFilter(filter,80,false);
    Mat fftTemp=dftDst.mul(filter);//复数频谱图与滤波器相乘,实现频域滤波
    Mat srcFiltered;
    dft(fftTemp,srcFiltered,DFT_INVERSE);//逆傅里叶变换
    //显示经过滤波后的图像
    displayDftSpectrum(srcFiltered,"filtered image",true);//显示逆傅里叶频谱图
    waitKey();
    return 0;
}
				
时间: 2025-01-14 08:41:17

opencv的频域滤波的相关文章

Python下opencv使用笔记(十)(图像频域滤波与傅里叶变换)

前面曾经介绍过空间域滤波,空间域滤波就是用各种模板直接与图像进行卷积运算,实现对图像的处理,这种方法直接对图像空间操作,操作简单,所以也是空间域滤波. 频域滤波说到底最终可能是和空间域滤波实现相同的功能,比如实现图像的轮廓提取,在空间域滤波中我们使用一个拉普拉斯模板就可以提取,而在频域内,我们使用一个高通滤波模板(因为轮廓在频域内属于高频信号),可以实现轮廓的提取,后面也会把拉普拉斯模板频域化,会发现拉普拉斯其实在频域来讲就是一个高通滤波器. 既然是频域滤波就涉及到把图像首先变到频域内,那么把图

傅里叶变换和频域滤波

傅里叶变换 #include "opencv2/opencv.hpp" using namespace cv; #define PI2 2*3.141592654 int main() { Mat image = imread("lena.png"); resize(image, image, Size(100,100)); cvtColor(image,image,CV_RGB2GRAY); imshow("src",image); image

傅里叶变换,频域滤波

#include "opencv2/opencv.hpp" using namespace cv; #define PI2 2*3.141592654 int main() { Mat image = imread("lena.png"); resize(image, image, Size(100,100)); cvtColor(image,image,CV_RGB2GRAY); imshow("src",image); image.conve

opencv中值滤波和低通滤波器对椒盐噪声处理的效果比较

opencv中值滤波和低通滤波器对椒盐噪声处理的效果比较 效果: 通过比较我们可以看出,中值滤波器有很好的保留了图像的边界信息 代码: void showimage(const std::string &str,const cv::Mat &image){ namedWindow(str,CV_WINDOW_AUTOSIZE); imshow(str,image); } Mat salt(const cv::Mat &image,int n){ Mat result = image

目标跟踪之粒子滤波---Opencv实现粒子滤波算法

目标跟踪学习笔记_2(particle filter初探1) 目标跟踪学习笔记_3(particle filter初探2) 前面2篇博客已经提到当粒子数增加时会内存报错,后面又仔细查了下程序,是代码方面的问题.所以本次的代码与前几次改变比较小.当然这些code基本也是参考网上的.代码写得很不规范,时间不够,等以后有机会将其优化并整理成类的形式.)              Opencv实现粒子滤波算法            摘要 本文通过opencv实现了一种目标跟踪算法——粒子滤波算法,算法的

灰度图像--频域滤波 同态滤波

学习DIP第27天 转载请标明本文出处:http://blog.csdn.net/tonyshengtan,欢迎大家转载,发现博客被某些论坛转载后,图像无法正常显示,无法正常表达本人观点,对此表示很不满意.有些网站转载了我的博文,很开心的是自己写的东西被更多人看到了,但不开心的是这段话被去掉了,也没标明转载来源,虽然这并没有版权保护,但感觉还是不太好,出于尊重文章作者的劳动,转载请标明出处!!!! 文章代码已托管,欢迎共同开发:https://github.com/Tony-Tan/DIPpro

从图像空间域滤波到频域滤波

频域滤波的快速实现是工程领域的里程碑.频域滤波最让工程师兴奋的原因来自于这个公式: f(x)*g(y)<-->F(u)G(v) 这说明空间域中的复杂的卷积算子,变换到频域中就成了简单的乘法,这样不仅计算简单,而且工程上易于实现.在FFT和快速DCT(余弦变换)的数字实现之前,频域变换的计算是很头疼的事情,在计算效率上并不比普通卷积快多少:在FFT和快读DCT实现之后,频域信号处理几乎无处不在. 空间域滤波的算子可以变成频域滤波算子.假设当前图像尺寸为512x512,滤波算子大小为3x3,显然直

灰度图像--频域滤波 概论

学习DIP第25天 转载请标明本文出处:http://blog.csdn.net/tonyshengtan,欢迎大家转载,发现博客被某些论坛转载后,图像无法正常显示,无法正常表达本人观点,对此表示很不满意.有些网站转载了我的博文,很开心的是自己写的东西被更多人看到了,但不开心的是这段话被去掉了,也没标明转载来源,虽然这并没有版权保护,但感觉还是不太好,出于尊重文章作者的劳动,转载请标明出处!!!! 开篇废话 这两天写了一下频域滤波的代码,并且发现以前博客里代码的一个BUG,产生BUG的原因是一维

数字图像处理-频域滤波

频域滤波 频域滤波是在频率域对图像做处理的一种方法.步骤如下: 1.理想的高/低通滤波器 顾名思义,高通滤波器为:让高频信息通过,过滤低频信息:低通滤波相反.滤波器大小和频谱大小相同, 理想的低通滤波器模板为: 其中,D0表示通带半径,D(u,v)是到频谱中心的距离(欧式距离),计算公式如下: M和N表示频谱图像的大小,(M/2,N/2)即为频谱中心 理想的高通滤波器与此相反,1减去低通滤波模板即可. 代码如下:(D0=20) """理想的高/低通滤波器""