为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用opencv python对具有大小的DFT进行反演

如何使用opencv python对具有大小的DFT进行反演

慕仙森 2022-07-12 14:51:44
我对这一切都很陌生,我想从图像中获取幅度谱,然后从修改后的幅度谱中重建图像。但现在我得到了一个非常暗的重建。import numpy as npimport cv2from matplotlib import pyplot as pltimg = cv2.imread('IMG.jpg',0)dft = cv2.dft(np.float32(img),flags = cv2.DFT_COMPLEX_OUTPUT)dft_shift = np.fft.fftshift(dft)m, a = np.log(cv2.cartToPolar(dft_shift[:,:,0],dft_shift[:,:,1]))# do somthing with mx, y = cv2.polarToCart(np.exp(m), a)back = cv2.merge([x, y])f_ishift = np.fft.ifftshift(back)img_back = cv2.idft(f_ishift)img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])plt.subplot(131),plt.imshow(img, cmap = 'gray')plt.title('Input Image'), plt.xticks([]), plt.yticks([])plt.subplot(132),plt.imshow(m, cmap = 'gray')plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])plt.subplot(133),plt.imshow(img_back, cmap = 'gray')plt.title('result'), plt.xticks([]), plt.yticks([])plt.show()结果你们能帮我弄清楚为什么这么黑吗?预先感谢 :)
查看完整描述

3 回答

?
暮色呼如

TA贡献1853条经验 获得超9个赞

您应该在不应用日志的情况下从 cartToPolar() 中提取幅度和相位图像。然后单独进行日志仅查看频谱,保持原始形式的幅度。然后在进行逆 dft 之前根据需要修改原始幅度。

其他问题之一是往返图像需要重新调整为 8 位范围和数据类型。我用 cv2.normalize() 来做到这一点。您可以从打印的最小值和最大值中看到这种需求。

以下是如何在 Python/OpenCV 中进行 dft、获取光谱然后进行逆 dft。我从彩色图像开始,但在读取它时将其转换为灰度。最终返回的往返 dft/idft 仍将是灰度。

输入:

https://i.stack.imgur.com/QP2Nd.png

import numpy as np

import cv2


# read input as grayscale

img = cv2.imread('lena.png', 0)


# convert image to floats and do dft saving as complex output

dft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT)


# apply shift of origin from upper left corner to center of image

dft_shift = np.fft.fftshift(dft)


# extract magnitude and phase images

mag, phase = cv2.cartToPolar(dft_shift[:,:,0], dft_shift[:,:,1])


# get spectrum for viewing only

spec = np.log(mag) / 30


# convert magnitude and phase into cartesian real and imaginary components

real, imag = cv2.polarToCart(mag, phase)


# combine cartesian components into one complex image

back = cv2.merge([real, imag])


# shift origin from center to upper left corner

back_ishift = np.fft.ifftshift(back)


# do idft saving as complex output

img_back = cv2.idft(back_ishift)


# combine complex components into original image again

img_back = cv2.magnitude(img_back[:,:,0], img_back[:,:,1])


# re-normalize to 8-bits

min, max = np.amin(img_back, (0,1)), np.amax(img_back, (0,1))

print(min,max)

img_back = cv2.normalize(img_back, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)


cv2.imshow("ORIGINAL", img)

cv2.imshow("MAG", mag)

cv2.imshow("PHASE", phase)

cv2.imshow("SPECTRUM", spec)

cv2.imshow("REAL", real)

cv2.imshow("IMAGINARY", imag)

cv2.imshow("ORIGINAL DFT/IFT ROUND TRIP", img_back)

cv2.waitKey(0)

cv2.destroyAllWindows()


# write result to disk

cv2.imwrite("lena_dft_ift_opencv.png", img_back)


结果:

https://i.stack.imgur.com/qiv4k.png

查看完整回答
反对 回复 2022-07-12
?
小唯快跑啊

TA贡献1863条经验 获得超2个赞

以下是如何使用 Python/OpenCV 在傅里叶域中使用陷波滤波从图像中去除重复的图案噪声

  • 阅读图片

  • 做 DFT

  • 从实部和虚部生成幅度和相位分量

  • 从幅度创建频谱

  • 对光谱图像进行阈值化,以在阈值化图像的中心用黑色覆盖 DC 区域

  • 将蒙版应用于幅度

  • 结合新的幅度和原始相位

  • 将它们转换为实部和虚部

  • 做 IDFT

  • 保存结果

带有重复图案噪声的输入:

https://i.stack.imgur.com/eE9xK.jpg

import numpy as np

import cv2


# read input as grayscale

img = cv2.imread('clown.jpg', 0)


# get min and max values of img

img_min, img_max = np.amin(img, (0,1)), np.amax(img, (0,1))

print(img_min,img_max)


# convert image to floats and do dft saving as complex output

dft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT)


# apply shift of origin from upper left corner to center of image

dft_shift = np.fft.fftshift(dft)


# extract magnitude and phase images

mag, phase = cv2.cartToPolar(dft_shift[:,:,0], dft_shift[:,:,1])


