opencv顯示影象的傅立葉譜影象(頻譜)原始碼詳解
阿新 • • 發佈:2019-02-11
1. 頻率域
通過傅立葉變換連線空間域和頻率域,其是頻率域濾波的基礎。這裡將結合opencv中的sample文件(\source\sample目錄下的dft.cpp),對一副灰度影象進行傅立葉變換,並顯示其傅立葉譜影象。
2. 傅立葉譜顯示
#include<opencv.hpp> #include<iostream> int main(void) { //載入一副灰度影象 cv::Mat src=cv::imread("D:/Opencv Picture/Lena.jpg", CV_LOAD_IMAGE_GRAYSCALE); if (!src.data) { std::cout << "Image Load Fail!!!" << "\n"; return 1; } cv::imshow("SRC", src); //擴充影象尺寸到最佳尺寸,邊界用0填充 int r = cv::getOptimalDFTSize(src.rows); int c = cv::getOptimalDFTSize(src.cols); cv::Mat padded; cv::copyMakeBorder(src, padded, 0, r - src.rows, 0, c - src.cols, cv::BORDER_CONSTANT,cv::Scalar::all(0)); //為傅立葉變換的結果(複數,包含實部和虛部,所以需要建立一個二維的陣列)分配儲存空間, //需要用至少float型來儲存 //最後將二維數組合併為二通道--傅立葉變換需要 cv::Mat dst1[] = { cv::Mat_<float>(padded), cv::Mat::zeros(padded.size(), CV_32F) }; cv::Mat dst2; cv::merge(dst1,2, dst2); //傅立葉變換,結果依舊儲存在dst2中 cv::dft(dst2, dst2); //將複數換算成幅值 cv::split(dst2, dst1);//把二通道影象分解為二維陣列,儲存到dst1中,dst1[0]中存放的為實部 cv::magnitude(dst1[0], dst1[1], dst1[0]);//結果存放在dst1[0]中 cv::Mat magnitudeImage = dst1[0]; //對數尺度縮放以便於顯示 //計算log(1 + sqrt(Re(DFT(dst2))**2 + Im(DFT(dst2))**2)) magnitudeImage += cv::Scalar::all(1); cv::log(magnitudeImage, magnitudeImage); //剪下和重分佈幅度圖象限 //若有奇數行或奇數列,進行頻譜裁剪 magnitudeImage = magnitudeImage(cv::Rect(0, 0, magnitudeImage.cols & -2, magnitudeImage.rows & -2));//任何一個數&-2的結果一定是偶數 //重新排列傅立葉影象的象限,使原點位於影象中心 int cx = magnitudeImage.cols / 2; int cy = magnitudeImage.rows / 2; cv::Mat q0(magnitudeImage(cv::Rect(0, 0, cx, cy))); cv::Mat q1(magnitudeImage(cv::Rect(cx, 0, cx, cy))); cv::Mat q2(magnitudeImage(cv::Rect(0, cy, cx, cy))); cv::Mat q3(magnitudeImage(cv::Rect(cy, cy, cx, cy))); cv::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之間 cv:normalize(magnitudeImage, magnitudeImage, 0, 1, cv::NORM_MINMAX); //顯示最後的頻譜 cv::imshow("spectrum magnitude", magnitudeImage); cv::waitKey(); return 0; }
3. 顯示結果
執行結果如下。
下面來一步步看看,各個步驟的作用。如果不進行歸一化處理的結果如下圖所示,整個畫面發白,根本看不到任何資訊。
如果不進行象限調整,結果如下,低頻出現在圖片的四個角(四角發亮),而通過調整之後將低頻調整到了原點附近。
如果不進行尺度調整,可以發現對比度不高,僅僅能看到中心一個亮點,說明尺度調整後,能顯示更多細節。