介绍
本程序是使用数学软件Maple中的ImageTools和SignalProcessing实现混合图像的效果。
混合图像是指将一张图片的低频与另一张图片的高频相结合的图片。根据观看距离的不同,所得到的图像有两种解释:
- 近距离看(或者放大图片的大小)是阿尔伯特·爱因斯坦
- 远距离看(或者减小图片的大小)是玛丽莲·梦露
为了实现这一效果,您必须实现低通和高通滤波操作来应用于您选择的两幅图像,并线性组合过滤后的图像,得到具有所需的两种解释的混合图像,最后将只有低频信息的图片和只有高频信息的图像叠加在一起。
• 对于图像的低频部分:可以理解为图像的“轮廓”,比如一幅画的线条等
• 对于图像的高频部分:可以理解为图像的“细节”,比如一幅画的颜色搭配,颜色深度等
创建混合图像的过程如下:
这个概念是在2006年的论文中提出的。论文提出混合图像是基于人类视觉系统对图像的多尺度处理,由视觉掩蔽研究驱动的。这些图像可用于创建引人注目的显示,其中图像在不同的距离有不同的感知。通过滤波分离图像的高频和低频,将不同图像的高频和低频合并以创建相关尺度的图像。
A. Oliva, A. Torralba, P.G. Schyns (2006). Hybrid Images. ACM Transactions on Graphics, ACM Siggraph, 25-3, 527-530.
https://www.researchgate.net/publication/220184425_Hybrid_images
当我们观察附近的物体或者放大混合图像时,可以看到精细的细节,即高频信息。相反地,当我们远距离观察物体或者缩小图片时,大的轮廓占据主导,这时候我们我们就更倾向于识别低频的部分。
程序
restart: #重启内存
with(ImageTools): #加载图像工具函数包
with(SignalProcessing): #加载信号处理函数包
fft_shift := proc(M) #proc() ... end proc: 是过程程序定义
local nRows, nCols, quad_1, quad_2, quad_3, quad_4, cRows, cCols; #局部变量声明
nRows, nCols := LinearAlgebra:-Dimensions(M): #Dimensions函数是求矩阵M的行数和列数,赋值给变量nRows和cCols
cRows, cCols := ceil(nRows/2), ceil(nCols/2): #ceil获取大于等于行数和列数一半的最小整数
quad_1 := M[1..cRows, 1..cCols]: #取矩阵M的1~cRows行,1~cCols列
quad_2 := M[1..cRows, cCols + 1..-1]: #取矩阵M的1~cRows行,cCols~最后一列
quad_3 := M[cRows + 1..-1, cCols + 1..-1]: #取矩阵M的cRows+1~最后一行(序数是-1),cCols+1~最后一列
quad_4 := M[cRows + 1..-1, 1..cCols]: #取矩阵M的cRows+1~最后一行(序数是-1),1~cCols列
return <<quad_3, quad_2 |quad_4, quad_1>>: #重组并返回矩阵
end proc: #结束proc
PowerSpectrum2D := proc(M) #功率谱函数
return sqrt~(abs~(M)) # ~是映射命令,将函数sqrt映射给矩阵的所有项,abs~是指对矩阵所有项求绝对值
end proc:
gaussian_filter := (a, b, sigma) -> Matrix(2 * a, 2 * b, (i, j) -> evalf(exp(-((i - a)^2 + (j - b)^2) / (2 * sigma^2))), datatype = float[8]):
#定义一个高斯滤波器函数,-> 是函数定义算子
注:Maple中命令行写代码时如果要换行,快捷键是 Shift + Enter健
fft_shift() 是交换二维傅里叶变换的象限,让零频率分量位于中心。
gaussian_filter() 是一个函数,在频域中应用高通或低通滤波器,其中a和b是二维傅里叶变换中的行数和列数,sigma是截止频率。
输入和显示图像
einstein_img := Read("this:///einstein.png")[..,..,1]: #用ImageTools:-Read命令读入
Embed(einstein_img)
marilyn_img := Read("this:///marilyn.png")[..,..,1]:
Embed(marilyn_img)
变换图像到傅里叶域(空间频域)
Maple中的SignalProcessing:-FFT可以计算矩阵的傅里叶变换。
with(SignalProcessing); FFT()
einstein_fourier := fft_shift(FFT(einstein_img)):
monroe_fourier := fft_shift(FFT(marilyn_img)):
查看未过滤图像的功率谱。低频数据靠近中心,而高频数据远离中心.
Embed(Create(PowerSpectrum2D(einstein_fourier)))
Embed(Create(PowerSpectrum2D(monroe_fourier)))
使用低通和高通滤波器过滤图像
定义高通和低通滤波器的截止频率:
sigma_einstein := 25:
sigma_monroe := 10:
在频域,对Einstein图像的傅里叶变换应用高通滤波,对Monroe图像应用低通滤波。
nRows, nCols := LinearAlgebra:-Dimension(einstein_img):
#调用LinearAlgebra函数包中的Dimension命令求图像对应的矩阵einstein_img的行列数
einstein_fourier_high_pass := einstein_fourier *~ (1 -~ gaussian_filter(nRows/2, nCols/2, sigma_einstein)):
# *~是对后面数据对象中的所有项应用相乘*运算;-~表示对后面矩阵中的所有数据项应用"减"算子
monroe_fourier_low_pass := monroe_fourier *~ gaussian_filter(nRows/2, nCols/2, sigma_monroe):
过滤后的图像的功率谱。
Embed(Create(PowerSpectrum2D(einstein_fourier_high_pass)))
Embed(Create(PowerSpectrum2D(monroe_fourier_low_pass)))
在合成两个过滤处理后的图像前,我们分别看下图像转换到空间域后是什么样子。
einstein_high_pass_img := Re~(InverseFFT(fft_shift(einstein_fourier_high_pass))):
monroe_low_pass_img := Re~(InverseFFT(fft_shift(monroe_fourier_low_pass))):
Embed(FitIntensity(Create(einstein_high_pass_img)))
#图像保留了细节
Embed(FitIntensity(Create(monroe_low_pass_img)))
#图像有点模糊,只是保留了较低的空间频率数据
合成两个滤波傅里叶转换后的图像并转换到空间域
hybrid_image := Create(Re~(InverseFFT(fft_shift(monroe_fourier_low_pass + einstein_fourier_high_pass)))):
Embed(hybrid_image);
#InverseFFT是快速傅里叶逆变换
#Re是取复数的实部
#ImageTools:-Create是创建一个图像
Maple文件下载:https://pan.baidu.com/s/1kUJ_lG6UcQqQgi-XG2IKyQ?pwd=u1fo