标签:
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.傅里叶逆变换
上面得到滤波后的频谱图,
标签:
原文地址:http://www.cnblogs.com/gisvito/p/4087762.html