-
暮色呼如
您应该在不应用日志的情况下从 cartToPolar() 中提取幅度和相位图像。然后单独进行日志仅查看频谱,保持原始形式的幅度。然后在进行逆 dft 之前根据需要修改原始幅度。其他问题之一是往返图像需要重新调整为 8 位范围和数据类型。我用 cv2.normalize() 来做到这一点。您可以从打印的最小值和最大值中看到这种需求。以下是如何在 Python/OpenCV 中进行 dft、获取光谱然后进行逆 dft。我从彩色图像开始,但在读取它时将其转换为灰度。最终返回的往返 dft/idft 仍将是灰度。输入:https://i.stack.imgur.com/QP2Nd.pngimport numpy as npimport cv2# read input as grayscaleimg = cv2.imread('lena.png', 0)# convert image to floats and do dft saving as complex outputdft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT)# apply shift of origin from upper left corner to center of imagedft_shift = np.fft.fftshift(dft)# extract magnitude and phase imagesmag, phase = cv2.cartToPolar(dft_shift[:,:,0], dft_shift[:,:,1])# get spectrum for viewing onlyspec = np.log(mag) / 30# convert magnitude and phase into cartesian real and imaginary componentsreal, imag = cv2.polarToCart(mag, phase)# combine cartesian components into one complex imageback = cv2.merge([real, imag])# shift origin from center to upper left cornerback_ishift = np.fft.ifftshift(back)# do idft saving as complex outputimg_back = cv2.idft(back_ishift)# combine complex components into original image againimg_back = cv2.magnitude(img_back[:,:,0], img_back[:,:,1])# re-normalize to 8-bitsmin, 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 diskcv2.imwrite("lena_dft_ift_opencv.png", img_back)结果:https://i.stack.imgur.com/qiv4k.png
-
小唯快跑啊
以下是如何使用 Python/OpenCV 在傅里叶域中使用陷波滤波从图像中去除重复的图案噪声阅读图片做 DFT从实部和虚部生成幅度和相位分量从幅度创建频谱对光谱图像进行阈值化,以在阈值化图像的中心用黑色覆盖 DC 区域将蒙版应用于幅度结合新的幅度和原始相位将它们转换为实部和虚部做 IDFT保存结果带有重复图案噪声的输入:https://i.stack.imgur.com/eE9xK.jpg import numpy as npimport cv2# read input as grayscaleimg = cv2.imread('clown.jpg', 0)# get min and max values of imgimg_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 outputdft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT)# apply shift of origin from upper left corner to center of imagedft_shift = np.fft.fftshift(dft)# extract magnitude and phase imagesmag, phase = cv2.cartToPolar(dft_shift[:,:,0], dft_shift[:,:,1])# get spectrumspec = np.log(mag) / 20# create mask from spectrum keeping only the brightest spots as the notchesmask = 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 maskkernel = 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 backgroundxcenter = mask.shape[1] // 2ycenter = mask.shape[0] // 2mask = 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 spotsmag[mask!=0] = 0# convert new magnitude and old phase into cartesian real and imaginary componentsreal, imag = cv2.polarToCart(mag, phase)# combine cartesian components into one complex imageback = cv2.merge([real, imag])# shift origin from center to upper left cornerback_ishift = np.fft.ifftshift(back)# do idft saving as complex outputimg_back = cv2.idft(back_ishift)# combine complex components into original image againimg_back = cv2.magnitude(img_back[:,:,0], img_back[:,:,1])# re-normalize to 8-bits in range of originalmin, 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 diskcv2.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
-
天涯尽头无女友
如果您需要通过将幅度提高到接近 1 的幂(称为系数求根或 alpha 求根)来修改幅度,那么这只是使用 Python/OpenCV 对我上面的代码进行的简单修改。在将幅度和相位转换回实部和虚部之前,只需添加 cv2.pow(mag, 1.1)。输入:import numpy as npimport cv2# read input as grayscaleimg = cv2.imread('lena.png', 0)# convert image to floats and do dft saving as complex outputdft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT)# apply shift of origin from upper left corner to center of imagedft_shift = np.fft.fftshift(dft)# extract magnitude and phase imagesmag, phase = cv2.cartToPolar(dft_shift[:,:,0], dft_shift[:,:,1])# get spectrum for viewing onlyspec = 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 contrastmag = cv2.pow(mag, 1.1)# convert magnitude and phase into cartesian real and imaginary componentsreal, imag = cv2.polarToCart(mag, phase)# combine cartesian components into one complex imageback = cv2.merge([real, imag])# shift origin from center to upper left cornerback_ishift = np.fft.ifftshift(back)# do idft saving as complex outputimg_back = cv2.idft(back_ishift)# combine complex components into original image againimg_back = cv2.magnitude(img_back[:,:,0], img_back[:,:,1])# re-normalize to 8-bitsmin, 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 diskcv2.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