簡體   English   中英

FFT 圖像的 IFFT 導致原始圖像奇怪的倒置重疊

[英]IFFT of FFT-image results in weird upside-down overlap of original image

在下面的代碼中,我有一個函數,它返回裁剪到某個半徑的中心圓的圖像。 然后我對圖像進行傅立葉變換,再次逆傅立葉變換,以恢復圖像,效果很好。

然后我計算出,半徑為 43 的能量譜(此處不包括)的中心圓將產生原始圖像能量的 99%。 但是當我嘗試將我的函數“imgRadius”應用於幅度譜(傅立葉變換圖像),然后對該圖像執行傅立葉逆變換時,我得到了原始圖像的這種奇怪的倒置重疊。

def imgRadius(img, radius):
    result = np.zeros(img.shape,np.float64)
    centerX = (img.shape[0])/2
    centerY = (img.shape[1])/2
    for m in range(img.shape[0]):
        for n in range(img.shape[1]):
            if math.sqrt((m-centerX)**2+(n-centerY)**2) < radius:
                result[m,n] = img[m,n]
    return result

imgpath = directory+"NorbertWiener.JPG"
img = cv.imread(imgpath, cv.IMREAD_GRAYSCALE)
norm_image = cv.normalize(img, None, alpha=0, beta=1, norm_type=cv.NORM_MINMAX, dtype=cv.CV_32F)
amp = (np.fft.fftshift(np.fft.fft2(norm_image)))
amp_log = np.log(np.abs(amp))
norm_amp = cv.normalize(amp_log, None, alpha=0, beta=1, norm_type=cv.NORM_MINMAX, dtype=cv.CV_32F)
restoredAMP = np.abs(np.fft.ifft2(np.fft.ifftshift(amp)))
radamp = imgRadius(norm_amp,43)
rest99 = np.abs(np.fft.ifft2((imgRadius(amp,43))))

plt.subplot(231),plt.imshow(norm_image, "gray", vmin=0, vmax=1),plt.title('Image')
plt.xticks([]), plt.yticks([])
plt.subplot(232),plt.imshow(norm_amp, "gray", vmin=0, vmax=1),plt.title('Amplitude')
plt.xticks([]), plt.yticks([])
plt.subplot(233),plt.imshow(restoredAMP, "gray", vmin=0, vmax=1),plt.title('Restored from amplitude')
plt.xticks([]), plt.yticks([])
plt.subplot(235),plt.imshow(rest99, "gray", vmin=0, vmax=1),plt.title('Restored from r=43')
plt.xticks([]), plt.yticks([])
plt.subplot(234),plt.imshow(radamp, "gray", vmin=0, vmax=1),plt.title('Amplitude r=43')
plt.xticks([]), plt.yticks([])
plt.show()

在此處查看生成的子圖

它與我使用絕對值的事實有什么關系嗎? 我不明白我應該如何在不去除圖像的虛部的情況下繪制圖像,但我可以看到一些信息如何在逆 fft 中丟失。

我只是不明白為什么在原始幅度譜上執行 IFFT 時我沒有遇到問題。

丟棄 FFT 的虛部(以及實部的符號)正是導致倒置圖像“回折”到自身的問題所在。 一個關於其原點對稱的函數的 FFT 是實數(即虛部 0)。 通過丟棄虛部,圖像因此以某種方式“對稱化”。

在傅里葉空間對復數FFT結果進行運算后,可以進行逆FFT,然后只繪制它的實部np.fft.ifft2((imgRadius(amp,43))).real

以下在 Python/OpenCV/Numpy 中對我有用,並顯示了使用尖銳邊界圓和通過高斯模糊平滑以減輕振鈴偽影的區別

輸入:

在此處輸入圖片說明

import numpy as np
import cv2

# read input and convert to grayscale
img = cv2.imread('lena_gray.png', cv2.IMREAD_GRAYSCALE)

# do dft saving as complex output
dft = np.fft.fft2(img)

# apply shift of origin to center of image
dft_shift = np.fft.fftshift(dft)

# generate spectrum from magnitude image (for viewing only)
mag = np.abs(dft_shift)
spec = np.log(mag) / 20

# create circle mask
radius = 32
mask = np.zeros_like(img)
cy = mask.shape[0] // 2
cx = mask.shape[1] // 2
cv2.circle(mask, (cx,cy), radius, (255,255,255), -1)[0]

# blur the mask
mask2 = cv2.GaussianBlur(mask, (19,19), 0)

# apply mask to dft_shift
dft_shift_masked = np.multiply(dft_shift,mask) / 255
dft_shift_masked2 = np.multiply(dft_shift,mask2) / 255


# shift origin from center to upper left corner
back_ishift = np.fft.ifftshift(dft_shift)
back_ishift_masked = np.fft.ifftshift(dft_shift_masked)
back_ishift_masked2 = np.fft.ifftshift(dft_shift_masked2)


# do idft saving as complex output
img_back = np.fft.ifft2(back_ishift)
img_filtered = np.fft.ifft2(back_ishift_masked)
img_filtered2 = np.fft.ifft2(back_ishift_masked2)

# combine complex components to form original image again
img_back = np.abs(img_back).clip(0,255).astype(np.uint8)
img_filtered = np.abs(img_filtered).clip(0,255).astype(np.uint8)
img_filtered2 = np.abs(img_filtered2).clip(0,255).astype(np.uint8)


cv2.imshow("ORIGINAL", img)
cv2.imshow("SPECTRUM", spec)
cv2.imshow("MASK", mask)
cv2.imshow("MASK2", mask2)
cv2.imshow("ORIGINAL DFT/IFT ROUND TRIP", img_back)
cv2.imshow("FILTERED DFT/IFT ROUND TRIP", img_filtered)
cv2.imshow("FILTERED2 DFT/IFT ROUND TRIP", img_filtered2)
cv2.waitKey(0)
cv2.destroyAllWindows()

# write result to disk
cv2.imwrite("lena_dft_numpy_mask.png", mask)
cv2.imwrite("lena_dft_numpy_mask_blurred.png", mask2)
cv2.imwrite("lena_dft_numpy_roundtrip.png", img_back)
cv2.imwrite("lena_dft_numpy_lowpass_filtered1.png", img_filtered)
cv2.imwrite("lena_dft_numpy_lowpass_filtered2.png", img_filtered2)


鋒利的面具:

在此處輸入圖片說明

模糊蒙版:

在此處輸入圖片說明

簡單往返:

在此處輸入圖片說明

來自銳利掩模的低通濾波結果(振鈴明顯):

在此處輸入圖片說明

模糊蒙版的低通濾波結果(減輕了振鈴):

在此處輸入圖片說明

問題發生在這里:

def imgRadius(img, radius):
    result = np.zeros(img.shape,np.float64)

您正在創建一個實數值數組,並復制復數值。 可能將實數分量或幅度寫入數組。 在任何情況下,復值頻域數據都變為實值。 逆變換是一個對稱矩陣。

為了解決這個問題,將result初始化為復數值數組。

在此之后,確保使用逆變換的實部分量,而不是幅度,正如Gianluca 在他們的回答中已經建議的那樣

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM