1读入一幅图像,对其进行傅里叶变换,并显示傅里叶变换结果。
#include<opencv2/opencv.hpp> #include<iostream> using namespace std; using namespace cv; int main(int a, char **p) { Mat input = imread("pic1.jpg", CV_LOAD_IMAGE_GRAYSCALE); //以灰度图像的方式读入图片 namedWindow("startwindow",WINDOW_NORMAL); imshow("startwindow", input);//显示原图 Mat padded; int m = getOptimalDFTSize(input.rows); //获取最佳尺寸 int n = getOptimalDFTSize(input.cols); copyMakeBorder(input, padded, 0, m - input.rows, 0, n - input.cols, BORDER_CONSTANT, Scalar::all(0)); Mat plane[] = { Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F) };//创建通道,zeros对图片进行初始化 Mat complexI; merge(plane, 2, complexI);//合并通道 //dft实现 dft(complexI, complexI);//进行傅立叶变换,结果保存在自身 //频谱计算,将实数和复数的值转换为幅度值 split(complexI, plane);//分离通道 magnitude(plane[0], plane[1], plane[0]);//获取幅度图像,0通道为实数通道,1为虚数,因为二维傅立叶变换结果是复数 Mat magI = plane[0]; //对数坐标转换 magI += Scalar::all(1); log(magI, magI); //频谱平移 magI = magI(Rect(0, 0, magI.cols & -2, magI.rows & -2)); int cx = magI.cols / 2; int cy = magI.rows / 2;//一下的操作是移动图像,左上与右下交换位置,右上与左下交换位置 Mat part1(magI, Rect(0, 0, cx, cy)); //左上角 Mat part2(magI, Rect(cx, 0, cx, cy));//右上角 Mat part3(magI, Rect(0, cy, cx, cy));//左下角 Mat part4(magI, Rect(cx, cy, cx, cy));//右下角 Mat tmp; part1.copyTo(tmp); part4.copyTo(part1); tmp.copyTo(part4); part2.copyTo(tmp); part3.copyTo(part2); tmp.copyTo(part3); //标准化 normalize(magI, magI, 0, 1, CV_MINMAX); namedWindow("dft", WINDOW_NORMAL); imshow("dft",magI); waitKey(); return 0; }
2. 对不同类型的图像进行傅里叶变换,并分析其频域变换结果的区别。
与上题一样,将输入图片的格式转变一下就OK
3. 实现对图像的反傅里叶变换,并显示反傅里叶变换结果。
#include<opencv2/opencv.hpp> #include<iostream> using namespace std; using namespace cv; int main(int a, char **p) { Mat input=imread("F:\\work_three_grade\\DigitalImage\\c.jpg",CV_LOAD_IMAGE_GRAYSCALE); namedWindow("input", CV_WINDOW_NORMAL); imshow("input", input);//显示原图 int w = getOptimalDFTSize(input.cols); int h = getOptimalDFTSize(input.rows);//获取最佳尺寸,快速傅立叶变换要求尺寸为2的n次方 Mat padded; copyMakeBorder(input, padded, 0, h - input.rows, 0, w - input.cols, BORDER_CONSTANT, Scalar::all(0));//填充图像保存到padded中 Mat plane[] = { Mat_<float>(padded),Mat::zeros(padded.size(),CV_32F) };//创建通道 Mat complexIm; merge(plane, 2, complexIm);//合并通道 dft(complexIm, complexIm);//进行傅立叶变换,结果保存在自身 split(complexIm, plane);//分离通道 magnitude(plane[0], plane[1], plane[0]);//获取幅度图像,0通道为实数通道,1为虚数,因为二维傅立叶变换结果是复数 int cx = padded.cols / 2; int cy = padded.rows / 2;//一下的操作是移动图像,左上与右下交换位置,右上与左下交换位置 Mat temp; Mat part1(plane[0], Rect(0, 0, cx, cy)); Mat part2(plane[0], Rect(cx, 0, cx, cy)); Mat part3(plane[0], Rect(0, cy, cx, cy)); Mat part4(plane[0], Rect(cx, cy, cx, cy)); part1.copyTo(temp); part4.copyTo(part1); temp.copyTo(part4); part2.copyTo(temp); part3.copyTo(part2); temp.copyTo(part3); Mat _complexim; complexIm.copyTo(_complexim);//把变换结果复制一份,进行逆变换,也就是恢复原图 Mat iDft[] = { Mat::zeros(plane[0].size(),CV_32F),Mat::zeros(plane[0].size(),CV_32F) };//创建两个通道,类型为float,大小为填充后的尺寸 idft(_complexim, _complexim);//傅立叶逆变换 split(_complexim, iDft); magnitude(iDft[0], iDft[1], iDft[0]);//分离通道,主要获取0通道 normalize(iDft[0], iDft[0], 1, 0, CV_MINMAX);//归一化处理,float类型的显示范围为0-1,大于1为白色,小于0为黑色 namedWindow("idft", CV_WINDOW_NORMAL); imshow("idft", iDft[0]);//显示逆变换 plane[0] += Scalar::all(1); log(plane[0], plane[0]); normalize(plane[0], plane[0], 1, 0, CV_MINMAX); namedWindow("dft",CV_WINDOW_NORMAL); imshow("dft", plane[0]); waitKey(100086110); return 0; }
4. 对频域变换的结果进行处理,将一部频域结果置为零,进行反傅里叶变换,分析与原始图像的区别。
#include<opencv2/opencv.hpp> #include<iostream> using namespace std; using namespace cv; int main(int a, char **p) { Mat input=imread("F:\\work_three_grade\\DigitalImage\\c.jpg",CV_LOAD_IMAGE_GRAYSCALE); namedWindow("input", CV_WINDOW_NORMAL); imshow("input", input);//显示原图 int w = getOptimalDFTSize(input.cols); int h = getOptimalDFTSize(input.rows);//获取最佳尺寸,快速傅立叶变换要求尺寸为2的n次方 Mat padded; copyMakeBorder(input, padded, 0, h - input.rows, 0, w - input.cols, BORDER_CONSTANT, Scalar::all(0));//填充图像保存到padded中 Mat plane[] = { Mat_<float>(padded),Mat::zeros(padded.size(),CV_32F) };//创建通道 Mat complexIm; merge(plane, 2, complexIm);//合并通道 dft(complexIm, complexIm);//进行傅立叶变换,结果保存在自身 split(complexIm, plane);//分离通道 magnitude(plane[0], plane[1], plane[0]);//获取幅度图像,0通道为实数通道,1为虚数,因为二维傅立叶变换结果是复数 int cx = padded.cols / 2; int cy = padded.rows / 2;//以下的操作是移动图像,左上与右下交换位置,右上与左下交换位置 Mat temp; Mat part1(plane[0], Rect(0, 0, cx, cy)); Mat part2(plane[0], Rect(cx, 0, cx, cy)); Mat part3(plane[0], Rect(0, cy, cx, cy)); Mat part4(plane[0], Rect(cx, cy, cx, cy)); part1.copyTo(temp); //part4.copyTo(part1); temp.copyTo(part4); for (int i = 0; i < cx; i++) { for (int j = 0; j < cy; j++) { part1.at<int>(i, j) = 0; } } part2.copyTo(temp); part3.copyTo(part2); temp.copyTo(part3); //将complexIm的一部分置为0,然后再进行反傅里叶变换 for (int i = 0; i < cx; i++) { for (int j = 0; j < cy; j++) { complexIm.at<int>(i, j) = 0; } } Mat _complexim; complexIm.copyTo(_complexim);//把变换结果复制一份,进行逆变换,也就是恢复原图 Mat iDft[] = { Mat::zeros(plane[0].size(),CV_32F),Mat::zeros(plane[0].size(),CV_32F) };//创建两个通道,类型为float,大小为填充后的尺寸 idft(_complexim, _complexim);//傅立叶逆变换 split(_complexim, iDft); magnitude(iDft[0], iDft[1], iDft[0]);//分离通道,主要获取0通道 normalize(iDft[0], iDft[0], 1, 0, CV_MINMAX);//归一化处理,float类型的显示范围为0-1,大于1为白色,小于0为黑色 namedWindow("idft", CV_WINDOW_NORMAL); imshow("idft", iDft[0]);//显示逆变换 plane[0] += Scalar::all(1); log(plane[0], plane[0]); normalize(plane[0], plane[0], 1, 0, CV_MINMAX); namedWindow("dft",CV_WINDOW_NORMAL); imshow("dft", plane[0]); waitKey(100086110); return 0; }