当前位置: 首页 > news >正文

频域滤波中默认的边界条件——补零与不补零(答作者问)

这个问题源自于Rafael Gonzalez的《数字图像处理》中的这幅图,为什么他频域滤波要将图像零延拓到二倍尺寸?

完全没有没要,既浪费计算,又浪费空间。
在这里插入图片描述
注:图(d)错误,见这里。
这个他给的解释,并没有从理论高度做解释。
在这里插入图片描述

三个基础知识

卷积边界延拓的方式

在这里插入图片描述

离散傅里叶变换的周期性

在这里插入图片描述

线性卷积和循环卷积等效的条件

在这里插入图片描述

离散傅里叶变换的卷积定理

循环卷积对应于离散傅里叶变换的乘积,即离散傅里叶变换的卷积定理。

如果 X ( k ) = D F T { x ( n ) } X(k) = DFT\{x(n)\} X(k)=DFT{x(n)} Y ( k ) = D F T { y ( n ) } Y(k) = DFT\{y(n)\} Y(k)=DFT{y(n)},那么

X ( k ) Y ( k ) = D F T { { x ( n ) } ⊛ { y ( n ) } } X(k)Y(k) = DFT\{\{x(n)\} \circledast \{y(n)\}\} X(k)Y(k)=DFT{{x(n)}{y(n)}}

这里, ⊛ \circledast 表示由下式定义的循环卷积:

{ x ( n ) } ⊛ { y ( n ) } = ∑ m = 0 N − 1 x ( m ) y ( ( n − m ) m o d N ) . \{x(n)\} \circledast \{y(n)\} = \sum_{m=0}^{N-1} x(m)y((n-m) \mod N). {x(n)}{y(n)}=m=0N1x(m)y((nm)modN).

y ( ( n − m ) m o d N ) y((n-m) \mod N) y((nm)modN)表示循环移位。

Conventional Shift

在这里插入图片描述

Circular Shift

在这里插入图片描述

线性卷积是这样的, h ( − n ) h(-n) h(n)移位,计算与 f ( n ) f(n) f(n)对位相乘再求和,一直下去就是线性卷积的结果 g ( n ) g(n) g(n)
在这里插入图片描述
然而,不幸的是,离散傅里叶变换的周期性造成时域是循环卷积。某人优点很突出,缺点也很突出,我很欣赏他的优点,怎么办呢?那只能解决掉他的缺点。

零延拓,补零的边界条件

循环卷积没办法了,那就想办法让循环卷积与线性卷积等价,于是就有了零延拓。对信号补零到线性卷积结果的长度。图中虽然循环移位,但是由于信号 f ( n ) f(n) f(n)补零了,对应的那两个点就是零,相乘也是零。换句话说就是把位置给留出来。这样仍然是线性卷积的结果。
在这里插入图片描述

由于是线性卷积,那默认的边界延拓方式就是零延拓。看图说话,相当于 f ( n ) f(n) f(n)补零后周期延拓, h ( − n ) h(-n) h(n)移位,那就是零延拓的线性卷积。
在这里插入图片描述

看图像的结果,这里看不出大小。

在这里插入图片描述
因为fft2本身可以做任意点的傅里叶变换,所以无需提前延拓,也就没显示。
在这里插入图片描述
在这里插入图片描述

空域滤波器,频域实现。

blurtype = 'gaussian';
sigma = 2;
hsize = 2 * ceil(3 * sigma) + 1;
psf_gauss = fspecial('gaussian', hsize, sigma);
offset = floor(size(psf_gauss)/2);
S = size(Img) + size(psf_gauss) - 1;
F = fft2(Img, S(1), S(2));
H = fft2(psf_gauss, S(1), S(2));G=F.* H;
g=im2uint8(real(ifft2(G)));

那Gonzalez为什么要补零为二倍呢?这是由于他在频域直接对模拟滤波器采样为 M × N M\times N M×N点,对应的空域就是 M × N M\times N M×N点(频域滤波器不这样设计,很离谱,暂且不论)。所以为了不产生混叠,延拓的图像尺寸至少是 ( 2 M − 1 ) × ( 2 N − 1 ) (2M-1)\times (2N-1) (2M1)×(2N1)。他的大错不少,小错不断,他认为是 2 M × 2 N 2M \times 2N 2M×2N也就见怪不怪了。

