這裏我們將從兩個方面進行頻域增強的學習
一、任選兩幅圖像(包括一副自備圖像),計算其頻譜圖,並顯示
二、採用頻域濾波的方法進行圖像降採樣和升採樣
一、首先計算其頻譜圖,用到的庫函數如下:
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;
}
按照自己的需要進行相應的處理即可。
完。