当前位置:  开发笔记 > 编程语言 > 正文

使用Python在图像上进行FFT

如何解决《使用Python在图像上进行FFT》经验,为你挑选了1个好方法。

我在Python中使用FFT实现了一个问题.我有完全奇怪的结果.好吧,我想打开图像,获取RGB中每个像素的值,然后我需要在它上面使用fft,然后再次转换为图像.

我的步骤:

1)我正在使用Python中的PIL库打开图像

from PIL import Image
im = Image.open("test.png")

2)我得到了像素

pixels = list(im.getdata())

3)我将每个像素分成r,g,b值

for x in range(width):
    for y in range(height):
        r,g,b = pixels[x*width+y]
        red[x][y] = r
        green[x][y] = g
        blue[x][y] = b

4).我们假设我有一个像素(111,111,111).并在所有红色值上使用fft

red = np.fft.fft(red)

然后:

print (red[0][0], green[0][0], blue[0][0])

我的输出是:

(53866+0j) 111 111

我认为这是完全错误的.我的图像是64x64,而来自gimp的FFT完全不同.实际上,我的FFT只给出了具有巨大值的数组,这就是为什么我的输出图像是黑色的.

你知道问题出在哪里吗?

[编辑]

我按照建议改变了

red= np.fft.fft2(red)

然后我扩展它

scale = 1/(width*height)
red= abs(red* scale)

而且,我只得到黑色图像.

[EDIT2]

好的,让我们拍一张照片. test.png

假设我不想打开它并保存为灰度图像.所以我这样做.

def getGray(pixel):
    r,g,b = pixel
    return (r+g+b)/3  

im = Image.open("test.png")
im.load()

pixels = list(im.getdata())
width, height = im.size
for x in range(width):
    for y in range(height):
        greyscale[x][y] = getGray(pixels[x*width+y])  

data = []
for x in range(width):
     for y in range(height):
         pix = greyscale[x][y]
         data.append(pix)

img = Image.new("L", (width,height), "white")
img.putdata(data)
img.save('out.png')

在此之后,我得到了这张照片 灰阶,没关系.所以现在,我想在我将它保存到新图像之前对我的图像进行fft,所以我就是这样做的

scale = 1/(width*height)
greyscale = np.fft.fft2(greyscale)
greyscale = abs(greyscale * scale)

加载后.保存到文件后,我有坏FFT.所以让我们现在尝试使用gimp打开test.png并使用FFT过滤器插件.我收到这张图片,这是正确的好的FFT

我该怎么办呢?



1> Ahmed Fasih..:

好问题.我从来没有听说过它,但Gimp Fourier插件似乎很整洁:

一个简单的插件,可以对您的图像进行傅立叶变换.这个插件的主要优点是能够在GIMP中使用转换后的图像.您可以在傅立叶空间中绘制或应用滤波器,并使用逆FFT获得修改后的图像.

这个想法 - 对频域数据进行Gimp风格的操作并转换回图像 - 非常酷!尽管多年来使用FFT,但我从未考虑过这样做.不要乱用Gimp插件和C可执行文件和丑陋,让我们用Python做到这一点!

