OpenCV-Python中的圖像處理-傅里葉變換

OpenCV-Python中的圖像處理-傅里葉變換

  • 傅里葉變換
    • Numpy中的傅里葉變換
    • Numpy中的傅里葉逆變換
    • OpenCV中的傅里葉變換
    • OpenCV中的傅里葉逆變換
  • DFT的性能優化
  • 不同濾波算子傅里葉變換對比

傅里葉變換

  • 傅里葉變換經常被用來分析不同濾波器的頻率特性。我們可以使用 2D 離散傅里葉變換 (DFT) 分析圖像的頻域特性。實現 DFT 的一個快速算法被稱為快速傅里葉變換( FFT)。
  • 對于一個正弦信號:x (t) = A sin (2πft), 它的頻率為 f,如果把這個信號轉到它的頻域表示,我們會在頻率 f 中看到一個峰值。如果我們的信號是由采樣產生的離散信號組成,我們會得到類似的頻譜圖,只不過前面是連續的,現在是離散。你可以把圖像想象成沿著兩個方向采集的信號。所以對圖像同時進行 X 方向和 Y 方向的傅里葉變換,我們就會得到這幅圖像的頻域表示(頻譜圖)。
  • 對于一個正弦信號,如果它的幅度變化非常快,我們可以說他是高頻信號,如果變化非常慢,我們稱之為低頻信號。你可以把這種想法應用到圖像中,圖像那里的幅度變化非常大呢?邊界點或者噪聲。所以我們說邊界和噪聲是圖像中的高頻分量(注意這里的高頻是指變化非常快,而非出現的次數多)。如果沒有如此大的幅度變化我們稱之為低頻分量。

Numpy中的傅里葉變換

Numpy 中的 FFT 包可以幫助我們實現快速傅里葉變換。函數 np.fft.fft2() 可以對信號進行頻率轉換,輸出結果是一個復雜的數組。本函數的第一個參數是輸入圖像,要求是灰度格式。第二個參數是可選的, 決定輸出數組的大小。輸出數組的大小和輸入圖像大小一樣。如果輸出結果比輸入圖像大,輸入圖像就需要在進行 FFT 前補0。如果輸出結果比輸入圖像小的話,輸入圖像就會被切割。
f = np.fft.fft2(img)
現在我們得到了結果,頻率為 0 的部分(直流分量)在輸出圖像的左上角。如果想讓它(直流分量)在輸出圖像的中心,我們還需要將結果沿兩個方向平移 N/2 。函數 np.fft.fftshift() 可以幫助我們實現這一步。(這樣更容易分析)。進行完頻率變換之后,我們就可以構建振幅譜了。
fshift = np.fft.fftshift(f)

import numpy as np
import cv2
from matplotlib import pyplot as pltimg = cv2.imread('./resource/opencv/image/messi5.jpg', cv2.IMREAD_GRAYSCALE)
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)# 構建振幅圖
magnitude_spectrum = 20*np.log(np.abs(fshift))plt.subplot(121), plt.imshow(img, cmap='gray'), plt.title('Input Image')
plt.subplot(122), plt.imshow(magnitude_spectrum, cmap='gray'), plt.title('Magnitude Spectrum')
plt.show()

在這里插入圖片描述
我們可以看到輸出結果的中心部分更白(亮),這說明低頻分量更多。

Numpy中的傅里葉逆變換

  • 對圖像進行FFT變換之后得到頻域圖像數據,然后再做IFFT變換又可以得到原始圖像。相關函數:np.fft.ifftshift(),np.fft.ifft2()
    fishift = np.fft.ifftshift(fshift)
    img_ifft = np.fft.ifft2(fishift)
  • 我們可以對頻域圖像數據進行操作以實現一些圖像處理效果,如在頻域內將低頻分量的值設為0,可以實現對圖像的高通濾波處理:
    rows, cols = img.shape
    crow, ccol = int(rows/2) , int(cols/2)
    fshift[crow-30:crow+30, ccol-30:ccol+30] = 0
import numpy as np
import cv2
from matplotlib import pyplot as pltimg = cv2.imread('./resource/opencv/image/messi5.jpg', cv2.IMREAD_GRAYSCALE)# 1.在Numpy內對圖像進行傅里葉變換,得到其頻域圖像
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
# 這里是構建振幅圖,顯示圖像頻譜
magnitude_spectrum = 20*np.log(np.abs(fshift))# 2.IFFT 將頻域圖像還原成原始圖像,這里只是驗證FFT的逆運算
fishift = np.fft.ifftshift(fshift)
img_ifft = np.fft.ifft2(fishift)
img_ifft = np.abs(img_ifft) # 取絕對值,否則不能用imshow()來顯示圖像# 3.在頻域內將低頻分量的值設為0,實現高通濾波。
rows, cols = img.shape 
crow, ccol = int(rows/2) , int(cols/2) 
fshift[crow-30:crow+30, ccol-30:ccol+30] = 0 # 4.對高通濾波后的圖像頻域數據進行逆傅里葉變換,得到高通濾波后圖像。
f_ishift = np.fft.ifftshift(fshift)
img_back = np.fft.ifft2(f_ishift)
img_back = np.abs(img_back) # 取絕對值,否則不能用imshow()來顯示圖像
# 構建高通濾波后的振幅圖,顯示圖像頻譜
after_sepctrum = 20*np.log(np.abs(fshift))plt.subplot(231), plt.imshow(img, cmap='gray'), plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(232), plt.imshow(magnitude_spectrum, cmap='gray'), plt.title('Input Image Spectrum'), plt.xticks([]), plt.yticks([])
plt.subplot(233), plt.imshow(img_ifft, cmap='gray'), plt.title('Input IFFT'), plt.xticks([]), plt.yticks([])
plt.subplot(234), plt.imshow(after_sepctrum, cmap='gray'), plt.title('After HPF Spectrum'), plt.xticks([]), plt.yticks([])
plt.subplot(235), plt.imshow(img_back, cmap='gray'), plt.title('Image after HPF'), plt.xticks([]), plt.yticks([])
plt.subplot(236), plt.imshow(img_back), plt.title('Result in JET'), plt.xticks([]), plt.yticks([])
plt.show()

在這里插入圖片描述

OpenCV中的傅里葉變換

OpenCV 中相應的函數是 cv2.dft() 和 cv2.idft()。和前面輸出的結果一樣,但是是雙通道的。第一個通道是結果的實數部分,第二個通道是結果的虛數部分。輸入圖像要首先轉換成 np.float32 格式。

import numpy as np
import cv2
from matplotlib import pyplot as pltimg = cv2.imread('./resource/opencv/image/messi5.jpg', cv2.IMREAD_GRAYSCALE)dft = cv2.dft(np.float32(img), flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)magnitude_spectrum = 20*np.log(cv2.magnitude(dft_shift[:,:,0], dft_shift[:,:,1]))plt.subplot(121), plt.imshow(img, cmap='gray'), plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(magnitude_spectrum, cmap='gray'), plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()

在這里插入圖片描述

OpenCV中的傅里葉逆變換

前面的部分我們實現了一個 HPF(高通濾波)高通濾波其實是一種邊界檢測操作。現在我們來做 LPF(低通濾波)將高頻部分去除。其實就是對圖像進行模糊操作。首先我們需要構建一個掩模,與低頻區域對應的地方設置為 1, 與高頻區域對應的地方設置為 0。

import numpy as np
import cv2
from matplotlib import pyplot as pltimg = cv2.imread('./resource/opencv/image/messi5.jpg', cv2.IMREAD_GRAYSCALE)
# 1.OpenCV中做DFT
dft = cv2.dft(np.float32(img), flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)rows, cols = img.shape
crow, ccol = int(rows/2), int(cols/2)# create a mask first, center square is 1, remaining all zeros
mask = np.zeros((rows, cols, 2), np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 1# apply mask and inverse DFT
fshift = dft_shift*mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0], img_back[:,:,1])plt.subplot(121), plt.imshow(img, cmap='gray'), plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(img_back, cmap='gray'), plt.title('Output Image'), plt.xticks([]), plt.yticks([])
plt.show()

在這里插入圖片描述

DFT的性能優化

  • 當數組的大小為某些值時 DFT 的性能會更好。當數組的大小是 2 的指數時 DFT 效率最高。當數組的大小是 2, 3, 5 的倍數時效率也會很高。所以如果你想提高代碼的運行效率時,你可以修改輸入圖像的大小(補 0)。對于OpenCV 你必須自己手動補 0。但是 Numpy,你只需要指定 FFT 運算的大小,它會自動補 0。
  • OpenCV 提供了一個函數:cv2.getOptimalDFTSize()來確定最佳大小。它可以同時被 cv2.dft() 和 np.fft.fft2() 使用。
import numpy as np
import cv2img = cv2.imread('./resource/opencv/image/messi5.jpg', cv2.IMREAD_GRAYSCALE)
rows,cols = img.shape
print('原始圖像大小:',rows, cols)
nrows = cv2.getOptimalDFTSize(rows)
ncols = cv2.getOptimalDFTSize(cols)
print('DFT最佳大小:',nrows, ncols)

原始圖像大小: 342 548
DFT最佳大小: 360 576

import numpy as np
import cv2
from matplotlib import pyplot as pltimg = cv2.imread('./resource/opencv/image/messi5.jpg', cv2.IMREAD_GRAYSCALE)
rows,cols = img.shape
print('原始圖像大小:',rows, cols)
nrows = cv2.getOptimalDFTSize(rows)
ncols = cv2.getOptimalDFTSize(cols)
print('DFT最佳大小:',nrows, ncols)# Numpy數組操作,原圖擴大到最佳DFT size
nimg = np.zeros((nrows, ncols))
nimg [:rows, :cols] = img# 
right = ncols - cols
bottom = nrows - rows
# just to avoid line breakup in PDF file
mimg = cv2.copyMakeBorder(img, 0, bottom, 0, right, cv2.BORDER_CONSTANT, value=0)plt.subplot(231), plt.imshow(img, cmap='gray')
plt.subplot(232), plt.imshow(nimg, cmap='gray')
plt.subplot(233), plt.imshow(mimg, cmap='gray')
plt.show()

在這里插入圖片描述

不同濾波算子傅里葉變換對比

為什么拉普拉斯算子是高通濾波器?為什么 Sobel 是 HPF?等等。對于第一個問題的答案我們以傅里葉變換的形式給出。我們一起來對不同的算子進行傅里葉變換并分析它們:

import numpy as np
import cv2
from matplotlib import pyplot as plt# simple averaging filter whitout scaling parameter
mean_filter = np.ones((3,3))# creating a guassian filter
x = cv2.getGaussianKernel(5, 10)
# x.T 為矩陣轉置
gaussian = x*x.T# different edge detecting filters
# scharr in x-direction
scharr = np.array([[-3, 0, 3],[-10, 0, 10],[-3, 0, 3]])# sobel in x direction
sobel_x = np.array([[-1, 0, 1],[-2, 0, 2],[-1, 0, 1]])# sobel in y direction
sobel_y = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]])# laplacian
laplacian = np.array([[0, 1, 0], [1, -4, 1],[0, 1, 0]])filters = [mean_filter, gaussian, laplacian, sobel_x, sobel_y, scharr]
filter_name = ['mean_filter', 'gaussian', 'laplacian', 'sobel_x', 'sobel_y', 'scharr_x']fft_filters = [np.fft.fft2(x) for x in filters]
fft_shift = [np.fft.fftshift(y) for y in fft_filters]
mag_spectrum = [np.log(np.abs(z)+1) for z in fft_shift]for i in range(6):plt.subplot(2,3,i+1), plt.imshow(mag_spectrum[i], cmap='gray')plt.title([filter_name[i]]), plt.xticks([]), plt.yticks([])
plt.show()

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/39036.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/39036.shtml
英文地址,請注明出處:http://en.pswp.cn/news/39036.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2308C++對稱轉移

