news 2026/4/3 6:13:13

汉宁窗与汉明窗:原理、公式与代码实现剖析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
汉宁窗与汉明窗:原理、公式与代码实现剖析

汉宁窗与汉明窗:原理、公式与代码实现剖析

一、为什么需要窗函数?——频谱泄漏的深度解析

1. 频谱泄漏的原理

想象你在听一首歌,但只截取了其中的一小段,然后想用FFT分析它的频率。问题来了:你截断的这段音乐在时域上是突然开始和结束的,这相当于在时域上乘以一个矩形窗。

频谱泄漏的数学原理

  • 假设原始信号为x(t)=Acos⁡(2πf0t)x(t) = A\cos(2\pi f_0 t)x(t)=Acos(2πf0t)
  • 时域截断后:x′(t)=x(t)⋅rect(t/T)x'(t) = x(t) \cdot \text{rect}(t/T)x(t)=x(t)rect(t/T)
  • 在频域:X′(f)=X(f)∗rect(f)=X(f)∗sinc(fT)X'(f) = X(f) * \text{rect}(f) = X(f) * \text{sinc}(fT)X(f)=X(f)rect(f)=X(f)sinc(fT)
  • 矩形窗的频谱是sinc函数,有主瓣和旁瓣,导致原信号的频谱被"扩散"

频谱泄漏示意图

原信号频谱: |-----| (理想正弦波) | | 矩形窗频谱: |-----|-----|-----|... (sinc函数) | | | | 卷积后频谱: |-----|-----|-----|... (频谱泄漏) | | | |

2. 窗函数的解决方案

窗函数通过在信号两端逐渐减小振幅,使信号"平滑地消失",从而减少频谱泄漏。

  • 理想窗函数:主瓣窄(频率分辨率高),旁瓣低(泄漏小)
  • 实际权衡:没有完美窗函数,需要在主瓣宽度和旁瓣高度之间权衡

二、汉宁窗(Hanning Window)的详细剖析

1. 数学原理与公式

汉宁窗的定义
w(n)=0.5⋅[1−cos⁡(2πnN−1)],0≤n≤N−1w(n) = 0.5 \cdot \left[1 - \cos\left(\frac{2\pi n}{N-1}\right)\right], \quad 0 \leq n \leq N-1w(n)=0.5[1cos(N12πn)],0nN1

推导过程
汉宁窗是升余弦窗的一个特例,可以看作是3个矩形时间窗的频谱之和:
w(n)=13rect(nN)∗rect(nN)∗rect(nN)w(n) = \frac{1}{3} \text{rect}\left(\frac{n}{N}\right) * \text{rect}\left(\frac{n}{N}\right) * \text{rect}\left(\frac{n}{N}\right)w(n)=31rect(Nn)rect(Nn)rect(Nn)
或者说是3个sinc(t)型函数之和,而括号中的两项相对于第一个谱窗向左、右各移动了π/T,从而使旁瓣互相抵消。

2. 时域特性

  • 时域形状:两端触零的平滑钟形曲线
  • 端点值w(0)=w(N−1)=0w(0) = w(N-1) = 0w(0)=w(N1)=0
  • 中心点w((N−1)/2)=1w((N-1)/2) = 1w((N1)/2)=1
  • 对称性:关于中心对称

3. 频域特性

特性数值说明
主瓣宽度1.2π/N比矩形窗宽约2.5倍
第一旁瓣-31dB旁瓣最高点的幅度
旁瓣衰减速度-60dB/10oct每十倍频程衰减60dB
旁瓣最大值-31dB与主瓣的相对幅度

4. 代码实现

