当前位置:   article > 正文

汉宁窗口介绍以及计算方法

汉宁窗

汉宁窗口介绍

汉宁窗口(Hanning Window)的起源:

汉宁窗口是一种在信号处理和频谱分析中常用的窗口函数。它的名字来自于发明者之一的Julius von Hann(也写作Hanning)。Hann是奥地利的物理学家,他于1928年发表了一篇题为《Über die Verwendung von Fensterfunktionen bei der Fourier-Analyse von Zeitabhängigen Messungen》(关于在傅里叶分析中使用窗口函数进行时间相关测量的论文)的文章,介绍了这个窗口函数的概念。

汉宁窗口计算公式

汉宁窗口(Hanning Window)的计算公式如下:

其中:

  • ( w(n) ) 是窗口函数在位置 ( n ) 处的值。
  • ( n ) 是窗口中的样本点索引,从 0 开始。
  • ( N ) 是窗口的长度(样本点的数量)。

这个公式描述了汉宁窗口函数在离散样本点上的取值。窗口的特点是在两端有较小的幅度,中心区域的振幅相对较高。这有助于减小截断信号产生的频谱泄漏,提高频谱分析的准确性。

应用场景

汉宁窗口的应用场景:

在信号处理中,窗口函数用于限制从无穷信号中选择的有限片段,以便在频域中进行傅里叶变换。窗口函数有助于减小截断信号产生的频谱泄漏(spectral leakage)现象,提高频谱分析的准确性。

汉宁窗口的主要特点是在窗口内信号的两端降低幅度,以减小边界效应,同时保持中心区域的振幅不变。

C++实现一个示例并用用OpenCV绘制

用C++计算汉宁窗口数组并用OpenCV展示曲线:

下面是一个使用C++和OpenCV的简单示例代码,计算汉宁窗口数组并绘制其曲线:

  1. #include <iostream>
  2. #include <cmath>
  3. #include <opencv2/opencv.hpp>
  4. int main() {
  5. // 设置窗口大小
  6. int windowSize = 100;
  7. // 计算汉宁窗口数组
  8. cv::Mat hanningWindow = cv::Mat::zeros(1, windowSize, CV_64F);
  9. for (int i = 0; i < windowSize; ++i) {
  10. hanningWindow.at<double>(0, i) = 0.5 * (1 - std::cos(2 * CV_PI * i / (windowSize - 1)));
  11. }
  12. // 设置窗口背景颜色
  13. cv::Scalar backgroundColor(255, 255, 255); // 白色背景
  14. // 显示汉宁窗口曲线
  15. cv::Mat plot = cv::Mat::ones(400, windowSize, CV_8UC3) * 255;
  16. plot.setTo(backgroundColor);
  17. for (int i = 0; i < windowSize - 1; ++i) {
  18. cv::line(plot, cv::Point(i, 200 - hanningWindow.at<double>(0, i) * 200),
  19. cv::Point(i + 1, 200 - hanningWindow.at<double>(0, i + 1) * 200),
  20. cv::Scalar(0, 0, 0), 2, cv::LINE_AA);
  21. }
  22. // 显示图像
  23. cv::imshow("Hanning Window", plot);
  24. cv::waitKey(0);
  25. return 0;
  26. }

这个程序首先计算了汉宁窗口数组,然后使用OpenCV绘制了窗口函数的曲线。通过调整windowSize可以改变窗口的大小。在绘制过程中,窗口函数的值被映射到图像的纵轴上,形成了窗口函数的曲线。

用C++实现一个类似于科学计算库scipy中实现的hann窗口函数

scipy中直接调用

win = scipy.signal.windows.hann(N_win, sym=False)

C++代码具体实现

  1. bool len_guards(int M) {
  2. if (M < 0) {
  3. throw std::invalid_argument("Window length M must be a non-negative integer");
  4. }
  5. return M <= 1;
  6. }
  7. std::pair<int, bool> extend(int M, bool sym) {
  8. if (!sym) {
  9. return std::make_pair(M + 1, true);
  10. } else {
  11. return std::make_pair(M, false);
  12. }
  13. }
  14. std::vector<double> truncate(std::vector<double>& w, bool needed) {
  15. if (needed) {
  16. w.pop_back();
  17. }
  18. return w;
  19. }
  20. std::vector<double> general_cosine(int M, std::vector<double> alpha, bool sym) {
  21. if (len_guards(M)) {
  22. return std::vector<double>(M, 1.0);
  23. }
  24. auto [M_ext, needs_trunc] = extend(M, sym);
  25. double pi = std::acos(-1);
  26. std::vector<double> fac(M_ext);
  27. for (int i = 0; i < M_ext; ++i) {
  28. fac[i] = -pi + 2.0 * pi * i / (M_ext - 1);
  29. }
  30. std::vector<double> w(M_ext, 0.0);
  31. for (int k = 0; k < alpha.size(); ++k) {
  32. for (int i = 0; i < M_ext; ++i) {
  33. w[i] += alpha[k] * std::cos(k * fac[i]);
  34. }
  35. }
  36. return truncate(w, needs_trunc);
  37. }
  38. std::vector<double> general_hamming(int M, double alpha, bool sym=true) {
  39. return general_cosine(M, {alpha, 1.0 - alpha}, sym);
  40. }
  41. std::vector<double> hann(int M, bool sym=true) {
  42. return general_hamming(M, 0.5, sym);
  43. }
  44. std::vector<double> sqrtHann(int M, bool sym=true){
  45. auto arr = general_hamming(M, 0.5, sym);
  46. for(auto& a : arr){
  47. a = std::sqrt(a);
  48. }
  49. return arr;
  50. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/287638
推荐阅读
相关标签
  

闽ICP备14008679号