原文 了解對稱轉移 協程組提供了個編寫異步代碼的絕妙方法,與同步代碼一樣.只需要在合適地點加上協待,編譯器就會負責掛起協程,跨掛起點保留狀態,并在操作完成后恢復協程. 但是,最初有個令人討厭的限制,如果不小心,很容易導致棧溢出.如果想避免它,則必須引入額外同步成本,以…

Unity Spine幀事件

SpinePro中添加事件幀 首先 選中右上角的層級樹 然后選擇事件選項 最后在右下角看到 新建 點擊它 新建一個事件 點擊左上角的設置按鈕 彈出編輯窗口 編輯窗口 在右上角 動畫欄 可以切換對應的動畫 點坐邊的那個小灰點來切換 亮點代表當前動畫 選中幀 添加事件 點擊對應事件…

突破防線!泛微OA任意文件上傳Getshell

子曰:“巧言令色,鮮矣仁。” 漏洞復現 訪問漏洞url: 存在漏洞的路徑為 /weaver/weaver.common.Ctrl/.css?arg0com.cloudstore.api.service.Service_CheckApp&arg1validateApp漏洞利用: 漏洞證明: 文筆生疏&…

ubuntu 20.0.4 搭建nvidia 顯卡環境

一、安裝docker 1、安裝dokcer sudo apt install docker.io2、docker 添加到用戶組 創建docker用戶組 sudo groupadd docker添加當前用戶加入docker用戶組 sudo usermod -aG docker ${USER}重啟docker服務 sudo systemctl restart docker切換或者退出當前賬戶再從新登入 …

openGauss學習筆記-41 openGauss 高級數據管理-匿名塊

文章目錄 openGauss學習筆記-41 openGauss 高級數據管理-匿名塊41.1 語法41.2 參數說明41.3 示例 openGauss學習筆記-41 openGauss 高級數據管理-匿名塊 匿名塊(Anonymous Block)是存儲過程的字塊之一,沒有名稱。一般用于不頻繁執行的腳本或…

NPM與外部服務的集成(下)

目錄 1、撤消訪問令牌 2、在CI/CD工作流中使用私有包 2.1 創建新的訪問令牌 持續整合 持續部署 交互式工作流 CIDR白名單 2.2 將令牌設置為CI/CD服務器上的環境變量 2.3 創建并簽入特定于項目的.npmrc文件 2.4 令牌安全 3、Docker和私有模塊 3.1 背景:運…

了解異或的好處和用途

1.什么是異或? 異或:對于二進制,相同為0 不同為11 ⊕ 1 00 ⊕ 0 01 ⊕ 0 10 ⊕ 1 1 2.異或的好處? 異或的好處?1.快速比較兩個值 2.xor a a例如 a 3 011xor 0110003.可以使用 異或 來使某些特定的位翻轉【原因…

移遠RM500U-CN模塊直連嵌入式ubuntu實現撥號上網