Python实现
importnumpyasnpimportmatplotlib.pyplotaspltdefhanning_window(N):"""生成汉宁窗"""n=np.arange(N)window=0.5*(1-np.cos(2*np.pi*n/(N-1)))returnwindow# 生成长度为64的汉宁窗N=64hanning=hanning_window(N)# 绘制时域波形plt.figure(figsize=(10,6))plt.plot(hanning,'b-',linewidth=2)plt.title('Hanning Window (N=64)')plt.xlabel('Sample Index')plt.ylabel('Amplitude')plt.grid(True)plt.show()# 计算频谱hanning_fft=np.fft.fft(hanning,1024)hanning_fft=np.fft.fftshift(hanning_fft)freq=np.fft.fftfreq(1024,1.0/N)freq=np.fft.fftshift(freq)# 绘制频谱plt.figure(figsize=(10,6))plt.plot(freq,20*np.log10(np.abs(hanning_fft)),'r-')plt.title('Frequency Response of Hanning Window')plt.xlabel('Frequency (Normalized)')plt.ylabel('Magnitude (dB)')plt.grid(True)plt.show()
Matlab实现
% 生成汉宁窗N=64;n=0:N-1;hanning=0.5*(1-cos(2*pi*n/(N-1)));% 绘制时域波形figure;plot(hanning,'b-','LineWidth',2);title(['Hanning Window (N=',num2str(N),')']);xlabel('Sample Index');ylabel('Amplitude');grid on;% 计算频谱hanning_fft=fft(hanning,1024);hanning_fft=fftshift(hanning_fft);freq=(0:1023)/1024-0.5;freq=freq*(2*pi);% Normalize frequency% 绘制频谱figure;plot(freq,20*log10(abs(hanning_fft)),'r-','LineWidth',2);title('Frequency Response of Hanning Window');xlabel('Frequency (Normalized)');ylabel('Magnitude (dB)');grid on;
C++实现
#include<iostream>#include<vector>#include<cmath>#include<fstream>std::vector<double>hanningWindow(intN){std::vector<double>window(N);for(intn=0;n<N;++n){window[n]=0.5*(1-cos(2*M_PI*n/(N-1)));}returnwindow;}voidsaveWindowToFile(conststd::vector<double>&window,conststd::string&filename){std::ofstreamfile(filename);for(doubleval:window){file<<val<<"\n";}file.close();}intmain(){intN=64;std::vector<double>window=hanningWindow(N);saveWindowToFile(window,"hanning_window.txt");std::cout<<"Hanning window of length "<<N<<" generated and saved to hanning_window.txt"<<std::endl;return0;}

三、汉明窗(Hamming Window)的详细剖析

1. 数学原理与公式

汉明窗的定义
w(n)=0.54−0.46⋅cos⁡(2πnN−1),0≤n≤N−1w(n) = 0.54 - 0.46 \cdot \cos\left(\frac{2\pi n}{N-1}\right), \quad 0 \leq n \leq N-1w(n)=0.540.46cos(N12πn),0nN1

为什么是0.54和0.46?

  • 这些系数是通过优化得到的,使得窗函数的频谱中第一个旁瓣的幅度达到最小。
  • 通过微调系数,可以使得第一旁瓣的幅度从-31dB降低到-42dB。

2. 时域特性

  • 时域形状:两端不触零的平顶钟形曲线
  • 端点值w(0)=w(N−1)=0.54w(0) = w(N-1) = 0.54w(0)=w(N1)=0.54
  • 中心点w((N−1)/2)=1w((N-1)/2) = 1w((N1)/2)=1
  • 对称性:关于中心对称

3. 频域特性

特性数值说明
主瓣宽度1.3π/N比汉宁窗略宽
第一旁瓣-42dB旁瓣最高点的幅度
旁瓣衰减速度-20dB/10oct比汉宁窗慢
旁瓣最大值-42dB与主瓣的相对幅度

4. 代码实现

