这里我们将从两个方面进行频域增强的学习
一、任选两幅图像(包括一副自备图像),计算其频谱图,并显示
二、采用频域滤波的方法进行图像降采样和升采样
一、首先计算其频谱图,用到的库函数如下:
CV_EXPORTS_W void dft(InputArray src, OutputArray dst, int flags = 0, int nonzeroRows = 0);
•在进行dft之前我们需要提取图片的行和列的像素值,然后创建一个二维的数组来储存傅里叶变换的实部和虚部。
•进行完dft之后,我们需要重新排列傅里叶图像的象限,使原点位于中心。
代码实现如下:
Mat Fourier_transform(Mat& imag)
{
int r = getOptimalDFTSize(imag.rows);
int c = getOptimalDFTSize(imag.cols);
Mat padded;
copyMakeBorder(imag, padded, 0, r - imag.rows, 0, c - imag.cols, BORDER_CONSTANT, Scalar::all(0));
//为傅里叶变换的结果(复数,包含实部和虚部,所以需要创建一个二维的数组
//分配存储空间,
//需要用至少float型来存储
//最后将二维数组合并为二通道--傅里叶变换需要
Mat dst1[] = { Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F) };
Mat dst2;
merge(dst1, 2, dst2);
//傅里叶变换,结果依旧存储在dst2中
dft(dst2, dst2);
//将复数换算成幅值
split(dst2, dst1);//把二通道图像分解为二维数组,保存到dst1中,dst1[0]中存放的为实部
magnitude(dst1[0], dst1[1], dst1[0]);//结果存放在dst1[0]中
Mat magnitudeImage = dst1[0];
//对数尺度缩放以便于显示
//计算log(1 + sqrt(Re(DFT(dst2))**2 + Im(DFT(dst2))**2))
magnitudeImage += Scalar::all(1);
log(magnitudeImage, magnitudeImage);
//剪切和重分布幅度图象限
//若有奇数行或奇数列,进行频谱裁剪
magnitudeImage = magnitudeImage(Rect(0, 0, magnitudeImage.cols & -2, magnitudeImage.rows & -2));//任何一个数&-2的结果一定是偶数
//重新排列傅里叶图像的象限,使原点位于图像中心
int cx = magnitudeImage.cols / 2;
int cy = magnitudeImage.rows / 2;
Mat q0(magnitudeImage(Rect(0, 0, cx, cy)));
Mat q1(magnitudeImage(Rect(cx, 0, cx, cy)));
Mat q2(magnitudeImage(Rect(0, cy, cx, cy)));
Mat q3(magnitudeImage(Rect(cy, cy, cx, cy)));
Mat tmp;
q0.copyTo(tmp);
q3.copyTo(q0);
tmp.copyTo(q3);
q1.copyTo(tmp);
q2.copyTo(q1);
tmp.copyTo(q2);
//将幅度值归一化到0~1之间,这是因为magnitudeImage中的数据类型是浮点型,这时用imshow()来显示函数,会将像素值乘于255,因此需要归一化到0~1之间
normalize(magnitudeImage, magnitudeImage, 0, 1,NORM_MINMAX);
//返回最后的频谱图像
return magnitudeImage;
}
其效果图如下:
二、采用频域滤波的方法进行图像降采样和升采样
这里我们主要用到的库函数如下:
CV_EXPORTS_W void pyrDown( InputArray src, OutputArray dst,const Size& dstsize = Size(), int borderType = BORDER_DEFAULT ); //降采样函数
CV_EXPORTS_W void pyrUp( InputArray src, OutputArray dst,const Size& dstsize = Size(), int borderType = BORDER_DEFAULT );//升采样函数
•高斯金字塔–降采样
•高斯金字塔从底向上,逐层降采样取得,不能跨域越层;
•对当前层删除偶数行与列就得到降采样后上一层的图片;
•高斯金字塔生成步骤:
•①进行高斯模糊;
•②删除偶数行与列。
•升采样则与之相反。
代码如下:
//降采样
Mat PyrDownTest(Mat& imag)
{
Mat dest1, dest2;
pyrDown(imag, dest1, Size(imag.cols/2 , imag.rows/2 ));
pyrDown(dest1, dest2, Size(dest1.cols / 2, dest1.rows / 2));
return dest2;
}
//升采样
Mat PyrupTest(Mat& imag)
{
Mat dest1, dest2;
pyrUp(imag, dest1, Size(imag.cols * 2, imag.rows * 2));
pyrUp(dest1, dest2, Size(dest2.cols * 2, dest2.rows * 2));
return dest2;
}
效果图如下:
主函数如下:
int main()
{
/*
Mat img = imread("5.jpg");
Mat src = imread("p3-05.tif", CV_LOAD_IMAGE_GRAYSCALE);
Mat src_1 = imread("1.jpg", CV_LOAD_IMAGE_GRAYSCALE);
if (!img.data)
{
std::cout << "Image->img Load Fail!!!" << "\n";
return 1;
}
if (!src.data)
{
std::cout << "Image->scr Load Fail!!!" << "\n";
return 1;
}
if (!src_1.data)
{
std::cout << "Image-scr_1 Load Fail!!!" << "\n";
return 1;
}*/
/**********************傅里叶变换*************************/
//namedWindow("【载入的图片1】", CV_WINDOW_AUTOSIZE);
//imshow("【载入的图片1】", src);
//namedWindow("【载入的图片2】", CV_WINDOW_AUTOSIZE);
//imshow("【载入的图片2】", src_1);
// Mat show_img, show_img_1;
//show_img = Fourier_transform(src);
//show_img_1 = Fourier_transform(src_1);
//imshow("【傅里叶变换后的图片1】", show_img);
//imshow("【傅里叶变换后的图片2】", show_img_1);
/*****************************************************/
/**********************升采样,降采样*************************/
/*namedWindow("【载入的图片】", CV_WINDOW_AUTOSIZE);
imshow("【载入的图片】", img);
Mat show_img;
show_img = PyrDownTest(img);
imshow("【降采样后的图片】", show_img);
show_img = PyrupTest(show_img);
imshow("【升采样后的图片】", show_img);*/
/*****************************************************/
waitKey(0);
return 0;
}
按照自己的需要进行相应的处理即可。
完。