1. 下面是频域滤波示例程序:
  1. 在本程序中,共有五个自定义函数,分别是:
  1. 1. myMagnitude(),在该函数中封装了Opencv中的magnitude函数,实现对于复数图像的幅值计算。
  1. 2. dftshift(),该函数实现对图像四个象限的对角互换,相当于MatLab fftshift(),将频谱的原点(00)移到图像中心。示例1中采用了该函数实现了频谱图中心化。
  1. 3. srcCentralized()用于傅里叶变换前的预处理,以便得到傅里叶频谱的原点(00)位于图像的中心。
  1. 该函数与dftshift()目的一致,实现方法不同,一个是变换前预处理,一个是变换后处理。
  1. 示例2中采用了该函数实现了频谱图中心化。
  1. 4. displayDftSpectrum(),该函数用于显示复数图像。
  1. 5. makeFilter(),用于制作频域滤波器,该函数利用了ptr()
  1. 指针遍历图像的方法,实现了圆等滤波函数。
  1. 下面是两个示例,分别采用了dftshift()、srcCentralized()实现频谱图的中心化。示例2与冈萨雷斯的《数字图像处理(第3版)》的4.6.7小结中的流程一致。
  1. 在主程序内容,参见注释。
    示例1:在该程序中采用了第2个函数dftshift(),实现了频谱图中心化。
  1.  
  1. #include <iostream>
  2. #include<opencv2/opencv.hpp>
  3. using namespace cv;
  4. using namespace std;
  5.  
  6. void myMagnitude(Mat & complexImg,Mat & mI)
  7. {
  8. Mat planes[];
  9. split(complexImg,planes);
  10. magnitude(planes[],planes[],mI);
  11. }
  12. void dftshift(Mat& ds)
  13. {
  14. int cx=ds.cols/;//图像的中心点x 坐标
  15. int cy=ds.rows/;//图像的中心点y 坐标
  16. Mat q0=ds(Rect(,,cx,cy));//左上
  17. Mat q1=ds(Rect(cx,,cx,cy));//右上
  18. Mat q2=ds(Rect(,cy,cx,cy));//左下
  19. Mat q3=ds(Rect(cx,cy,cx,cy));//右下
  20. Mat tmp;
  21. q0.copyTo(tmp);
  22. q3.copyTo(q0);
  23. tmp.copyTo(q3);
  24. q1.copyTo(tmp);
  25. q2.copyTo(q1);
  26. tmp.copyTo(q2);
  27. }
  28. void displayDftSpectrum(Mat&dftDst,String winName,bool inverseSpectrum)
  29. {
  30. Mat magI;
  31. myMagnitude(dftDst,magI);
  32. if(!inverseSpectrum)//如果是正向傅里叶变换谱
  33. {
  34. magI+=Scalar::all();
  35. log(magI,magI);
  36. }
  37. normalize(magI,magI,,,NORM_MINMAX);
  38. imshow(winName,magI);
  39. }
  40. void makeFilter(Mat&filter,int R,bool isLowPassFilter)
  41. {
  42. int cx=filter.cols/,cy=filter.rows/;
  43. int R2=R*R;
  44.  
  45. for(int i=;i<filter.rows;i++)
  46. {
  47. Vec2d* pf=filter.ptr<Vec2d>(i);
  48. for(int j=;j<filter.cols;j++)
  49. {
  50. int r2=(j-cx)*(j-cx)+(i-cy)*(i-cy);
  51. if(r2<R2)
  52. {
  53. pf[j][]=;
  54. pf[j][]=pf[j][];
  55. }
  56. }
  57. }
  58. if(!isLowPassFilter)
  59. {
  60. filter =Scalar::all()-filter;
  61. }
  62. Mat displayFilter;
  63. extractChannel(filter,displayFilter,);
  64. imshow("filter image",displayFilter);
  65. }
  66.  
  67. int main()
  68. {
  69. ///读入灰度图像
  70. Mat src=imread("D:\\Qt\\MyImage\\baboon.jpg",);
  71. int ny=src.rows,nx=src.cols;
  72. cv::copyMakeBorder(src,src,,ny,,nx,BORDER_CONSTANT);
  73. imshow("original image",src);
  74. /***************傅里叶变换*************/
  75. src.convertTo(src,CV_64FC1);//转成浮点数据类型
  76. Mat dftDst(src.size(),CV_64FC2);//预设dft的输出结果矩阵
  77. dft(src,dftDst,DFT_COMPLEX_OUTPUT,);//离散傅立叶变换
  78. dftshift(dftDst);//将傅里叶变换的结果,四象限对角互换
  79. displayDftSpectrum(dftDst,"dftSpectrum display",false);//显示傅里叶频谱图
  80.  
  81. /***************频域滤波*************/
  82. Mat filter(src.size(),CV_64FC2,Scalar::all());
  83. makeFilter(filter,,false);
  84. Mat fftTemp=dftDst.mul(filter);//复数频谱图与滤波器相乘,实现频域滤波
  85. Mat srcFiltered;
  86. dft(fftTemp,srcFiltered,DFT_INVERSE);//逆傅里叶变换
  87. //显示经过滤波后的图像
  88. displayDftSpectrum(srcFiltered,"filtered image",true);//显示逆傅里叶频谱图
  89. waitKey();
  90. return ;
  91. }

