OpenCV傅立叶正逆变换和频谱处理的例子
- Opencv中的范例中只给出了傅立叶正变换的生成频谱图像的例子,没有给出逆变换和频谱处理的例子,由于最近工作中要用到,就研究了一下用法,理论是几年前在大学学的,现在忘得差不多了,只是简单的回顾了下,所以理论方面就不多论述了,直接看代码。
C/C++
//这是范例中生成频谱图的代码,对其中部分进行了改动,
int M = getOptimalDFTSize( img.rows );
int N = getOptimalDFTSize( img.cols );
Mat padded;
copyMakeBorder(img, padded, 0, M - img.rows, 0, N - img.cols, BORDER_CONSTANT, Scalar::all(0));
Mat planes[2] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
Mat ImgDFT;
merge(planes, 2, ImgDFT);
dft(ImgDFT, ImgDFT);
//正变换过后,先对频谱图进行中心平移
ImgDFT = ImgDFT(Rect(0, 0, ImgDFT.cols & -2, ImgDFT.rows & -2));
int cx = ImgDFT.cols/2;
int cy = ImgDFT.rows/2;
// rearrange the quadrants of Fourier image
// so that the origin is at the image center
Mat tmp;
Mat q0(ImgDFT, Rect(0, 0, cx, cy));
Mat q1(ImgDFT, Rect(cx, 0, cx, cy));
Mat q2(ImgDFT, Rect(0, cy, cx, cy));
Mat q3(ImgDFT, Rect(cx, cy, cx, cy));
q0.copyTo(tmp);
q3.copyTo(q0);
tmp.copyTo(q3);
q1.copyTo(tmp);
q2.copyTo(q1);
tmp.copyTo(q2);
//将得到的频谱图分解成虚部和实部两部分
split(ImgDFT,planes);
Mat Proc_RE = planes[0];
Mat Proc_IM = planes[1];
/*******************************************************/
//此处定义处理频谱的方法,实部和虚部要分开分别进行处理
double ESP = 0.000001;
for( int i = 0; i < Proc_RE.rows; ++i )
for( int j = 0; j < Proc_RE.cols; ++j )
{
double dx = i - Proc_RE.rows/2;
double dy = j - Proc_RE.cols/2;
Proc_RE.at<float>(i, j) = (1 - exp(-100/(pow(dx, 2) + pow(dy, 2) + ESP)))* Proc_RE.at<float>(i, j);
Proc_IM.at<float>(i, j) = (1 - exp(-100/(pow(dx, 2) + pow(dy, 2) + ESP)))* Proc_IM.at<float>(i, j);
}
/*******************************************************/
#if 1
//此处用于显示处理后的频谱图像(频谱为傅立叶变换的幅值,magnitude()函数可以直接求得),
Mat mag;
magnitude(planes[0], planes[1], mag);
mag += Scalar::all(1);
log(mag, mag);
normalize(mag, mag, 0, 1, CV_MINMAX);
imshow("spectrum magnitude", mag);
waitKey();
#endif // 1
//将处理后的虚部和实部矩阵合成一个矩阵,并进行中心平移,还原回(0,2π)的图像
merge(planes, 2, ImgDFT);
q0.copyTo(tmp);
q3.copyTo(q0);
tmp.copyTo(q3);
q1.copyTo(tmp);
q2.copyTo(q1);
tmp.copyTo(q2);
//进行逆变换,归一化,并将尺寸调整为处理前的图像尺寸
idft(ImgDFT, ImgDFT, DFT_SCALE | DFT_REAL_OUTPUT);//1
//idft(ImgDFT, ImgDFT);//2
//split(ImgDFT, planes);
//为了后续的处理,此处的imp矩阵有两种选择方法:1、直接用Opencv提供的参数,生成输出图像(ImgDFT);
//2、使用2函数逆变换,然后将矩阵分解,选择实数部分为输出图像矩阵(planes[0])注:数字图像处理第三
// 版(冈萨雷斯)上说:为了消除计算不准确导致的寄生复分量,所以只取实部。
Mat imp = ImgDFT;
normalize(imp, imp, 0, 255, CV_MINMAX);
imp.convertTo(imp, CV_8U);
Mat Output = imp(Range(0, img.rows), Range(0, img.cols));
imshow("Output",Output);
waitKey(0);
参考文献:
[1] 冈萨雷斯.数字图象处理(第三版)[M].北京:电子工业出版社,2011.6.
[2] www.opencv.org.cn .如有错误,欢迎指正!
尊重原创,转载请注明出处!
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
- 上一篇: [openCV]图像的傅里叶频谱
- 下一篇: 傅立叶变换及频谱图