码迷,mamicode.com
首页 > 其他好文 > 详细

openCV中的频率域变换

时间:2015-04-24 00:54:16      阅读:664      评论:0      收藏:0      [点我收藏+]

标签:

openCV中频率域增强的傅里叶变换已经比较成熟了,在他的官方tutorials文档里有一个完整的得到频谱图的例子,如下:

 #include "opencv2/core/core.hpp"
 #include "opencv2/imgproc/imgproc.hpp"
 #include "opencv2/highgui/highgui.hpp"
 #include <iostream>
 int main(int argc, char ** argv)
 {
  const char* filename = argc >=2 ? argv[1] : "lena.jpg";

   Mat I = imread(filename, CV_LOAD_IMAGE_GRAYSCALE);
   if( I.empty())
     return -1;

   Mat padded; //expand input image to optimal size
   int m = getOptimalDFTSize( I.rows );
   int n = getOptimalDFTSize( I.cols ); // on the border add zero values
   copyMakeBorder(I, padded, 0, m - I.rows, 0, n - I.cols, BORDER_CONSTANT, Scalar::all(0));

   Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
   Mat complexI;
   merge(planes, 2, complexI); // Add to the expanded another plane with zeros

   dft(complexI, complexI); // this way the result may fit in the source matrix

   // compute the magnitude and switch to logarithmic scale
   // => log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2))
   split(complexI, planes); // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))
   magnitude(planes[0], planes[1], planes[0]);// planes[0] = magnitude
   Mat magI = planes[0];

   magI += Scalar::all(1); // switch to logarithmic scale
   log(magI, magI);

   // crop the spectrum, if it has an odd number of rows or columns
   magI = magI(Rect(0, 0, magI.cols & -2, magI.rows & -2));

   // rearrange the quadrants of Fourier image so that the origin is at the image center
   int cx = magI.cols/2;
   int cy = magI.rows/2;

   Mat q0(magI, Rect(0, 0, cx, cy)); // Top-Left - Create a ROI per quadrant
   Mat q1(magI, Rect(cx, 0, cx, cy)); // Top-Right
   Mat q2(magI, Rect(0, cy, cx, cy)); // Bottom-Left
   Mat q3(magI, Rect(cx, cy, cx, cy)); // Bottom-Right

   Mat tmp; // swap quadrants (Top-Left with Bottom-Right)
   q0.copyTo(tmp);
   q3.copyTo(q0);
   tmp.copyTo(q3);

   q1.copyTo(tmp); // swap quadrant (Top-Right with Bottom-Left)
   q2.copyTo(q1);
   tmp.copyTo(q2);

   normalize(magI, magI, 0, 1, CV_MINMAX); // Transform the matrix with float values into a
   // viewable image form (float between values 0 and 1).

   imshow("Input Image" , I ); // Show the result
   imshow("spectrum magnitude", magI);
   waitKey();

   return 0;
 }

写的很好,但是不够完整。完整的频率域处理流程应该是家在图像-->傅里叶变换-->滤波-->傅里叶逆变换-->保存图像,其中滤波是在频谱图的基础上去处理的。他的例子中只完成了前两个步骤。由于某些原因,本人不便于贴出完整流程的代码,所以下面将只贴出后三步的核心代码。

1.滤波

  频率域滤波器常用的有低通滤波器(理想低通、布特沃斯低通、高斯低通)、高通滤波器(理想高通、布特沃斯高通、高斯高通)、选择性滤波(带阻滤波器、带通滤波器、限波滤波器)等,各滤波器的原理可查阅相关的书籍,强烈推荐冈萨雷斯的《数字图像处理》。这里仅以高斯高通滤波器为例,代码如下:

void createGHPF( Mat *dst, float D0)
{
  //center position
  int cx = dst->cols/2;
  int cy = dst->rows/2;
  for( int i=0; i<dst->cols; i++)
  {
    for( int j=0; j<dst->rows; j++)
    {
      float X = i - cx + 1;
      float Y = j - cy + 1;
      float D = sqrt(X*X + Y*Y);
      float param = exp(-pow(D,2)/(2*pow(D0,2)));
      float parami = 1-param;
      dst->at<float>(Point(i,j)) = parami;
    }
  }
  return;
}

  dst中存储的就是滤波器,由于傅里叶变换得到的频率是复数概念的,用Mat保存是用两个通道表示的,所以也要将此滤波器保存为表示复数的双通道形式。

  shift(filter);  //中心化处理,这个上面的tutorials代码里是有的,可以提出来单独作为一个函数
  Mat f_planes[] = { Mat::zeros( complexI.size(), CV_32F), Mat::zeros( complexI.size(), CV_32F)};
  f_planes[0] = filter;
  f_planes[1] = filter;
  Mat f_filter;
  merge( f_planes, 2, f_filter);

  mulSpectrums(complex, f_filter, complex, DFT_ROWS);  //only DFT_ROWS accepted

最后一句是两个矩阵对应位置相乘的操作(区别于矩阵的乘法),就地转换后频谱图中存放的就是滤波后的频谱图了。

2.傅里叶逆变换

  上面得到滤波后的频谱图,

 

openCV中的频率域变换

标签:

原文地址:http://www.cnblogs.com/gisvito/p/4087762.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!