示例2:在该示例中采用了第3个函数srcCentralized(),实现频谱图中心化。程序流程即

在本教材的6.2.3频域滤波步骤小结中,或者在冈萨雷斯的《数字图像处理》4.6.7节中,频域滤波流程总结如下:

    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. /*求取复数矩阵的幅值*/
  2. void myMagnitude(Mat & complexImg,Mat & mI)
  3. {
  4. Mat planes[];
  5. split(complexImg,planes);
  6. magnitude(planes[],planes[],mI);
  7. }
  8. /*傅里叶变换后的频谱图后处理,将傅里叶普的原点(0,0)平移到图像的中心*/
  9. void dftshift(Mat& ds)
  10. {
  11. int cx=ds.cols/;//图像的中心点x 坐标
  12. int cy=ds.rows/;//图像的中心点y 坐标
  13. Mat q0=ds(Rect(,,cx,cy));//左上
  14. Mat q1=ds(Rect(cx,,cx,cy));//右上
  15. Mat q2=ds(Rect(,cy,cx,cy));//左下
  16. Mat q3=ds(Rect(cx,cy,cx,cy));//右下
  17. Mat tmp;
  18. q0.copyTo(tmp);
  19. q3.copyTo(q0);
  20. tmp.copyTo(q3);
  21. q1.copyTo(tmp);
  22. q2.copyTo(q1);
  23. tmp.copyTo(q2);
  24. }
  25. /*傅里叶变换前的预处理,以便频谱图的原点(0,0)移动到图像的中心*/
  26. void srcCentralized(Mat& src)
  27. {
  28. for(int i=;i<src.rows;i++)
  29. {
  30. for(int j=;j<src.cols;j++)
  31. {
  32. float* mv=CV_MAT_ELEM2(src,float,i,j);
  33. if((i+j)%!=)
  34. mv[]=-mv[];//如果i+j为奇数,该像素值取负值
  35. }
  36. }
  37. }
  38. /*在窗口中显示复数图像,如果是正向傅里叶矩阵,需要取log才能显示更多频谱信息
  39. *如果是逆傅里叶变换,通过normalize归一化后,显示频谱图*/
  40. void displayDftSpectrum(Mat&dftDst,String winName,bool inverseSpectrum)
  41. {
  42. Mat magI;
  43. myMagnitude(dftDst,magI);
  44. if(!inverseSpectrum)//如果是正向傅里叶变换谱
  45. {
  46. magI+=Scalar::all();
  47. log(magI,magI);
  48. }
  49. normalize(magI,magI,,,NORM_MINMAX);
  50. imshow(winName,magI);
  51. }
  52. void makeFilter(Mat&filter,int R,bool isLowPassFilter)
  53. {
  54. int cx=filter.cols/,cy=filter.rows/;
  55. int R2=R*R;
  56.  
  57. for(int i=;i<filter.rows;i++)
  58. {
  59. Vec2d* pf=filter.ptr<Vec2d>(i);
  60. for(int j=;j<filter.cols;j++)
  61. {
  62. int r2=(j-cx)*(j-cx)+(i-cy)*(i-cy);
  63. if(r2<R2)
  64. {
  65. pf[j][]=;
  66. pf[j][]=pf[j][];
  67. }
  68. }
  69. }
  70. if(!isLowPassFilter)
  71. {
  72. filter =Scalar::all()-filter;
  73. }
  74. Mat displayFilter;
  75. extractChannel(filter,displayFilter,);
  76. imshow("filter image",displayFilter);
  77. }
  78.  
  79. int main()
  80. {
  81. ///读入灰度图像
  82. Mat src=imread("D:\\Qt\\MyImage\\interferometer2.jpg",);
  83. int ny=src.rows,nx=src.cols;
  84. imshow("original image",src);
  85. src.convertTo(src,CV_32FC1);
  86. srcCentralized(src);
  87. cv::copyMakeBorder(src,src,,ny,,nx,BORDER_CONSTANT);
  88.  
  89. /***************傅里叶变换*************/
  90. src.convertTo(src,CV_64FC1);//转成浮点数据类型
  91. Mat dftDst(src.size(),CV_64FC2);//预设dft的输出结果矩阵
  92. dft(src,dftDst,DFT_COMPLEX_OUTPUT,);//离散傅立叶变换
  93. // dftshift(dftDst);//将傅里叶变换的结果,四象限对角互换
  94. displayDftSpectrum(dftDst,"dftSpectrum display",false);//显示傅里叶频谱图
  95.  
  96. /***************频域滤波*************/
  97. Mat filter(src.size(),CV_64FC2,Scalar::all());
  98. makeFilter(filter,,true);
  99. Mat fftTemp=dftDst.mul(filter);//复数频谱图与滤波器相乘,实现频域滤波
  100. srcCentralized(fftTemp);
  101.  
  102. Mat srcFiltered;
  103. dft(fftTemp,srcFiltered,DFT_INVERSE);//逆傅里叶变换
  104. // 显示经过滤波后的图像
  105. displayDftSpectrum(srcFiltered,"filtered image",true);//显示逆傅里叶频谱图
  106. waitKey();
  107. return ;
  108. }
  1.  