Python实现
importnumpyasnpimportmatplotlib.pyplotaspltdefhamming_window(N):"""生成汉明窗"""n=np.arange(N)window=0.54-0.46*np.cos(2*np.pi*n/(N-1))returnwindow# 生成长度为64的汉明窗N=64hamming=hamming_window(N)# 绘制时域波形plt.figure(figsize=(10,6))plt.plot(hamming,'b-',linewidth=2)plt.title('Hamming Window (N=64)')plt.xlabel('Sample Index')plt.ylabel('Amplitude')plt.grid(True)plt.show()# 计算频谱hamming_fft=np.fft.fft(hamming,1024)hamming_fft=np.fft.fftshift(hamming_fft)freq=np.fft.fftfreq(1024,1.0/N)freq=np.fft.fftshift(freq)# 绘制频谱plt.figure(figsize=(10,6))plt.plot(freq,20*np.log10(np.abs(hamming_fft)),'r-')plt.title('Frequency Response of Hamming Window')plt.xlabel('Frequency (Normalized)')plt.ylabel('Magnitude (dB)')plt.grid(True)plt.show()
Matlab实现
% 生成汉明窗N=64;n=0:N-1;hamming=0.54-0.46*cos(2*pi*n/(N-1));% 绘制时域波形figure;plot(hamming,'b-','LineWidth',2);title(['Hamming Window (N=',num2str(N),')']);xlabel('Sample Index');ylabel('Amplitude');grid on;% 计算频谱hamming_fft=fft(hamming,1024);hamming_fft=fftshift(hamming_fft);freq=(0:1023)/1024-0.5;freq=freq*(2*pi);% Normalize frequency% 绘制频谱figure;plot(freq,20*log10(abs(hamming_fft)),'r-','LineWidth',2);title('Frequency Response of Hamming Window');xlabel('Frequency (Normalized)');ylabel('Magnitude (dB)');grid on;
C++实现
#include<iostream>#include<vector>#include<cmath>#include<fstream>std::vector<double>hammingWindow(intN){std::vector<double>window(N);for(intn=0;n<N;++n){window[n]=0.54-0.46*cos(2*M_PI*n/(N-1));}returnwindow;}voidsaveWindowToFile(conststd::vector<double>&window,conststd::string&filename){std::ofstreamfile(filename);for(doubleval:window){file<<val<<"\n";}file.close();}intmain(){intN=64;std::vector<double>window=hammingWindow(N);saveWindowToFile(window,"hamming_window.txt");std::cout<<"Hamming window of length "<<N<<" generated and saved to hamming_window.txt"<<std::endl;return0;}

四、汉宁窗 vs 汉明窗:深度对比

1. 数学公式对比

窗函数公式系数
汉宁窗w(n)=0.5⋅[1−cos⁡(2πn/(N−1))]w(n) = 0.5 \cdot [1 - \cos(2\pi n/(N-1))]w(n)=0.5[1cos(2πn/(N1))]0.5, 0.5
汉明窗w(n)=0.54−0.46⋅cos⁡(2πn/(N−1))w(n) = 0.54 - 0.46 \cdot \cos(2\pi n/(N-1))w(n)=0.540.46cos(2πn/(N1))0.54, 0.46

2. 时域特性对比

特性汉宁窗汉明窗
端点值00.54
中心值11
两端形状触零不触零
时域形状钟形曲线平顶钟形

3. 频域特性对比

特性汉宁窗汉明窗
第一旁瓣-31dB-42dB
旁瓣衰减速度-60dB/10oct-20dB/10oct
主瓣宽度1.2π/N1.3π/N
适用场景通用场景语音信号处理

4. 代码实现对比

# 汉宁窗实现defhanning_window(N):return0.5*(1-np.cos(2*np.pi*np.arange(N)/(N-1)))# 汉明窗实现defhamming_window(N):return0.54-0.46*np.cos(2*np.pi*np.arange(N)/(N-1))

五、窗函数在信号处理中的实际应用

1. 信号处理流程

  1. 选择窗函数:根据需求选择汉宁窗、汉明窗等
  2. 生成窗函数:使用公式生成窗函数序列
  3. 应用窗函数:将窗函数与信号进行逐点乘法
  4. 执行FFT:对加窗后的信号进行快速傅里叶变换
  5. 分析频谱:根据频谱结果进行信号分析

2. 实际应用示例(Python)

