在傅里叶域中用核对图像进行卷积

2025-03-26 09:09:00
admin
原创
24
摘要:问题描述:我在图像和卷积核周围使用零填充,将它们转换为傅立叶域,然后将它们反转回来以获得卷积图像,请参阅下面的代码。然而,结果是错误的。我本来期望得到模糊的图像,但输出是四个移位的四分之一。为什么输出是错误的,我该如何修复代码?输入图像:卷积结果:from PIL import Image,ImageDraw...

问题描述:

我在图像和卷积核周围使用零填充,将它们转换为傅立叶域,然后将它们反转回来以获得卷积图像,请参阅下面的代码。然而,结果是错误的。我本来期望得到模糊的图像,但输出是四个移位的四分之一。为什么输出是错误的,我该如何修复代码?

输入图像:

输入图像

卷积结果:

输出图像

from PIL import Image,ImageDraw,ImageOps,ImageFilter
import numpy as np 
from scipy import fftpack
from copy import deepcopy
import imageio
## STEP 1 ##
im1=Image.open("pika.jpeg")
im1=ImageOps.grayscale(im1)
im1.show()
print("s",im1.size)
## working on this image array
im_W=np.array(im1).T
print("before",im_W.shape)
if(im_W.shape[0]%2==0):
im_W=np.pad(im_W, ((1,0),(0,0)), 'constant')
if(im_W.shape[1]%2==0):
im_W=np.pad(im_W, ((0,0),(1,0)), 'constant')
print("after",im_W.shape)
Boxblur=np.array([[1/9,1/9,1/9],[1/9,1/9,1/9],[1/9,1/9,1/9]])
dim=Boxblur.shape[0]

##padding before frequency domain multipication
pad_size=(Boxblur.shape[0]-1)/2
pad_size=int(pad_size)
##padded the image(starts here)

p_im=np.pad(im_W, ((pad_size,pad_size),(pad_size,pad_size)), 'constant')
t_b=(p_im.shape[0]-dim)/2
l_r=(p_im.shape[1]-dim)/2
t_b=int(t_b)
l_r=int(l_r)

##padded the image(ends here)

## padded the kernel(starts here)
k_im=np.pad(Boxblur, ((t_b,t_b),(l_r,l_r)), 'constant')
print("hjhj",k_im)
print("kernel",k_im.shape)

##fourier transforms image and kernel
fft_im = fftpack.fftshift(fftpack.fft2(p_im))
fft_k  = fftpack.fftshift(fftpack.fft2(k_im))
con_in_f=fft_im*fft_k
ifft2 = abs(fftpack.ifft2(fftpack.ifftshift(con_in_f)))
convolved=(np.log(abs(ifft2))* 255 / np.amax(np.log(abs(ifft2)))).astype(np.uint8)
final=Image.fromarray(convolved.T)
final.show()
u=im1.filter(ImageFilter.Kernel((3,3), [1/9,1/9,1/9,1/9,1/9,1/9,1/9,1/9,1/9], scale=None, offset=0))
u.show()

解决方案 1:

离散傅里叶变换 (DFT) 以及扩展的 FFT(计算 DFT)的原点位于输入和输出的第一个元素(对于图像,即左上角的像素)中。这就是我们经常在输出上使用该函数的原因fftshift以便将原点移到我们更熟悉的位置(图像中间)。

这意味着我们需要将 3x3 均匀加权模糊核转换为如下所示的样子,然后再将其传递给 FFT 函数:

1/9  1/9  0  0  ... 0  1/9
1/9  1/9  0  0  ... 0  1/9
  0    0  0  0  ... 0    0
...  ...               ...
  0    0  0  0  ... 0    0
1/9  1/9  0  0  ... 0  1/9

也就是说,内核的中间(其原点)位于图像的左上角,中间左上方的像素环绕并出现在图像的右端和底端。

我们可以使用ifftshift填充后应用于内核的函数来实现这一点。填充内核时,我们需要注意原点(内核中间)位于k_im.shape // 2内核图像内的位置(整数除法)k_im。最初原点位于[3,3]//2 == [1,1]。通常,我们匹配的图像大小是均匀的,例如[256,256]。那里的原点将位于[256,256]//2 == [128,128]。这意味着我们需要在左侧和右侧(以及底部和顶部)填充不同的量。我们需要小心计算这个填充:

sz = img.shape  # the sizes we're matching
kernel = np.ones((3,3)) / 9
sz = (sz[0] - kernel.shape[0], sz[1] - kernel.shape[1])  # total amount of padding
kernel = np.pad(kernel, (((sz[0]+1)//2, sz[0]//2), ((sz[1]+1)//2, sz[1]//2)), 'constant')
kernel = fftpack.ifftshift(kernel)

请注意,输入图像img不需要填充(尽管如果您想强制执行 FFT 更便宜的尺寸,您可以这样做)。fftshift在乘法之前也不需要对 FFT 的结果应用,然后在之后立即反转此移位,这些移位是多余的。您fftshift只应在要显示傅立叶域图像时使用。最后,对过滤后的图像应用对数缩放是错误的。

生成的代码是(我使用 pyplot 进行显示,根本不使用 PIL):

import numpy as np
from scipy import misc
from scipy import fftpack
import matplotlib.pyplot as plt

img = misc.face()[:,:,0]

kernel = np.ones((3,3)) / 9
sz = (img.shape[0] - kernel.shape[0], img.shape[1] - kernel.shape[1])  # total amount of padding
kernel = np.pad(kernel, (((sz[0]+1)//2, sz[0]//2), ((sz[1]+1)//2, sz[1]//2)), 'constant')
kernel = fftpack.ifftshift(kernel)

filtered = np.real(fftpack.ifft2(fftpack.fft2(img) * fftpack.fft2(kernel)))
plt.imshow(filtered, vmin=0, vmax=255)
plt.show()

请注意,我取的是逆 FFT 的实部。虚部应该只包含非常接近零的值,这是计算中的舍入误差的结果。取绝对值虽然很常见,但却是不正确的。例如,您可能想要将过滤器应用于包含负值的图像,或者应用产生负值的过滤器。在这里取绝对值会产生伪影。如果逆 FFT 的输出包含明显不同于零的虚值,则过滤内核的填充方式存在错误。

还要注意,这里的内核很小,因此模糊效果也很小。为了更好地看到模糊效果,请制作一个更大的内核,例如np.ones((7,7)) / 49

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2482  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1533  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   0  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   0  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用