目錄 1 平臺: 2 需要準備的資料 3 參考文檔 4 編譯環境與驅動移植 4.1 內核驅動添加廠家ID和產品ID 4. 2.添加零包處理 4.3 增加復位恢復機制 4.4 增加批量輸出 批量輸出 URB 的數量和容量 的數量和容量 4.5 內核配置與編譯 5 QM500U-CN撥號(在開…

Ubuntu和centos版本有哪些區別

Ubuntu和CentOS是兩個非常流行的Linux發行版,它們在一些方面有一些區別,如下所示: CentOS的版本發布周期相對較長,主要是因為它是基于RedHatEnterpriseLinux(RHEL)的。這意味著在RHEL發布后才能推出對應的CentOS版本。而Ubuntu則在…

春秋云鏡 CVE-2021-21315

春秋云鏡 CVE-2021-21315 systeminformation存在命令注入 靶標介紹 systeminformation是一個簡單的查詢系統和OS信息包。 啟動場景 漏洞利用 exp /api/osinfo?param[]$(curl%20-d%20/flag%20xxx.ceye.io)登錄ceye.io平臺,curl請求 http://eci-2zed871sr7xrdjb…

Lombok的使用及注解含義

文章目錄 一、簡介二、如何使用2.1、在IDEA中安裝Lombok插件2.2、添加maven依賴 三、常用注解3.1、Getter / Setter3.2、ToString3.3、NoArgsConstructor / AllArgsConstructor3.4、EqualsAndHashCode3.5、Data3.6、Value3.7、Accessors3.7.1、Accessors(chain true)3.7.2、Ac…

JavaScript 中常用簡寫技巧總結

平時我們寫代碼時最高級的境界是自己寫的東西別人看不懂!哈哈哈!分享一些自己常用的js簡寫技巧,長期更新,會著重挑選一些實用的簡寫技巧,使自己的代碼更簡潔優雅~ 這里只會收集一些大多數人不知道的用法,但…

MySQL新的版本發布模型 - 創新版本和長支持版本

2023年7月18日,MySQL發布了最新數據庫服務器版本8.1.0,其中變化最大的是MySQL采用了新的版本發布模型。本文是官方博客的中文摘抄和個人理解,原文更精彩: https://blogs.oracle.com/mysql/post/introducing-mysql-innovation-and-longterm-su…

網絡原理(JavaEE初階系列11)

目錄 前言: 1.網絡原理的理解 2.應用層 2.1自定義協議的約定 2.1.1確定要傳輸的信息 2.1.2確定數據的格式 3.傳輸層 3.1UDP 3.1.1UDP報文格式 3.2TCP 3.2.1確認應答 3.2.2超時重傳 3.2.3連接管理 3.2.3.1三次握手 3.2.3.2四次揮手 3.2.4滑動窗口 3.…

bigemap如何添加mapbox地圖?

第一步 打開瀏覽器,找到你要訪問的地圖的URL地址,并且確認可以正常在瀏覽器中訪問;瀏覽器中不能訪問,同樣也不能在軟件中訪問。 以下為常用地圖源地址: 天地圖: http://map.tianditu.gov.cn 包含&…

【SA8295P 源碼分析】75 - QNX GVM Secpol 安全策略文件 gvm_la.txt 內容分析解讀

【SA8295P 源碼分析】75 - QNX GVM Secpol 安全策略文件 gvm_la.txt 內容分析解讀 第一部分、gvm_la_t secpol 類型定義第二部分、gvm_la_t 內存透傳相關配置第三部分、gvm_la_t 中斷透傳相關配置第四部分、gvm_la_t 類型的進程允許通信的所有 secpol 類型系列文章匯總見:《【…

字符串的綜合練習

1、練習-轉換羅馬數字 鍵盤錄入一個字符串 要求1:長度為小于等于9 要求2:只能是數字 將內容變成羅馬數字 下面是阿拉伯數字跟羅馬數字的對比關系: Ⅰ-1 Ⅱ-2 Ⅲ-3 Ⅳ-4 Ⅴ-5 Ⅵ-6 Ⅶ-7 Ⅷ-8 Ⅸ-9 注意點:羅馬數字里面沒有0的&…

51單片機的管腳介紹

圖文介紹 純文字說明 單片機管腳相關結構及其作用如下 電源正極引腳 一般接5V電源,為單片機提供正常工作時的電壓。 電源負極引腳 接地。然后才開始工作。 時鐘引腳 18、19腳為時鐘引腳(XTAL2、XTAL1)。單片機內部有大量的數字電路&a…

SringBoot-響應

響應數據 如何加載響應數據呢 其實在SpringBoot,已經有名為RessponseBody的方法注解為我們提供的響應的方法,他的作用是將方法返回值直接響應,如果返回值類型為實體對象/集合,則會轉換為JSON格式響應。 而RestController已經在內…

Java真實面試題,offer已到手

關于學習 在黑馬程序員剛剛開始的時候學習盡頭非常足,到后面逐漸失去了一些興趣,以至于后面上課會出現走神等問題,但是畢業時后悔晚矣。等到開始學習項目一的時候,思路總會比別人慢一些,不看講義寫不出來代碼。 建議…