警告.我尝试了很多方法来做到这一点,试图从原始输入图像中获得接近输出Gimp Fourier图像(带有莫尔图案的灰色)的东西,但我根本不能.Gimp图像在图像中间看起来有些对称,但它不是垂直或水平翻转,也不是转置对称的.我希望插件能够使用真正的2D FFT将H×W图像转换为频域中的实数值数据的H×W阵列,在这种情况下,不存在对称性(它只是 - 对于像图像这样的实值输入,它是共轭对称的复数FFT.所以我放弃了尝试逆向工程Gimp插件正在做什么,看看我是如何从头开始做的.

代码.非常简单:读取图像,应用scipy.fftpack.rfft前两个维度获得"频率图像",重新缩放到0-255,然后保存.

请注意这与其他答案有何不同!没有灰度 - 2D实际到FFT在所有三个通道上独立发生.没有abs必要:频域的图像可以合法拥有负值,如果你让他们积极的,你无法恢复原始图像.(也是一个很好的功能:图像尺寸没有妥协.无论宽度/高度是偶数还是奇数,数组的大小在FFT之前和之后都保持不变.)

from PIL import Image
import numpy as np
import scipy.fftpack as fp

## Functions to go from image to frequency-image and back
im2freq = lambda data: fp.rfft(fp.rfft(data, axis=0),
                               axis=1)
freq2im = lambda f: fp.irfft(fp.irfft(f, axis=1),
                             axis=0)

## Read in data file and transform
data = np.array(Image.open('test.png'))

freq = im2freq(data)
back = freq2im(freq)
# Make sure the forward and backward transforms work!
assert(np.allclose(data, back))

## Helper functions to rescale a frequency-image to [0, 255] and save
remmax = lambda x: x/x.max()
remmin = lambda x: x - np.amin(x, axis=(0,1), keepdims=True)
touint8 = lambda x: (remmax(remmin(x))*(256-1e-4)).astype(int)

def arr2im(data, fname):
    out = Image.new('RGB', data.shape[1::-1])
    out.putdata(map(tuple, data.reshape(-1, 3)))
    out.save(fname)

arr2im(touint8(freq), 'freq.png')

(旁白:FFT-lover geek note.请查看文档以rfft获取详细信息,但我使用了Scipy的FFTPACK模块,因为它将rfft单个像素的实部和虚部交错为两个相邻的实数值,保证了任意大小的2D图像的输出(即使是奇数,宽度与高度)也将被保留.这与Numpy相反numpy.fft.rfft2,因为它返回大小width/2+1的复杂数据height/2+1,迫使你处理一个额外的行/列并处理复杂到真实的自我交织谁需要为这个应用程序麻烦.)

结果.给定输入命名test.png:

测试输入

此代码段产生以下输出(全局最小值/最大值已重新调整并量化为0-255):

测试输出,频域

并升级:

频率,升级

在此频率图像中,DC(0 Hz频率)分量位于左上角,频率随着向右和向下移动而变高.

现在,让我们看看当您以几种方式操作此图像时会发生什么.而不是这个测试图像,让我们使用猫照片.

原始的猫

我在Gimp中制作了一些掩模图像,然后我加载到Python中并将频率图像相乘以查看蒙版对图像的影响.

这是代码:

# Make frequency-image of cat photo
freq = im2freq(np.array(Image.open('cat.jpg')))

# Load three frequency-domain masks (DSP "filters")
bpfMask = np.array(Image.open('cat-mask-bpfcorner.png')).astype(float) / 255
hpfMask = np.array(Image.open('cat-mask-hpfcorner.png')).astype(float) / 255
lpfMask = np.array(Image.open('cat-mask-corner.png')).astype(float) / 255

# Apply each filter and save the output
arr2im(touint8(freq2im(freq * bpfMask)), 'cat-bpf.png')
arr2im(touint8(freq2im(freq * hpfMask)), 'cat-hpf.png')
arr2im(touint8(freq2im(freq * lpfMask)), 'cat-lpf.png')

这是左侧的低通滤镜掩码,右侧是结果单击以查看完整分辨率图像:

低过的猫

在掩模中,黑色= 0.0,白色= 1.0.所以最低频率保持在这里(白色),而高频率被阻挡(黑色).这通过衰减高频来模糊图像.低通滤波器遍布整个地方,包括在对图像进行抽取("下采样")时(尽管它们的形状比我在Gimp中绘制的要小得多).

这是一个带通滤波器,其中保留了最低频率(见左上角的白色位?)和高频,但中频频率被阻挡.相当奇怪!

带通猫

这是一个高通滤波器,上面掩模中左上角的左上角被涂黑:

高通滤波器

这就是边缘检测的工作原理.

后记.有人,使用这种技术制作一个webapp,让你绘制蒙版并将它们实时应用到图像中!


该网站允许您自定义蒙版并将其应用于图像.http://bigwww.epfl.ch/demo/ip/demos/03-FFT-filtering/
@CristianArteaga,它现在位于http://bigwww.epfl.ch/demo/ip/demos/FFT-filtering/--非常酷,感谢您分享链接!
推荐阅读
保佑欣疼你的芯疼
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有