importnumpyasnpimportmatplotlib.pyplotaspltfromscipyimportsignal# 生成一个正弦信号fs=1000# 采样频率t=np.linspace(0,1,fs,endpoint=False)# 1秒信号f=50# 信号频率signal=np.sin(2*np.pi*f*t)# 生成汉宁窗N=1024hanning=signal.windows.hann(N)# 应用汉宁窗windowed_signal=signal*hanning# 执行FFTfft_result=np.fft.fft(windowed_signal,N)freq=np.fft.fftfreq(N,1/fs)# 绘制原始信号和加窗后的信号plt.figure(figsize=(12,8))plt.subplot(2,1,1)plt.plot(t[:100],signal[:100],'b-',linewidth=1.5)plt.title('Original Signal (50Hz Sinusoid)')plt.xlabel('Time (s)')plt.ylabel('Amplitude')plt.grid(True)plt.subplot(2,1,2)plt.plot(t[:100],windowed_signal[:100],'r-',linewidth=1.5)plt.title('Windowed Signal (Hanning Window)')plt.xlabel('Time (s)')plt.ylabel('Amplitude')plt.grid(True)plt.tight_layout()plt.show()# 绘制频谱plt.figure(figsize=(10,6))plt.plot(freq[:N//2],20*np.log10(np.abs(fft_result[:N//2])),'g-')plt.title('Spectrum of Windowed Signal (Hanning Window)')plt.xlabel('Frequency (Hz)')plt.ylabel('Magnitude (dB)')plt.grid(True)plt.show()

3. 窗函数在OpenCV中的实现(2D汉宁窗)

根据知识库[1],OpenCV实现的2D汉宁窗:

voidcv::createHanningWindow(OutputArray _dst,cv::Size winSize,inttype){CV_INSTRUMENT_REGION();CV_Assert(type==CV_32FC1||type==CV_64FC1);CV_Assert(winSize.width>1&&winSize.height>1);_dst.create(winSize,type);Mat dst=_dst.getMat();introws=dst.rows,cols=dst.cols;AutoBuffer<double>_wc(cols);double*constwc=_wc.data();doublecoeff0=2.0*CV_PI/(double)(cols-1),coeff1=2.0*CV_PI/(double)(rows-1);for(intj=0;j<cols;j++)wc[j]=0.5*(1.0-cos(coeff0*j));if(dst.depth()==CV_32F){for(inti=0;i<rows;i++){float*dstData=dst.ptr<float>(i);doublewr=0.5*(1.0-cos(coeff1*i));for(intj=0;j<cols;j++)dstData[j]=(float)(wr*wc[j]);}}else{for(inti=0;i<rows;i++){double*dstData=dst.ptr<double>(i);doublewr=0.5*(1.0-cos(coeff1*i));for(intj=0;j<cols;j++)dstData[j]=wr*wc[j];}}// perform batch sqrt for SSE performance gainscv::sqrt(dst,dst);}

六、如何选择汉宁窗还是汉明窗?

1. 选择指南

场景推荐窗函数原因
通用信号处理汉宁窗平衡点,适用于大多数情况
语音信号处理汉明窗第一旁瓣更低(-42dB vs -31dB),更适合关注主瓣附近信号
需要极低旁瓣汉明窗第一旁瓣抑制更好
需要快速旁瓣衰减汉宁窗旁瓣衰减更快(-60dB/10oct vs -20dB/10oct)
计算资源有限汉明窗在FPGA实现中可节省20%-51%的资源

2. 选择技巧

  1. 不知道选哪种:汉宁窗是"万金油",适用于大多数情况。
  2. 语音信号处理:汉明窗更常用。
  3. 需要精确测量幅度:考虑使用平顶窗。
  4. 需要极高旁瓣抑制:考虑使用布莱克曼窗。

七、窗函数家族的其他成员

窗函数公式特点
矩形窗w(n)=1w(n) = 1w(n)=1主瓣最窄,旁瓣最高(-13dB)
汉宁窗0.5[1−cos⁡(2πn/(N−1))]0.5[1-\cos(2\pi n/(N-1))]0.5[1cos(2πn/(N1))]通用,平衡点
汉明窗0.54−0.46cos⁡(2πn/(N−1))0.54-0.46\cos(2\pi n/(N-1))0.540.46cos(2πn/(N1))第一旁瓣更低
布莱克曼窗0.42−0.5cos⁡(2πn/(N−1))+0.08cos⁡(4πn/(N−1))0.42-0.5\cos(2\pi n/(N-1))+0.08\cos(4\pi n/(N-1))0.420.5cos(2πn/(N1))+0.08cos(4πn/(N1))旁瓣更低,主瓣更宽
平顶窗多项式形式幅度测量精度高

八、总结

汉宁窗是"通用选手",适合大多数情况;汉明窗是"优化选手",特别适合关注主瓣附近信号的场景。

选择汉宁窗还是汉明窗,取决于你更看重"旁瓣衰减速度"还是"第一旁瓣的抑制效果"。

汉宁窗:通用性强,旁瓣衰减快,是信号处理中的"万金油"。
汉明窗:第一旁瓣更低(-42dB vs 汉宁窗的-31dB),特别适合语音信号处理等需要关注主瓣附近信号的场景。

在实际应用中,你可以通过比较频谱泄漏情况来确定哪种窗函数更适合你的具体需求。记住,没有完美的窗函数,只有最适合你应用场景的窗函数。

希望这个超详细的剖析能帮助你深入理解汉宁窗和汉明窗!如果你在实际应用中遇到具体问题,欢迎继续讨论~

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/29 18:43:19

FastReport Open Source:从零开始打造专业级.NET报表系统

FastReport Open Source&#xff1a;从零开始打造专业级.NET报表系统 【免费下载链接】FastReport Free Open Source Reporting tool for .NET6/.NET Core/.NET Framework that helps your application generate document-like reports 项目地址: https://gitcode.com/gh_mir…

作者头像 李华
网站建设 2026/3/28 21:03:23

电子签名完整指南:OpenSign开源免费PDF签署解决方案

电子签名完整指南&#xff1a;OpenSign开源免费PDF签署解决方案 【免费下载链接】OpenSign &#x1f525; &#x1f525; &#x1f525; The free & Open Source DocuSign alternative 项目地址: https://gitcode.com/gh_mirrors/op/OpenSign 在数字化办公时代&…

作者头像 李华
网站建设 2026/3/26 15:57:25

基于Vue.js和SpringBoot的新能源汽车充电站管理系统外文翻译

温州商学院本科毕业设计&#xff08;论文&#xff09;外文翻译毕业设计&#xff08;论文&#xff09;题目&#xff1a;姓 名学 号指导教师班 级19计算机本*原文题目&#xff1a;《EverAnalyzer: A Self-Adjustable Big Data Management Platform Exploiting the Hadoop Ecos…

作者头像 李华
网站建设 2026/3/28 10:50:11

Android为何引入Java而不完全使用Java所有特性

一、Java在Android中的核心作用1. 内存管理简化// Java vs C/C内存管理对比 ​ // Java&#xff08;自动内存管理&#xff09; public class JavaExample {private List<String> data new ArrayList<>();public void process() {String item new String("te…

作者头像 李华
网站建设 2026/3/25 22:10:49

终极指南:如何在Photoshop中完美使用WebP格式

WebPShop作为一款专为Adobe Photoshop设计的开源插件&#xff0c;彻底解决了设计师在处理现代WebP格式图像时的各种难题。这款插件不仅支持静态WebP图像的打开和保存&#xff0c;更提供了强大的动画处理能力&#xff0c;让您在工作流程中无缝衔接这一高效的图像格式。 【免费下…

作者头像 李华
网站建设 2026/4/1 21:40:41

基于Vue的美食菜谱网站的设计与实现任务书)

本科毕业论文&#xff08;设计&#xff09;任务书论文&#xff08;设计&#xff09;题目&#xff1a;学院信息工程学院专业计算机科学与技术年级2022级&#xff08;专升本&#xff09;学生姓名指导教师学号职称一、毕业论文&#xff08;设计&#xff09;应完成的内容及要求&…

作者头像 李华