# get spectrum

spec = np.log(mag) / 20


# create mask from spectrum keeping only the brightest spots as the notches

mask = cv2.normalize(spec, None, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX)

mask = cv2.threshold(mask, 0.65, 1, cv2.THRESH_BINARY)[1]


# dilate mask

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))

mask = cv2.morphologyEx(mask, cv2.MORPH_DILATE, kernel)


# cover center DC component by circle of black leaving only a few white spots on black background

xcenter = mask.shape[1] // 2

ycenter = mask.shape[0] // 2

mask = cv2.circle(mask, (xcenter,ycenter), radius=10, color=0, thickness=cv2.FILLED)


# apply mask to magnitude such that magnitude is made zero where mask is one, ie at spots

mag[mask!=0] = 0


# convert new magnitude and old phase into cartesian real and imaginary components

real, imag = cv2.polarToCart(mag, phase)


# combine cartesian components into one complex image

back = cv2.merge([real, imag])


# shift origin from center to upper left corner

back_ishift = np.fft.ifftshift(back)


# do idft saving as complex output

img_back = cv2.idft(back_ishift)


# combine complex components into original image again

img_back = cv2.magnitude(img_back[:,:,0], img_back[:,:,1])


# re-normalize to 8-bits in range of original

min, max = np.amin(img_back, (0,1)), np.amax(img_back, (0,1))

print(min,max)

notched = cv2.normalize(img_back, None, alpha=img_min, beta=img_max, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)


cv2.imshow("ORIGINAL", img)

cv2.imshow("MAG", mag)

cv2.imshow("PHASE", phase)

cv2.imshow("SPECTRUM", spec)

cv2.imshow("MASK", mask)

cv2.imshow("NOTCHED", notched)

cv2.waitKey(0)

cv2.destroyAllWindows()


# write result to disk

cv2.imwrite("clown_mask.png", (255*mask).clip(0,255).astype(np.uint8))

cv2.imwrite("clown_notched.png", notched)


光谱:

https://i.stack.imgur.com/FbBfD.png

面具:

https://i.stack.imgur.com/3Mfcn.png

陷波过滤结果(去除噪声):

https://i.stack.imgur.com/HdajF.png

动画(使用 Imagemagick 单独创建):

https://i.stack.imgur.com/DpLWM.gif



查看完整回答
反对 回复 2022-07-12
?
天涯尽头无女友

TA贡献1831条经验 获得超9个赞

如果您需要通过将幅度提高到接近 1 的幂(称为系数求根或 alpha 求根)来修改幅度,那么这只是使用 Python/OpenCV 对我上面的代码进行的简单修改。在将幅度和相位转换回实部和虚部之前,只需添加 cv2.pow(mag, 1.1)。

输入:

//img1.sycdn.imooc.com//62cd1a3b0001afab02450255.jpg

import numpy as np

import cv2


# read input as grayscale

img = cv2.imread('lena.png', 0)


# convert image to floats and do dft saving as complex output

dft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT)


# apply shift of origin from upper left corner to center of image

dft_shift = np.fft.fftshift(dft)


# extract magnitude and phase images

mag, phase = cv2.cartToPolar(dft_shift[:,:,0], dft_shift[:,:,1])


# get spectrum for viewing only

spec = np.log(mag) / 30


# NEW CODE HERE: raise mag to some power near 1

# values larger than 1 increase contrast; values smaller than 1 decrease contrast

mag = cv2.pow(mag, 1.1)


# convert magnitude and phase into cartesian real and imaginary components

real, imag = cv2.polarToCart(mag, phase)


# combine cartesian components into one complex image

back = cv2.merge([real, imag])


# shift origin from center to upper left corner

back_ishift = np.fft.ifftshift(back)


# do idft saving as complex output

img_back = cv2.idft(back_ishift)


# combine complex components into original image again

img_back = cv2.magnitude(img_back[:,:,0], img_back[:,:,1])


# re-normalize to 8-bits

min, max = np.amin(img_back, (0,1)), np.amax(img_back, (0,1))

print(min,max)

img_back = cv2.normalize(img_back, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)


cv2.imshow("ORIGINAL", img)

cv2.imshow("MAG", mag)

cv2.imshow("PHASE", phase)

cv2.imshow("SPECTRUM", spec)

cv2.imshow("REAL", real)

cv2.imshow("IMAGINARY", imag)

cv2.imshow("COEF ROOT", img_back)

cv2.waitKey(0)

cv2.destroyAllWindows()


# write result to disk

cv2.imwrite("lena_grayscale_opencv.png", img)

cv2.imwrite("lena_grayscale_coefroot_opencv.png", img_back)

原始灰度

https://i.stack.imgur.com/DaJ6S.png

系数生根结果:

https://i.stack.imgur.com/l8S55.png

这是显示差异的动画(使用 ImageMagick 创建):

https://i.stack.imgur.com/KSCFD.gif

查看完整回答
反对 回复 2022-07-12
  • 3 回答
  • 0 关注
  • 153 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信