天天看點

【OpenCV C++】離散傅裡葉變換離散傅裡葉變換程式說明代碼運作效果傅裡葉變換的頻譜圖的含義

OpenCV C++離散傅裡葉變換

  • 離散傅裡葉變換
  • 程式說明
  • 代碼
  • 運作效果
  • 傅裡葉變換的頻譜圖的含義

離散傅裡葉變換

傅裡葉變換是什麼?一看就懂,寫的超級棒!https://blog.csdn.net/m0_51233386/article/details/114764782

離散傅裡葉變換(Discrete Fourier Transform,DFT)傅裡葉分析方法是信号分析的最基本方法,傅裡葉變換是傅裡葉分析的核心,通過它把信号從時間域變換到頻率域,進而研究信号的頻譜結構和變化規律。

離散傅裡葉變換(DFT),**是傅裡葉變換在時域和頻域上都呈現離散的形式,将時域信号的采樣變換為在離散時間傅裡葉變換(DTFT)頻域的采樣。**在形式上,變換兩端(時域和頻域上)的序列是有限長的,而實際上這兩組序列都應當被認為是離散周期信号的主值序列。即使對有限長的離散信号作DFT,也應當将其看作經過周期延拓成為周期信号再作變換。在實際應用中通常采用快速傅裡葉變換以高效計算DFT。

程式說明

// 程式描述:OpenCV C++離散傅裡葉變換

// 參 考:毛星雲《OpenCV3程式設計入門》

// 作業系統: Windows 10 64bit

// 開發語言: C++

// IDE 版 本:Visual Studio 2019

// OpenCV版本:4.20

代碼

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace cv;

//--------------------------------------【main( )函數】-----------------------------------------
//          描述:控制台應用程式的入口函數,我們的程式從這裡開始執行
//-------------------------------------------------------------------------------------------------
int main()
{
	//【1】以灰階模式讀取原始圖像并顯示
	Mat srcImage = imread("23.jpg",0);
	if (!srcImage.data) { printf("讀取圖檔錯誤,請确定目錄下是否有imread函數指定圖檔存在~! \n"); return false; }
	imshow("原始灰階圖", srcImage);

	//【2】将輸入圖像延擴到最佳的尺寸,邊界用0補充
	int m = getOptimalDFTSize(srcImage.rows);
	int n = getOptimalDFTSize(srcImage.cols);
	//将添加的像素初始化為0.
	Mat padded;
	copyMakeBorder(srcImage, padded, 0, m - srcImage.rows, 0, n - srcImage.cols, BORDER_CONSTANT, Scalar::all(0));

	//【3】為傅立葉變換的結果(實部和虛部)配置設定存儲空間。
	//将planes數組組合合并成一個多通道的數組complexI
	Mat planes[] = { Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F) };
	Mat complexI;
	merge(planes, 2, complexI);

	//【4】進行就地離散傅裡葉變換
	dft(complexI, complexI);

	//【5】将複數轉換為幅值,即=> log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2))
	split(complexI, planes); // 将多通道數組complexI分離成幾個單通道數組,planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))
	magnitude(planes[0], planes[1], planes[0]);// planes[0] = magnitude  
	Mat magnitudeImage = planes[0];

	//【6】進行對數尺度(logarithmic scale)縮放
	magnitudeImage += Scalar::all(1);
	log(magnitudeImage, magnitudeImage);//求自然對數

	//【7】剪切和重分布幅度圖象限
	//若有奇數行或奇數列,進行頻譜裁剪      
	magnitudeImage = magnitudeImage(Rect(0, 0, magnitudeImage.cols & -2, magnitudeImage.rows & -2));
	//重新排列傅立葉圖像中的象限,使得原點位于圖像中心  
	int cx = magnitudeImage.cols / 2;
	int cy = magnitudeImage.rows / 2;
	Mat q0(magnitudeImage, Rect(0, 0, cx, cy));   // ROI區域的左上
	Mat q1(magnitudeImage, Rect(cx, 0, cx, cy));  // ROI區域的右上
	Mat q2(magnitudeImage, Rect(0, cy, cx, cy));  // ROI區域的左下
	Mat q3(magnitudeImage, Rect(cx, cy, cx, cy)); // ROI區域的右下
	//交換象限(左上與右下進行交換)
	Mat tmp;
	q0.copyTo(tmp);
	q3.copyTo(q0);
	tmp.copyTo(q3);
	//交換象限(右上與左下進行交換)
	q1.copyTo(tmp);
	q2.copyTo(q1);
	tmp.copyTo(q2);

	//【8】歸一化,用0到1之間的浮點值将矩陣變換為可視的圖像格式
	//此句代碼的OpenCV2版為:
	//normalize(magnitudeImage, magnitudeImage, 0, 1, CV_MINMAX); 
	//此句代碼的OpenCV3版為:
	normalize(magnitudeImage, magnitudeImage, 0, 1, NORM_MINMAX);

	//【9】顯示效果圖
	imshow("頻譜幅值", magnitudeImage);
	waitKey();

	return 0;
}


           

運作效果

示例(1)

【OpenCV C++】離散傅裡葉變換離散傅裡葉變換程式說明代碼運作效果傅裡葉變換的頻譜圖的含義
【OpenCV C++】離散傅裡葉變換離散傅裡葉變換程式說明代碼運作效果傅裡葉變換的頻譜圖的含義

示例(2)

為了便于了解變換過程,我将中間過程的圖檔也輸出了,其實我們隻需要得到最後一幅頻譜圖。

【OpenCV C++】離散傅裡葉變換離散傅裡葉變換程式說明代碼運作效果傅裡葉變換的頻譜圖的含義
【OpenCV C++】離散傅裡葉變換離散傅裡葉變換程式說明代碼運作效果傅裡葉變換的頻譜圖的含義

離散傅裡葉變換的運作速度與圖檔尺寸有很大關系,當圖像的尺寸的2,3, 5的整數倍時,計算速度最快。是以,為了達到快速計算的目的,經常通過添加新的邊緣像素的方法擷取最佳圖像尺寸。

将輸入圖像延擴到最佳的尺寸,邊界用0補充,可以看到圖檔下方多出了寬度大概0.5厘米的黑條。

【OpenCV C++】離散傅裡葉變換離散傅裡葉變換程式說明代碼運作效果傅裡葉變換的頻譜圖的含義
【OpenCV C++】離散傅裡葉變換離散傅裡葉變換程式說明代碼運作效果傅裡葉變換的頻譜圖的含義

示例(3)

【OpenCV C++】離散傅裡葉變換離散傅裡葉變換程式說明代碼運作效果傅裡葉變換的頻譜圖的含義
【OpenCV C++】離散傅裡葉變換離散傅裡葉變換程式說明代碼運作效果傅裡葉變換的頻譜圖的含義

離散傅裡葉變換的運作速度與圖檔尺寸有很大關系,當圖像的尺寸的2,3, 5的整數倍時,計算速度最快。是以,為了達到快速計算的目的,經常通過添加新的邊緣像素的方法擷取最佳圖像尺寸。

将輸入圖像延擴到最佳的尺寸,邊界用0補充,可以看到圖檔下方多出了寬度大概0.9厘米的黑條。

【OpenCV C++】離散傅裡葉變換離散傅裡葉變換程式說明代碼運作效果傅裡葉變換的頻譜圖的含義

示例(4)

【OpenCV C++】離散傅裡葉變換離散傅裡葉變換程式說明代碼運作效果傅裡葉變換的頻譜圖的含義
【OpenCV C++】離散傅裡葉變換離散傅裡葉變換程式說明代碼運作效果傅裡葉變換的頻譜圖的含義

此圖尺寸剛好合适,邊緣就沒有明顯的新增像素。

【OpenCV C++】離散傅裡葉變換離散傅裡葉變換程式說明代碼運作效果傅裡葉變換的頻譜圖的含義
【OpenCV C++】離散傅裡葉變換離散傅裡葉變換程式說明代碼運作效果傅裡葉變換的頻譜圖的含義

傅裡葉變換的頻譜圖的含義

詳情參考:https://blog.csdn.net/m0_51233386/article/details/115134101

二維頻譜中的每一個點都是一個與之一一對應的二維正弦/餘弦波。

頻譜圖除了周期性之外,還表示高頻低頻的分布。在經過頻譜居中後的頻譜中,中間最亮的點是最低頻率,屬于直流分量(DC分量)。越往邊外走,頻率越高。是以,頻譜圖中的四個角和X,Y軸的盡頭都是高頻。

繼續閱讀