数字信号处理实验报告docx自动化:FFT、滤波器与python-docx交付 简介本资源为北京理工大学数字信号处理课程实验报告文档面向电子信息、通信工程等专业本科生及需要完成相关实验的学习者。报告围绕离散傅里叶变换DFT展开涵盖DFT与DTFT的取样关系、由N点DFT恢复DTFT的两种方法以及利用DFT分析连续时间信号频谱的完整流程并针对频谱混叠、栅栏效应、频谱分辨率与频谱泄露等问题给出参数选取思路。四个实验分别考察补零对频谱分辨率的影响、序列频谱的DFT估计、复合正弦波信号频率分辨率的确定以及不同采样间隔与截取长度下连续信号幅度谱的分析每个实验均附MATLAB代码、幅度谱与相位谱结果及简要分析。资源包内含1个docx文件大小约795KB结构完整便于直接参考与排版。目前已有1351人学习下载适合用于实验预习、报告撰写参照及DFT知识点查漏补缺。1. 数字信号处理实验报告 docx从能跑通到能交付实验室里卷积、FFT、滤波器的代码半小时能跑出图真正拖住进度的是后面那件事把波形、参数、结论按格式塞进一份 docx还要对齐页边距、题注编号、公式编号。北京理工大学数字信号处理实验报告.docx 这类文件值得单独拎出来讲是因为它把两个世界缝在一起——一边是采样率、窗函数、幅频响应这些硬指标一边是样式、题注、目录域这些排版规则。只懂一边的人交付时一定要返工。这篇面向的是要交 DSP 实验报告的学生也面向任何需要用程序批量产出带图带表 Word 文档的工程师把数据流水线和文档流水线拆开再让它们对齐。2. 数字信号处理实验报告 docx 的内容骨架与数据落点一份报告写不下去八成不是因为不会算 FFT而是因为不知道哪一段该放什么、数据从哪个文件来、图用什么口径画。先把骨架和数据落点定死后面写代码才有靶子。2.1 数字信号处理实验报告 docx 的固定段落与每段该写什么常见的六个实验离散信号与系统、卷积、DFT/FFT、IIR 滤波器、FIR 滤波器、采样与重构报告结构基本一致段落顺序不要自创实验目的三到四条写清验证哪个理论点不要抄实验指导书整段。实验原理公式为主体差分方程、系统函数 $H(z)$、窗函数表达式各占一段每条公式给编号。实验内容与步骤参数表加关键代码片段代码只贴调用和参数设置不贴完整脚本。实验结果与分析图、表、数值三者互相对照图必须能读出坐标轴单位和量纲。误差与思考题把实测值和理论值列在一起差值算到相对误差。原理段最容易写空。以 FIR 低通为例至少写清 $h[n]$ 的由来窗函数法理想冲激响应乘窗、截止频率 $\omega_c$ 与归一化频率的关系 $\omega_c 2\pi f_c / f_s$、以及阻带衰减由窗型决定的定性结论。这三句话决定了后面分析图的解释力也是老师判断你有没有真正做过实验的地方。2.2 数据来源的口径统一MATLAB、Python 与硬件采集同一份报告里最忌讳两套参数。有人频谱图用 $f_s 1000\ \text{Hz}$滤波器设计又用 $f_s 8000\ \text{Hz}$图看着都对结论全错。常见做法是把所有实验参数集中写成一个配置文件或者一段常量导出数据统一落成 CSV图片重新用脚本渲染而不是从 MATLAB 界面上截图。# params.py —— 全实验共用参数任何脚本都从这里取 FS 1024 # 采样率 Hz N 1024 # 采样点数取 2 的幂便于 FFT F0 50.0 # 主频分量 1 F1 120.0 # 主频分量 2 FC 100.0 # 低通截止频率 Hz ORDER 4 # 巴特沃斯阶数 WINDOW hanning # 窗函数类型参数集中在常量里好处是报告正文的参数表、代码里的数值、图上标注的轴范围三者能靠同一份来源对齐改一次 $f_s$全篇跟着变。注意N取 2 的幂不是为了省事而是为了让np.fft.rfft走基 2 分解同时保证频率分辨率 $\Delta f f_s / N 1\ \text{Hz}$ 是个整数读谱线位置时不会有小数误差。硬件采集的数据多一步先做直流去除减均值再确认量程与 AD 位数否则频谱里的低频鼓包会被误判成信号成分。采集卡导出的二进制或 CSV 在入报告前统一转成浮点电压值别混着原始码值和电压两套单位。2.3 图表、有效数字与单位约定报告里的图不是能看就行横轴纵轴标签、单位、刻度方向都要能被人复现。约定一张表写脚本时照着填实验项目采样率 fs点数 N窗函数关键指标DFT/FFT 频谱1024 Hz1024汉宁窗频谱分辨率 1 Hz幅值误差 5%IIR 低通1024 Hz2048无通带 0–80 Hz阻带衰减 ≥30 dBFIR 低通1024 Hz2048汉明窗截止 100 Hz过渡带宽度约 30 Hz采样与重构2000 Hz1024无重构信噪比 ≥40 dB有效数字按仪器和算法精度定频率类保留到小数点后一位或整数幅度类保留三位有效数字相对误差保留两位。表格里同一列的小数位数必须一致这一条比数字本身准不准更容易被扣分。3. 用 python-docx 把 FFT 与滤波器结果写进报告数据齐了接下来是组装。python-docx 的能力边界很清楚段落、样式、表格、图片、页眉页脚都能做公式只能靠 OMML 片段或域代码图表动画和复杂排版不要指望。把边界认清就不会在样式上反复折腾。3.1 先定样式再写内容Normal、题注与三线表默认模板的 Normal 样式是西文字体中文会掉成宋体以外的字体字号也不一定是小四。样式必须在插内容之前设好中途改样式会让已有段落行为不一致。from docx import Document from docx.shared import Pt, Cm from docx.enum.text import WD_ALIGN_PARAGRAPH from docx.oxml.ns import qn doc Document() # 基于默认模板也可换成学校模板 normal doc.styles[Normal] normal.font.name Times New Roman # 西文 normal.font.size Pt(12) # 小四 normal._element.rPr.rFonts.set(qn(w:eastAsia), 宋体) # 中文字体 for sec in doc.sections: # 页边距按学校要求 sec.top_margin, sec.bottom_margin Cm(2.5), Cm(2.5) sec.left_margin, sec.right_margin Cm(3.0), Cm(2.5)normal._element.rPr.rFonts这一步是绕不开的python-docx 没有中文专属字体接口只能直接写w:eastAsia这个 XML 属性。西文字体设成 Times New Roman、中文设宋体是多数高校模板的默认组合如果学校要求正文用宋体小四、行距 1.5 倍还要补一句normal.paragraph_format.line_spacing 1.5。标题样式不要手写字号用doc.add_heading(text, level2)走内置 Heading 样式这样后期在 Word 里生成目录才能识别层级。题注图 1、表 1没有内置样式老老实实加一个居中段落字体设为五号def add_caption(doc, text): p doc.add_paragraph(text) p.alignment WD_ALIGN_PARAGRAPH.CENTER for r in p.runs: r.font.size, r.font.name Pt(10.5), Times New Roman r._element.rPr.rFonts.set(qn(w:eastAsia), 宋体) return p3.2 numpy 算频谱、scipy 设计滤波器并出图出图和算数放在同一个脚本里图才能和参数严格对应。下面的频谱计算里有两个容易被忽略的细节加窗后要按窗函数求和归一化否则幅值修正是错的单边谱要乘 2但直流和奈奎斯特点不能乘。import numpy as np import matplotlib matplotlib.use(Agg) # 无 GUI 环境下必须指定后端 import matplotlib.pyplot as plt from params import FS, N, F0, F1 t np.arange(N) / FS x 0.8*np.sin(2*np.pi*F0*t) 0.5*np.sin(2*np.pi*F1*t) 0.05*np.random.randn(N) w np.hanning(N) # 汉宁窗降低旁瓣泄漏 X np.fft.rfft(x * w) mag 2.0 * np.abs(X) / np.sum(w) # 幅值修正 freq np.fft.rfftfreq(N, 1.0/FS) # 频率轴步长 FS/N fig, ax plt.subplots(figsize(6, 3.5), dpi200) ax.plot(freq, mag, lw0.9) ax.set_xlabel(频率 / Hz); ax.set_ylabel(幅值 / V) ax.set_xlim(0, 200); ax.grid(alpha0.3) fig.tight_layout(); fig.savefig(fig_fft.png); plt.close(fig)dpi200是折中值低于 150 打印时锯齿明显高于 300 文件体积涨得快而 Word 显示并不更清楚。figsize(6, 3.5)对应正文里约 12 cm 的图宽插入时按widthCm(12)缩放纵横比不会变形。滤波器部分用scipy.signal.butter拿系数再用freqz取幅频响应from scipy import signal from params import FS, FC, ORDER b, a signal.butter(ORDER, FC/(FS/2), btypelow) # 归一化频率必须除以 Nyquist w2, h signal.freqz(b, a, worN1024, fsFS) # 指定 fs 后横轴直接是 Hz h_db 20*np.log10(np.abs(h) 1e-12) print(b , np.round(b, 5)); print(a , np.round(a, 5))FC/(FS/2)里的FS/2是奈奎斯特频率忘了归一化会得到完全错误的截止特性这是新手最常踩的坑。打印b、a两组系数贴进报告比只贴一张幅频图更有说服力因为读者能拿系数复算出同样的曲线。3.3 组装 docx图片、表格与结论段的写入顺序写入顺序按报告阅读顺序来先标题后正文图片紧跟在结果与分析段落之后题注紧随图片。doc.add_heading(3 实验结果与分析, level1) doc.add_paragraph(对加汉宁窗后的信号做 1024 点 FFT频率分辨率为 1 Hz 50 Hz 与 120 Hz 处出现明显谱峰与理论设置一致。) doc.add_picture(fig_fft.png, widthCm(12)) doc.paragraphs[-1].alignment WD_ALIGN_PARAGRAPH.CENTER # 图片居中 add_caption(doc, 图 3-1 加汉宁窗后的单边幅值谱) tab doc.add_table(rows1, cols3); tab.style Table Grid for i, h in enumerate([分量, 理论幅值/V, 实测幅值/V]): tab.rows[0].cells[i].text h for name, th, me in [(50 Hz, 0.8, 0.79), (120 Hz, 0.5, 0.50)]: cells tab.add_row().cells cells[0].text, cells[1].text, cells[2].text name, f{th:.2f}, f{me:.2f} doc.save(dsp_report.docx)doc.add_picture后返回的是最后一个段落对象直接给它设居中即可不需要再定位。表格用Table Grid边框样式如果学校要求三线表就手动改首行上下框和末行下框的 XML 边框属性比找第三方样式可靠。数值用 f-string 格式化而不是str()避免0.7900000000000001这类浮点尾巴进入报告。4. 多组实验参数下的批量生成与一致性控制一个学期六到八个实验结构一样、参数不同逐份手改既慢又容易串味。批量的关键不是循环而是决定模板替换还是全代码生成。4.1 模板占位符替换与全代码生成怎么选方案适用场景优点代价模板占位符替换学校给了固定格式模板样式、页眉页脚、封面一次搞定只能替换文本图片和表格要额外插全代码生成格式要求宽松、参数变化多可控性最强便于版本管理页眉、页脚、目录要自己补混合模板做壳、代码填肉多数实际情况兼容两者的长处需要处理占位符定位混合方案最省事把封面、页眉、页脚、目录页做进模板 docx正文部分留{{PRINCIPLE}}、{{RESULT}}这样的占位符用脚本替换文本后再插图和表。文本替换要小心 run 被切碎的问题from docx import Document def replace_in_doc(doc, mapping): for p in doc.paragraphs: for run in p.runs: # 逐 run 替换保留原格式 for k, v in mapping.items(): if k in run.text: run.text run.text.replace(k, v) return doc tpl Document(template.docx) replace_in_doc(tpl, {{{TITLE}}: 实验四 IIR 数字滤波器设计, {{FS}}: 1024 Hz, {{FC}}: 100 Hz}) tpl.add_picture(fig_iir.png, widthCm(12)) tpl.save(exp04_report.docx)逐 run 替换的问题是占位符如果被 Word 拆到两个 run 里{{TI和TLE}}一次性替换会失败。稳妥做法是先合并段落内所有 run 的文本再重新写入首个 run或者干脆保证模板里的占位符不经过拼写检查修改。参数表驱动批量时把每个实验的参数字典放进列表循环即可experiments [ {name: exp03_fft, fs: 1024, n: 1024, win: hanning}, {name: exp04_iir, fs: 1024, n: 2048, win: None}, {name: exp05_fir, fs: 1024, n: 2048, win: hamming}, ] for e in experiments: generate(e) # 内部完成算数、出图、填模板、另存字典里显式写win: None而不是省略键是为了让下游代码用e[win]时不会 KeyError这份一致性在参数变多时价值很大。4.2 踩坑清单图片路径、样式串味与 WPS 打开异常第一类坑是路径。脚本在 A 目录运行、图片写到 B 目录add_picture找不到文件直接抛异常相对路径还会因为批处理脚本的当前工作目录不同而失效。统一用相对于脚本文件的路径from pathlib import Path BASE Path(__file__).resolve().parent # 脚本所在目录 doc.add_picture(str(BASE / figs / fig_fft.png), widthCm(12))第二类坑是样式串味。往模板里插图、插表时新段落的样式继承自模板的 Normal如果模板 Normal 是段前 0 行、单倍行距插进去的正文就可能和其他段落不一致。做法是在模板里专门留一个正文占位段用它作为模板段复制 XML而不是新建段落。python-docx 没有直接复制段落样式的接口简单办法是把样式名写死在代码里p.style doc.styles[BodyText]。第三类坑是 WPS 打开时提示文件格式与扩展名不一致或目录页码不刷新。python-docx 直接拼 XML 出来的包多数情况下没问题但如果手动改过settings.xml、删过关系项校验就会失败。至于页码和目录代码生成的文档里目录域是静态的打开后要在 Word 或 WPS 里按 F9 更新域才会显示正确页码如果模板里放了 TOC 域却没有更新交上去就是一片错误未定义书签。另外 WPS 的默认新建格式设置是它自身的选项不影响脚本产出的.docx不要被这个现象误导去改代码。5. 交付前校验OMML 公式、包结构与自检脚本写到最后一版最该花时间的不是再润色文字而是把文档当二进制产物验一遍公式是不是公式、图片在不在包里、样式有没有被污染。5.1 公式用 OMML不要贴截图原理段的公式如果是从别处截图贴进来的放大就糊字号也和正文不匹配更致命的是老师无法用搜索定位。Word 2007 之后的公式本质是 OMML存在word/document.xml里就是一段数学标记。python-docx 不直接支持公式可以用两种办法一是从已有文档里把公式段落的 XML 抽出来用parse_xml插到目标位置二是用 LaTeX 转 OMML 的工具先生成片段再doc.element.body.append(...)。抽 XML 的做法最实用from docx import Document from docx.oxml import parse_xml src Document(formula_lib.docx) # 预置公式的素材文档 omml src.paragraphs[0]._p.xml # 取出第一个公式段落 new_p parse_xml(omml) # 反序列化为元素 doc.element.body.append(new_p) # 追加到目标文档末尾这样插进去的公式是可编辑的域对象Word 里双击就能改参数缩放不失真。注意parse_xml需要带命名空间声明的完整 XML直接从_p.xml取出的片段恰好满足这一点。5.2 用 zipfile 检查 docx 内部结构是否完整docx 本身就是一个 zip 包交付前拆开看一眼比在 Word 里翻半天管用import zipfile with zipfile.ZipFile(dsp_report.docx) as z: names z.namelist() media [n for n in names if n.startswith(word/media/)] print(图片数量:, len(media), media) print(document.xml 存在:, word/document.xml in names) print(损坏项:, z.testzip()) # None 表示 CRC 全部通过word/media/下每张插入的图对应一个imageN.png数量对不上说明有图没进去testzip()返回None才说明压缩包没有损坏。这一步还能顺手查出重复插入的同一张图——python-docx 不会去重同一张图插三次包里就有三份几十兆的文档多半是这么来的。5.3 交付前自检表检查项判据工具公式可编辑双击弹出公式编辑器Word / WPS图片齐全word/media数量等于插入次数zipfile目录页码正确F9 更新域后页码与正文一致Word字体统一正文中文宋体、西文 Times New Roman样式检查参数字段一致正文参数表与代码常量逐项相等人工比对数值格式同列小数位数一致无浮点尾巴脚本正则包完整testzip()返回 Nonezipfile数值格式那一项可以写成脚本扫全文段落用正则找\d\.\d{6,}这类长小数命中就报行号比人眼翻三十页快得多。整份报告生成脚本放在版本库里改一次参数重跑一遍比在 Word 里手动调格式稳得多。本文还有配套的精品资源点击获取