Answers:
我只会回答第一个问题:图像中的频率是多少?
傅里叶变换是一种数学技术,其中,不是针对每个像素分别表示相同的图像信息,而是针对每个频率表示相同的图像信息。这样想吧。海中有海浪,有些浪潮非常缓慢(如潮汐),有些浪中等大小,还有一些浪很微小,如阵风形成的涟漪。您可以将它们视为三个独立的波浪,但是在海面的每个点和某个时刻,您只能得到一个高度的水。
这同样适用于图像。您可以想到图像是由各种波或频率组成的。要创建图像,请从平均颜色开始(实际上考虑灰度图像比较容易)。然后添加不同波长和强度的波,以缓慢建立图片中的细节。
源图像:
第一频率(平均):
沿垂直方向的第二个频率是一个波,在图像的底部从零开始,然后上升,沿着中心水平线再次变为零,然后降到零以下,最后在图像的顶部变为零。(我描述了没有相移的傅立叶级数,但是这种类比仍然成立。)
在这里您可以看到沿水平和垂直方向的第二个频率。请注意,您可以确定山将在哪里(黑暗)以及天空和湖泊将在何处(更亮)。
第二频率:
每增加一个波或每个频率都会带来更多的纹波,从而带来更多细节。为了获得不同的图像,可以更改波高/波幅以及波的起点(也称为相位)。
第三频率:
有趣的是,此表示形式中的信息量相同,并且可以在正常图像(空间域)和傅立叶变换图像(频域)之间来回移动。在频域中,我们需要保留所有频率的信息以及幅度和相位信息。
这是使用50%的频率:
所有这些都有变体,在傅立叶级数,傅立叶变换和离散傅立叶变换以及离散余弦变换(DCT)之间有所区别。
一种有趣的应用是使用诸如JPEG之类的压缩算法。在这里,DCT用于保存图像的更多重要部分(低频)和更少的高频。
我写这篇文章是希望新手读者可以对傅立叶变换的概念有一个基本的了解。为此,我做了一些简化,希望更多的高级读者能原谅我。
Thomas Devoogdt生成的视频可以在Vimeo上观看。
有许多方法依赖于频率进行后期处理,主要是因为我们从不单独查看单个像素。许多算法都在频率上起作用,因为以这种方式考虑它们更自然。而且由于傅里叶变换包含相同的信息,我们可以在频域和空间域中表达任何数学运算(或后处理步骤)!有时逐像素描述更好,但频率描述通常更好。(在这种情况下,更好的主要意思是更快。)
我想指出的一种技术没有特别的原因,除了它是艺术家直接使用频率工作外,这就是“频率分离”。我不会描述它,但是您可以看到它在Photoshop和GIMP上如何在YouTube上运行。
您创建了两层,一层是低频,一层是高频。对于人像,您可以在高频下进行皮肤平滑处理,而不会影响低频下的肤色。
这是一些生成以上示例的代码。它可以作为简单的Python程序运行。
from PIL import Image
from numpy.fft import rfft2, irfft2
import numpy as np
def save_dims(ft, low, high, name):
ft2 = np.zeros_like(ft)
# copy the frequencies from low to high but all others stay zero.
ft2[low:high, low:high] = ft[low:high, low:high]
save(ft2, name)
def save(ft, name):
rft = irfft2(ft)
img = Image.fromarray(rft)
img = img.convert('L')
img.save(name)
def main():
# Convert input into grayscale and save.
img = Image.open("input.jpg")
img = img.convert('L')
img.save('input_gray.png')
# Do Fourier Transform on image.
ft = rfft2(img)
# Take only zeroth frequency and do Inverse FT and save.
save_dims(ft, 0, 1, 'output_0.png')
# Take first two frequencies in both directions.
save_dims(ft, 0, 2, 'output_1.png')
save_dims(ft, 0, 3, 'output_2.png')
# Take first 50% of frequencies.
x = min(ft.shape)
save_dims(ft, 0, x/2, 'output_50p.png')
def generateGif():
''' Generates images to be later converted to a gif.
This requires ImageMagick:
convert -delay 100 -loop 0 output_*.png animation.gif
'''
# Requires images2gif from code.google.com/p/visvis/source/browse/vvmovie/images2gif.py
# from images2gif import writeGif
img = Image.open('input.jpg')
img = img.convert('L')
# Resize image before any calculation.
size = (640,480)
img.thumbnail(size, Image.ANTIALIAS)
ft = rfft2(img)
images = []
for x in range(0, max(ft.shape)):
ft2 = np.zeros_like(ft)
ft2[0:x, 0:x] = ft[0:x,0:x]
rft = irfft2(ft2)
img_out = Image.fromarray(rft).convert('L')
fname = 'animation/output_%05d.jpg' %(x, )
img_out.save(fname, quality=60, optimize=True)
#writeGif('animation.gif', images, duration=0.2)
if __name__=='__main__':
main()
#generateGif()
我将尝试用最简单的数学术语进行解释。如果您想跳过数学,请跳至第二部分,如果您想获得简短答案,请跳至第三部分
第一部分
信号的频率是指每单位时间重复事件的发生次数。因此,如果时间单位是秒,则频率用赫兹(Herz)测量:1Hz = 1 / s。因此,具有100Hz的信号具有每秒重复100次的模式。
从信号处理的角度来看,最基本的信号是正弦信号。
y(t)= sin(2πft)
其中f是此窦信号的频率,t是时间。如果此信号是声音且f约为50Hz,您将听到一个非常低的低音。如果频率较高,例如15kHz,则音调会更高。
现在概括一下这个概念,该信号可以是空间信号,而不是时间信号……就好像您在一张纸上画出正弦波一样,x轴指向右侧,y轴垂直到x轴
y(x)= sin(2πfx)
其中,f是信号的频率,x是空间变量。f在这里不再以1 / s进行测量,而是1 /(空间单位)。
法国数学家傅立叶(Fourier)表示,您可以通过添加许多具有不同幅度和频率的正弦和余弦信号来生成任何信号。那就是所谓的傅立叶分析。
使用傅立叶分析,可以将任何函数y(x)写为具有不同频率的正弦和余弦信号之和,因此可以根据与频率Y(f)相关的几个函数来重写函数y(x)。可以说y(x)= Some_Function(Y(f))。或Y(f)= Reverse_of_Some_Function(y(x))
傅立叶变换是将信号从x域转换到频域的函数F。
Y(f) = F( y(x) )
y(x) = F_inv(Y(f))
F是一个模拟函数,离散傅立叶变换DFT是F的数值近似值。快速傅立叶变换FFT是一种针对速度进行DFT优化的方法。
好...
第二部分
现在,计算机图像由像素组成,并且每个像素都具有红色,绿色,蓝色(即RGB)值的强度值。在灰度图像中,任何像素的R,G,B的强度都相等,R = G = B = I,因此我们可以说灰度图像的I。
下面的800px X 100px灰度图片是使用I(x)= sin(2πfx)生成的,其中f = 1重复/ 800px = 0.00125重复/ px
您可以使用Python3自己生成
from PIL import Image, ImageDraw
from math import sin, pi
img = Image.new('RGB', (800,100), color='black')
draw = ImageDraw.draw(img)
#cacluate the frequency
n = 10 #repetitions
f = n/img.width #
#iterate of the width pixels
for x in range(img.width):
#calculate the intensity i in that pixel x
y = sin(2*pi*f*x - pi/2) #this will generate values between -1 and +1, -pi/2 is to make sure that i starts with value 0 in the next line.
i = (255+255*y)/2 #shifting and scaling y so that the values are between 0 and 255
draw.line((i,0,i,img.height), fill=(int(i),int(i),int(i)))
img.show()
下面的800px X 100px灰度图片是使用I(x)= sin(2πfx)生成的,其中f = 10个重复/ 800px = 0.0125个重复/ px
现在很容易看到该图像的水平频率为10。让我们将频率增加10倍,以使n =100。f = 100/800 = 1/8 = 0.125个重复/像素:
如前所述,您可以将任何信号(一维灰度图像)表示为具有不同频率的正弦信号(一维灰度正弦图像)的总和系列。
第三部分
因此,如果A具有“更精细”的细节,则一维灰度图像A的频率要高于另一个灰度图像B的频率。
您可以将该原理推广到彩色2D甚至3D图像。图像的“细节”越精细,该图像的频率含量就越高。
因此,与花朵的图像相比,蓝天的频率较低。
您可以通过阅读有关傅里叶分析和数字图像处理的知识来了解更多。
简而言之,频率是指变化率。更准确地说,频率是变化周期的倒数,即从一种亮度(或其他任何一种)循环到另一种亮度并再次返回所需的时间。然后变化越快(例如,从亮到暗),表示图像的那部分所需的视觉“频率”就越高。
换句话说,您可以将图像中的频率视为变化率。从一种颜色快速变化为另一种颜色的图像部分(例如,锐利边缘)包含高频,而逐渐变化的部分(例如具有纯色的大表面)仅包含低频。
当我们谈论DCT和FFT以及其他类似的转换时,通常是在图像的一部分上进行处理(例如,用于JPEG压缩,边缘检测等)。然后,在给定大小的转换块的背景下讨论转换是最有意义的。
想象一下,如果您愿意,则是一个32像素x 32像素的图像数据块。(此数字是任意的。)假设图像是一个简单的渐变,左侧为白色,中间为黑色,右侧为白色。我们可以说该信号的周期大约是每32个像素宽度一个波长,因为它每32个像素又经历一个从白色到黑色再到白色的完整周期。
我们可以随意地将此频率称为“ 1”,即每32个像素1个周期。我隐约记得在转换教科书中通常将其称为θ或θ/ 2,但我可能会记错了。无论哪种方式,我们现在将其称为1,因为从绝对意义上讲,这确实是任意的。重要的是相对意义上的频率之间的关系。:-)
假设您的第二个图像在一侧边缘处为白色,然后以两倍快的速度褪色,以使其在另一侧边缘处从白色变为黑色,从白色变为黑色,然后再次变为白色。然后,我们将该频率称为“ 2”,因为它在该32像素块的宽度上变化的频率是其两倍。
如果我们想复制那些简单的图像,我们可以从字面上说每一行都包含一个频率为1或2的信号,您将知道图像的外观。如果图像从黑色变为灰色的50%,则可以执行相同的操作,但是您必须说图像的频率为1或2,强度为50%。
当然,现实世界中的图像不仅仅是简单的渐变。当您从左向右扫描时,图像会频繁而不定期地更改。但是,在足够小的块内(例如8个像素,16个像素),您可以将该像素行近似为一系列信号的总和,从该行中像素值的平均值开始,然后是“混入频率为0.5“的信号(一侧为黑色,逐渐变为白色)(或负值,减去该信号的数量),然后混入频率1,频率2,频率4,依此类推。
现在图像是独特的,因为它在两个方向上都有频率。在水平和垂直方向移动时,它会变得越来越亮。因此,我们使用2D DCT或FFT变换代替1D。但是原理仍然基本相同。您可以使用大小相似的存储桶的8x8网格精确地表示8x8图像。
由于颜色的缘故,图像也更加复杂,但是我们暂时将其忽略,并假设我们只查看单个灰度图像,因为您可能会通过单独查看照片的红色通道来获得灰度图像。
至于如何读取转换结果,这取决于您要查看的是1D转换还是2D转换。对于一维变换,您需要一系列的仓。第一个是所有输入值的平均值。第二个是要添加的频率1信号的数量,第三个是要添加的频率2信号的数量,依此类推。
对于2D变换,您具有一个n x n的值网格。左上角通常是平均值,当您沿水平方向移动时,每个存储桶都包含要混合的信号量,其水平频率为1、2、4等,而当您沿垂直方向移动时,它会是要与垂直频率为1、2、4等混合的信号量。
当然,如果您正在谈论DCT,那就是完整的故事。相比之下,FFT的每个bin包含实部和虚部。FFT仍然基于相同的基本思想(某种),不同之处在于频率映射到bin的方式不同并且数学难度更大。:-)
当然,生成此类转换的最常见原因是再走一步,将一些数据丢弃。例如,DCT用于JPEG压缩。通过从左上方(平均值)开始向左下方(以平均值的形式)读取锯齿形的值,首先记录最重要的数据(平均值和低频信息),然后逐渐记录高频数据。在某些时候,您基本上会说“这足够好”并丢弃最高频率的数据。通过丢弃精细细节可以从本质上使图像平滑,但仍然可以为您提供大约正确的图像。
在IIRC中,FFT有时也用于边缘检测,在这里您将除高频分量之外的所有噪声都丢弃了,以检测锐利边缘的高对比度区域。
National Instruments有一篇很好的文章,用图片对此进行了解释。:-)