首页 > 解决方案 > FFT频谱中的0是白色的?,为什么?- OpenCV

问题描述

在此处输入图像描述

该图像代表了我在 openCV 练习中使用傅里叶变换所做的事情。这是一个消除周期性噪声的练习。我正在检测产生噪音的波段,并用面具将其删除。正如你所看到的,我正在dft_shift用面具做产品。我假设它的乘积为0,我的问题是:如果该值为0,为什么那条线是白色的???

代码:

dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT)    #calcula la transf. Fourier 
dft_shift = np.fft.fftshift(dft) #proyecta los cuadrantes de la imagen 
dft_shift = dft_shift*mask2
f_ishift = np.fft.ifftshift(dft_shift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])

完整的脚本在这里

标签: pythonnumpyopencv

解决方案


解决方案

如果您打印出product图像数组中的值,您会发现白色条带中的所有像素实际上的值都是-inf,而不是0。在您的代码中,作为创建过程的一部分,product您可以使用np.log重新调整某些数据。该数据中有0',结果np.log(0)-inf

您可以通过几种不同的方式解决此问题。最简单的选择是将所有-infproduct替换为0. 创建后product,如果添加以下行:

product[np.isneginf(product)] = 0

那么当您绘制product它时,它将有黑色条带,就像您预期的那样:

在此处输入图像描述

深潜

这就是您最终以-infin结尾的原因product。这是您的代码中创建的行product

product = 20*np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))

如果我们把它分成两行,我们可以弄清楚发生了什么:

magnitude = cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1])
product = 20*np.log(magnitude)

magnitude像你预期的那样0在乐队中。但是,如果您尝试直接绘制震级,您最终会得到一个非常暗且显示不多的图:

在此处输入图像描述

这样做的原因是 Matplotlib 会在选择颜色时缩放您的数据,以便图像数组中的最小值为黑色,最大值为白色。这里的问题是 in 中的最大值magnitude远大于几乎所有其他值。因此,您会得到几个白色像素(靠近中心),而其他每个像素都被染成几乎黑色。

您可以通过传递给用于绘制图像的函数来使绘图magnitude显示更多的底层细节。这为颜色图设置了一个明确的最大数据值:vmax=1000imshow

在此处输入图像描述

这远非理想,因为这意味着图像的很大一部分显示为完全饱和的白色,而不管其底层细节如何。

实际上,您已经在代码中为这个问题提供了更好的解决方案:您在magnitudeusing中重新调整数据np.log。这种重新缩放的结果,product数组,将使其所有值更接近。这有利于您在绘图时看到图像中的精细细节product。但是,您在这里遇到的问题是 0 的日志是无穷大的:

print(np.log(0))
# this outputs
# -inf

因此, in 的带成为in0的带。Matplotlib通过将它们着色为与输入数组中的最大值相同的颜色(即白色)来处理这些值。因此,您会得到您在绘制的图像中看到的白色带。magnitude-infproduct-infproduct


推荐阅读