opencv的频域滤波的更多相关文章

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

    前面以前介绍过空间域滤波,空间域滤波就是用各种模板直接与图像进行卷积运算,实现对图像的处理,这个方案直接对图像空间操作,操作简单.所以也是空间域滤波. 频域滤波说究竟终于可能是和空间域滤波实现相同的功 ...

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

    Python下opencv使用笔记(图像频域滤波与傅里叶变换) 转载一只程序喵 最后发布于2018-04-06 19:07:26 阅读数 1654  收藏 展开 本文转载自  https://blog ...

  3. Matlab中图像处理实例:灰度变换,空域滤波,频域滤波,傅里叶变换的实现

    http://blog.sciencenet.cn/blog-95484-803140.html % %图像灰度变换 % f = imread('E:\2013第一学期课程\媒体计算\实验一\Img\ ...

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

    目标跟踪学习笔记_2(particle filter初探1) 目标跟踪学习笔记_3(particle filter初探2) 前面2篇博客已经提到当粒子数增加时会内存报错,后面又仔细查了下程序,是代码方 ...

  5. 灰度图像--频域滤波 傅里叶变换之离散傅里叶变换(DFT)

    学习DIP第23天 转载请标明本文出处:http://blog.csdn.net/tonyshengtan,欢迎大家转载,发现博客被某些论坛转载后,图像无法正常显示,无法正常表达本人观点,对此表示很不 ...

  6. 灰度图像--频域滤波 傅里叶变换之离散时间傅里叶变换(DTFT)

    学习DIP第22天 转载请标明本文出处:http://blog.csdn.net/tonyshengtan,欢迎大家转载,发现博客被某些论坛转载后,图像无法正常显示,无法正常表达本人观点,对此表示很不 ...

  7. 灰度图像--频域滤波 傅里叶变换之连续信号傅里叶变换(FT)

    学习DIP第20天 转载请标明本文出处:http://blog.csdn.net/tonyshengtan,欢迎大家转载,发现博客被某些论坛转载后,图像无法正常显示,无法正常表达本人观点,对此表示很不 ...

  8. CUDA加opencv复现导向滤波算法

    CUDA是GPU通用计算的一种,其中现在大热的深度学习底层GPU计算差不多都选择的CUDA,在这我们先简单了解下其中的一些概念,为了好理解,我们先用DX11里的Compute shader来和CUDA ...

  9. opencv中的滤波

    以前的时候,为了过滤图像中的一些噪点,学过一些简单的滤波,比如中值滤波,均值滤波,也是自己实现的. 在opencv中有现成的函数可以调用,实现滤波的操作. 函数的原型如下: CVAPI(void) c ...

随机推荐

  1. 29.Jwt集成(3):token设置过期时间、异常判断

    token设置过期时间 package main import ( "fmt" "github.com/dgrijalva/jwt-go" "io/i ...

  2. Ubuntu下搜狗输入法乱码

    本文适用于Ubuntu 16.04,造冰箱的大熊猫@cnblogs 2018/10/10 参考<这里>,可以不用重新登录 这个问题时不时的出现,很烦人,最简单最粗暴的解决的方法是将&quo ...

  3. 降维算法----PCA原理推导

    1.从几何的角度去理解PCA降维 以平面坐标系为例,点的坐标是怎么来的? 图1                                                             ...

  4. Postman(一)、断言

    postman常见断言方法介绍: 1.Clear a global variable (清除一个全局变量)  postman.clearGlobalVariable("variable_ke ...

  5. fiddler(一)、下载及安装

    fiddler 官网地址:https://www.telerik.com/fiddler 进入页面后点击 Free download 进入下载页面,填写用途,邮箱和国家等信息后,点击Download ...

  6. Linux任务计划及周期性任务执行:at、crontab命令

    一.概述 未来的某时间点执行一次某任务:at, batch 周期性运行某任务:crontab 这两个任务的执行结果:会通过邮件发送给用户 (本地终端用户之间的邮件通知) centos 5,6,7默认开 ...

  7. Android_(控件)Chronometer计时器

    Android Chronometer(计时器) 继承TextView,显示的是某个时间点开始以及之后的时间增加 运行截图 程序结构 package com.example.administrator ...

  8. C++入门经典-例5.3例5.4-输出int指针运算后的地址值

    1:代码如下: // 5.3.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> using ...

  9. IDEA无法自动导入HttpServlet包问题解决

    全部都报红,连Alt + Enter都没有提示导包 这时候只需要IDEA右上角的这个键 再点击Libraries 选择添加 → Java 再把你Tomcat中对应的servlet-api.jar添加进 ...

  10. HTML userAgent

    <html> <body> <script type="text/javascript"> document.write("<p ...