频域滤波器

在这里插入图片描述

filename = 'cameraman';
suffix = '.tif';
Img = im2double(im2gray(imread([filename, suffix])));
[M,N]=size(Img);
D0 = 0.15;
[U,V] = freqspace([2*M 2*N],'meshgrid');
d = sqrt(U.^2+V.^2);
H = exp(-(d/(2*D0.^2)));F = fftshift(fft2(Img,2*M,2*N));
G = F.* H;
g=im2uint8(real(ifft2(ifftshift(G))));

不补零,周期延拓的边界条件

回头再看不零延拓的话,会怎么样?头部数据混叠,尾部数据丢失。
在这里插入图片描述
但是图像处理的滤波通常是考虑same size的结果,可以先做循环移位。
在这里插入图片描述

在这里插入图片描述
与线性卷积的结果比较,中间的五个值是相同的,这是因为边界受周期延拓影响了。

>> gcgc =1.4641    1.5738    0.9545    0.5790    0.3512    0.2130    0.8149
>> gg =0.7071    1.4289    1.5738    0.9545    0.5790    0.3512    0.2130    0.1078    0.0352

所以MATLAB提出了psf2otf函数,先做循环移位,再计算离散傅里叶变换。如果有空域的卷积核,通过这个函数实现频域滤波。相当于周期延拓的边界条件。

空域滤波器,频域实现。

在这里插入图片描述

[M,N]=size(Img);
F = fft2(Img,M,N);blurtype = 'gaussian';
sigma = 2;
hsize = 2 * ceil(3 * sigma) + 1;
offset = (hsize-1)/2;
psf_gauss = fspecial('gaussian', hsize, sigma);
H = psf2otf(psf_gauss, [M,N]); %这里使用fft2就会产生错误,很多刊物这里有误。
G=F.*H;
g=im2uint8(real(ifft2(G)));

注意psf2otf的地方。

频域滤波器

在这里插入图片描述

[M,N]=size(Img);
D0 = 0.3;
[U,V] = freqspace([M N],'meshgrid');
d = sqrt(U.^2+V.^2);
H = exp(-(d/(2*D0.^2)));F = fftshift(fft2(Img));
G = F.* H;g=im2uint8(real(ifft2(ifftshift(G))));

结论

完全没有必要延拓,可以对原图像尺寸的频率直接频域滤波或者频域实现,就是相当于周期延拓。本来空域也有这样的延拓方式,而且我觉得比零延拓的效果好。


http://www.mrgr.cn/news/79846.html

相关文章:

  • 活动预告 |【Part1】Microsoft Azure 在线技术公开课:使用 Microsoft Fabric 实现数据湖仓
  • C++ webrtc开发(非原生开发,linux上使用libdatachannel库)
  • 知识图谱9:知识图谱的展示
  • SQL Server:只有MDF文件,如何附加数据库
  • WebRTC Simulcast 大小流介绍与优化实践
  • 高效利用资源:分布式有状态服务的高可靠性设计
  • 电脑怎么设置通电自动开机(工控机)
  • OpenMMlab导出MaskFormer/Mask2Former模型并用onnxruntime和tensorrt推理
  • 【实现多网卡电脑的网络连接共享】
  • Edge SCDN的独特优势有哪些?
  • 简单的多网卡选择指定网卡ip注册
  • 数据仓库工具箱—读书笔记01(数据仓库、商业智能及维度建模初步)
  • 善于运用指针--函数与指针
  • 《机器学习》2.4假设检验 t分布 F分布
  • 光伏电站建设成本利润估算
  • Playwright中Page类的方法
  • Android 第三方框架:RxJava:源码分析:责任链模式
  • 【学习笔记】目前市面中手持激光雷达设备及参数汇总
  • 信奥题解:Recamán 序列
  • 100 模数与数模转换器
  • 51c深度学习~合集9
  • Visual Studio的解决方案管理器怎么从文件夹视图切换回原视图——最后一根稻草
  • 从小学题到技术选型哲学:以智能客服系统为例,解读相关AI技术栈20241211
  • Python基础笔记17--面向对象(其他)
  • C++ 中 std::array<int, array_size> 与 std::vector<int> 的深入对比
  • Scala的隐式对象