opencv 傅立叶变换及其逆变换实例及其理解1

傅立叶变换是把图像从空间域转化到频率域的变换。

空间域

一般的情况下,空间域的图像是f(x,y)=灰度级(0-255),形象一点就是一个二维矩阵,每个坐标对应一个颜色值。

频率域

先介绍几个概念

频率:对于图像来说可以指图像颜色值的梯度,即灰度级的变化速度

幅度:可以简单的理解为是频率的权,即该频率所占的比例

能量=幅度(可能不太准确)

变换结果为F(u,v)

F代表幅度值,u代表x方向的频率,v代表y方向的频率

opencv 傅立叶变换及其逆变换实例及其理解1_第1张图片

一般会对变换结果进行一定的处理,以便以图片的形式展现,结果就是幅度值被当作灰度级,亮的地方表示能量高

图像的主要部分集中在低频部分,边界和噪声主要集中在高频部分

由于图像变换的结果原点在边缘部分,不容易显示,所以会将原点移动到中心部分。

那么结果便是中间一个亮点朝着周围发散开来,越远离中心位置的能量越低(越暗)。

接下来展示一下代码


     
     
     
     
  1. #include
  2. #include
  3. using namespace std;
  4. using namespace cv;
  5. int main(int a,char **p)
  6. {
  7. Mat input=imread(p[ 1],CV_LOAD_IMAGE_GRAYSCALE); //以灰度图像的方式读入图片
  8. //如果不知到怎么传入p[1]。可以改为
  9. //Mat input=imread(“image.jpg”,CV_LOAD_IMAGE_GRAYSCALE); 
  10. imshow( “input”,input); //显示原图
  11. int w=getOptimalDFTSize(input.cols);
  12. int h=getOptimalDFTSize(input.rows); //获取最佳尺寸,快速傅立叶变换要求尺寸为2的n次方
  13. Mat padded;
  14. copyMakeBorder(input,padded, 0,h-input.rows, 0,w-input.cols,BORDER_CONSTANT,Scalar::all( 0)); //填充图像保存到padded中
  15. Mat plane[]={Mat_< float>(padded),Mat::zeros(padded.size(),CV_32F)}; //创建通道
  16. Mat complexIm;
  17. merge(plane, 2,complexIm); //合并通道
  18. dft(complexIm,complexIm); //进行傅立叶变换,结果保存在自身
  19. split(complexIm,plane); //分离通道
  20. magnitude(plane[ 0],plane[ 1],plane[ 0]); //获取幅度图像,0通道为实数通道,1为虚数,因为二维傅立叶变换结果是复数
  21. int cx=padded.cols/ 2; int cy=padded.rows/ 2; //一下的操作是移动图像,左上与右下交换位置,右上与左下交换位置
  22. Mat temp;
  23. Mat part1(plane[0],Rect(0,0,cx,cy));
  24. Mat part2(plane[0],Rect(cx,0,cx,cy));
  25. Mat part3(plane[0],Rect(0,cy,cx,cy));
  26. Mat part4(plane[0],Rect(cx,cy,cx,cy));
  27. part1.copyTo(temp);
  28. part4.copyTo(part1);
  29. temp.copyTo(part4);
  30. part2.copyTo(temp);
  31. part3.copyTo(part2);
  32. temp.copyTo(part3);
  33. //*******************************************************************
  34. //Mat _complexim(complexIm,Rect(padded.cols/4,padded.rows/4,padded.cols/2,padded.rows/2));
  35. //opyMakeBorder(_complexim,_complexim,padded.rows/4,padded.rows/4,padded.cols/4,padded.cols/4,BORDER_CONSTANT,Scalar::all(0.75));
  36. Mat _complexim;
  37. complexIm.copyTo(_complexim); //把变换结果复制一份,进行逆变换,也就是恢复原图
  38. Mat iDft[]={Mat::zeros(plane[ 0].size(),CV_32F),Mat::zeros(plane[ 0].size(),CV_32F)}; //创建两个通道,类型为float,大小为填充后的尺寸
  39. idft(_complexim,_complexim); //傅立叶逆变换
  40. split(_complexim,iDft); //结果貌似也是复数
  41. magnitude(iDft[ 0],iDft[ 1],iDft[ 0]); //分离通道,主要获取0通道
  42. normalize(iDft[ 0],iDft[ 0], 1, 0,CV_MINMAX); //归一化处理,float类型的显示范围为0-1,大于1为白色,小于0为黑色
  43. imshow( “idft”,iDft[ 0]); //显示逆变换
  44. //*******************************************************************
  45. plane[ 0]+=Scalar::all( 1); //傅立叶变换后的图片不好分析,进行对数处理,结果比较好看
  46. log(plane[ 0],plane[ 0]);
  47. normalize(plane[ 0],plane[ 0], 1, 0,CV_MINMAX);
  48. imshow( “dft”,plane[ 0]);
  49. waitKey( 100086110);
  50. return 0;
  51. }
运行结果

opencv 傅立叶变换及其逆变换实例及其理解1_第2张图片

接下来介绍一下运行结果

左边到右边,第一副图像是原图,第二图是幅值图,第三副图是逆变换后的结果

幅值图,结果和预料的一样

逆变换的结果显示,多了一圈黑边,这是因为填充后的结果


            

你可能感兴趣的:(傅里叶变换)