资讯动态

MATLAB动态仿真牛顿环:从光程差公式到GIF动图实现

发布时间:2026/10/14 18:21:38 来源:尧图企业网站定制
简介基于MATLAB开发的牛顿环动态光学仿真资源面向光电信息科学与工程专业本科生、高校教师及光学实验研究者涉及等厚干涉、光程差等核心概念用于直观理解厚度变化对干涉条纹的影响。资源仅4个文件包含可自定义参数的MATLAB脚本、动态演示GIF、等倾干涉与牛顿环的对比分析文档及使用说明压缩包整体约362MB结构精炼不冗余。该资源已有1794人学习浏览脚本支持调节初始厚度与变化速率可模拟膜层变厚与变薄两个方向的动态过程配套动图清晰展示条纹级数随厚度连续变化文档则从原理层面辨析等倾干涉与牛顿环的异同便于理解光程差与环状条纹的对应关系。通过仿真与图文结合既能服务课堂演示与课后自学也为光学测量相关科研提供可复现的参考工具。1. 光学仿真与 MATLAB 动态仿真牛顿环一条公式把干涉演示做成动图一门光学课要讲等厚干涉课本上最经典的图就是牛顿环一圈一圈明暗相间的同心圆。可你真站到讲台上会发现这套实验很难演——实物装置里的空气膜厚度差只有微米量级投影出来的条纹对焦难、反光重想让学生看清条纹怎样从中心“长”出来、怎样随曲率半径变化而扩缩往往只能靠课后录视频补讲。光学仿真 MATLAB 动态仿真牛顿环的干涉图像正好把这个过程变成一帧一帧可计算的光强分布再合成动图或实时重绘。它解决的是“让看不见的光程差变成看得见的动态过程”这个核心问题适合教学演示、实验预演、课程设计也适合想亲手验证干涉公式的初学者。2. 先把物理模型写进代码牛顿环的光程差公式与像素网格化2.1 从光程差到暗纹半径核心公式其实只有一条牛顿环的实验装置是平凸透镜放在平板玻璃上两者之间形成一圈厚度连续变化的空气薄膜。单色光垂直入射后从空气膜上下两个表面反射回来的两束光发生干涉。空气中厚度 d 随径向距离 r 变化近似为 d(r) r² / (2R)R 是平凸透镜的曲率半径。加上反射时产生的半波损失两束反射光的光程差写成δ 2d λ/2 r² / R λ/2这是整个仿真里唯一需要写进代码的物理公式。光强分布用双光束干涉的余弦平方公式I(r) cos²(π · δ / λ)中心处 d 0δ λ/2cos²(π/2) 0所以中心是一个暗斑从中心往外光强随 r² 周期变化形成明暗相间的同心圆环。因为每个像素的光强只由它到中心的距离决定这种干涉被称为等厚干涉仿真的几何关系天然是一圈圈同心圆。从这个公式能直接推导暗纹半径r_k √(k·λ·R)k 0, 1, 2…。k0 对应中心暗斑k1 是第一级暗环以此类推。这个式子后面会反复用到——调参前先算它能避免大量盲目试错。仿真的本质是把连续的 r 坐标离散成像素网格对每一个像素代入公式算光强最后把光强矩阵映射成灰度图。整个过程没有数值积分也没有迭代几行代码就能出结果这也是 MATLAB 做这类光学仿真最顺手的地方meshgrid 生成网格矩阵运算一步到位。2.2 用像素网格“拍”下光场第一版静态仿真搭建先给一段可以完整运行的静态仿真脚本。它不会生成动图但是后面所有动态版本的地基。% 牛顿环静态干涉图仿真单帧光强分布计算 lambda 589e-9; % 钠黄光波长米589nm R 1.0; % 平凸透镜曲率半径米 pixels 800; % 图像分辨率800x800 L 5e-3; % 视场宽度米即图像覆盖5mm见方区域 % 生成像素坐标网格从 -L/2 到 L/2 均匀取 pixels 个点 x linspace(-L/2, L/2, pixels); [X, Y] meshgrid(x, x); % 径向距离平方每个像素离图像中心接触点的平面距离平方 r2 X.^2 Y.^2; % 光程差空气膜厚度项 r2/R 加上半波损失项 lambda/2 delta r2 / R lambda/2; % 反射双光束干涉光强cos^2 形式 I cos(pi * delta / lambda).^2; % 归一化到 0~255转 8bit 灰度图显示 I I / max(I(:)) * 255; figure(Color, black); imshow(uint8(I), Border, tight); title(sprintf(Newton Rings: \\lambda %.0f nm, R %.2f m, lambda*1e9, R));这段代码的逻辑分三块。第一块是参数区lambda、R、pixels、L 四个变量决定仿真结果的一切差异第二块是网格生成linspace 在 [-L/2, L/2] 上均匀取点meshgrid 把一维坐标扩展成二维坐标矩阵X.^2 Y.^2 对每个像素求它到中心的径向距离平方 r2第三块是光强计算和显示delta 里 r2/R 是空气膜贡献的光程差lambda/2 是半波损失cos(pi * delta / lambda) 把光程差折算成相位平方后得到干涉光强。参数选择不是随手填的。L 取 5mm是因为在 R 1m、λ 589nm 时第 10 级暗纹半径约 2.43mm略小于视场半径 2.5mm图像能完整装下约 10 条暗环既能看到完整的环带分布又不会因为条纹过多而看不清细节。pixels 取 800对应中心到第 10 级暗环约 388 个像素平均每级暗环约 39 像素的间距边缘干净不发毛。lambda 必须写成 589e-9 而不是 589否则 δ 的量级会错上 6 个数量级生成的全是密密麻麻的细条纹。这段代码里最容易被忽略的是中心位置的行为。因为 delta 里加了 lambda/2即使 r2 0 时光程差也不是 0中心天然落在干涉极小值上显示为暗斑。如果去掉半波损失中心立刻变成亮斑而且明暗环位置全部互换一眼就能看出不对。2.3 写代码之前先估算视场、级数与像素的匹配我习惯在写代码之前先手算一遍量级能省掉不少瞎调参数的时间。做法是先定要显示几级暗环再反推视场宽度最后确定像素数。第 k 级暗环半径是 r_k √(k·λ·R)。如果希望视场边缘能看到第 10 级暗环视场半宽至少要大于 r_10。把 λ 589e-9、R 1.0 代进去r_10 ≈ 2.43mm所以视场全宽至少要 4.86mm取整到 5mm 就是 L 的由来。像素数按“每个暗环至少占 30 个像素”来定视场半宽 2.5mm 分成 400 份中心到第 10 级暗环仍然有 388 个像素足够平滑。下面是 λ 589nm、R 1m 时几组常用的参数组合换波长或曲率半径时按公式重新算一次即可目标暗环级数视场宽度 L像素数单级暗环像素宽度5 级3.5mm600约 40 像素10 级5mm800约 30 像素15 级6.5mm1000约 24 像素养成“先算后写”的习惯后面做动态仿真调 R 时就能直接判断某个 R 值下条纹会不会超出视场外、会不会全部挤在中心成一团而不用把动图生成出来之后才发现方向错了。3. 从单帧快照到动态干涉图帧序列、GIF 合成与动图的物理方向3.1 三种让静态图动起来的方案适用场景完全不同MATLAB 里把牛顿环变成动图常见有三条路合成 GIF、录制 AVI/MP4、实时重绘。它们各自适合不同的输出场景先盘清楚再动手。方式输出优点缺点适用场景GIF 合成图片文件体积小、PPT/网页直接插入256 色、帧多会卡教学演示、课件插图VideoWriter 录视频AVI/MP4帧数不限、画面细节保留文件大、需播放器长过程记录、高清输出实时重绘屏幕动画参数可交互、反馈即时不能直接保存成文件实验预演、参数探索我一般判断标准很简单动图要插进 PPT 或网页选 GIF单帧分辨率控制在 400×400 左右帧数不超过 48要录一段连续几分钟的曲率半径扫描选 VideoWriter 录 AVI分辨率可以拉到 800×800目标是让学生亲手拖滑块看条纹变化就选实时重绘用回调函数驱动光强矩阵刷新。三个方案不冲突GIF 负责传播AVI 负责精度实时重绘负责交互。3.2 用 MATLAB 把 48 帧干涉图合成 GIF曲率半径线性扫描的最小实现动态仿真最直观的物理量是曲率半径 R。R 增大时空气膜同一径向位置的厚度比例增大条纹整体向外扩张R 减小则条纹向中心收缩。用 R 从 0.5m 线性变化到 2.5m 做一组长扫描正好能看到“条纹从中心成串涌出、向边缘扩散”的完整过程。下面代码把上一章的静态仿真固化成 48 帧并写入 GIF保留了生成动画的最小参数集% 动态牛顿环曲率半径 R 从 0.5m 线性扫描到 2.5m输出 GIF 动图 lambda 589e-9; % 波长 589nm pixels 400; % 动图分辨率降到 400控制 GIF 体积 L 5e-3; % 视场宽度不变 frames 48; % 总帧数 gif_file newton_rings_dynamic.gif; % 准备像素网格每帧共用不重复计算 x linspace(-L/2, L/2, pixels); [X, Y] meshgrid(x, x); r2 X.^2 Y.^2; % 曲率半径扫描序列等间隔取 48 个值 R_list linspace(0.5, 2.5, frames); for k 1:frames R R_list(k); % 光程差厚度项 半波损失项 delta r2 / R lambda/2; % 干涉光强并归一化到 8bit 灰度 I cos(pi * delta / lambda).^2; I uint8(I / max(I(:)) * 255); % 转为索引图写入 GIF第一帧创建后续帧追加 [A, map] gray2ind(I, 256); if k 1 imwrite(A, map, gif_file, gif, Loopcount, inf, DelayTime, 0.08); else imwrite(A, map, gif_file, gif, WriteMode, append, DelayTime, 0.08); end end几个关键参数为什么要取现在的值需要说清楚。帧数 frames 取 48 而不是 12 或 120小于 24 帧时条纹连续扩张会有明显跳变演示时学生能看出“一格一格在动”超过 64 帧时GIF 体积成倍增大而 0.5m 到 2.5m 的扫描过程中相邻帧的条纹位移量已经小于一个像素多出来的帧不会带来更多信息量。DelayTime 取 0.08 秒等效帧率约 12.5 帧/秒这个区间慢速扩张看得清方向课堂等待也不会太长。如果觉得动得太快先加 frames 而不是盲目调小 DelayTime否则总时长缩短运动速度反而更快。分辨率取 400 是因为 GIF 是 8 位索引色格式单帧尺寸再大颜色量化也会把明暗过渡的边缘切出断层同时直接拉升整个文件的体积。注意千万别把 800×800 的帧序列直接写进 GIF体积涨几倍不说色带伪影会让暗纹边缘一圈一圈地分层。循环里有个容易被忽略的优化坐标网格在循环外只生成了一次。r2 是与 R 无关的几何量R 改变时只是 r2/R 的系数在变不需要重新 meshgrid。很多初学者把 linspace、meshgrid 一起搬进循环功能没错但每一帧都重新分配几百 MB 的临时矩阵动图生成时间翻倍。这种小习惯在实时重绘里尤其重要回调函数里每毫秒都值钱。写 GIF 时第一帧和后续帧的 imwrite 参数不同第一帧用 Loopcount, inf 指定无限循环后面用 WriteMode, append 追加。如果第一帧不指定 Loopcount某些看图软件会把动图当普通静态图显示如果后续帧用了 append 却忘了在首帧设置 Loopcount循环播放设置也会丢失。这是 GIF 合成最常见的翻车点。3.3 条纹到底往哪边动一个一眼能验伪的物理方向检验动态仿真跑通之后第一件事不是看画质而是看条纹运动方向。方向对了说明光程差模型和参数扫描顺序都对方向反了说明要么 R_list 写反要么 delta 表达式符号有问题要么光程差公式漏了项。用暗纹半径公式 r_k √(k·λ·R) 直接分析R 从 0.5m 增大到 2.5m所有级数 k 的暗环半径 r_k 都按 √R 的比例同步放大。固定看某一级暗环它的位置会从较小的半径向外移动与此同时原本因为半径太小而挤在中心附近的高阶环随着 r_k 变大不断显形看起来就是新条纹从中心不停地冒出来。整体视觉是条纹从中心涌出然后向边缘扩散。反过来如果 R 从 2.5m 减小到 0.5m所有暗环半径收缩最靠近中心的高阶环先塌进中心消失条纹看起来是向中心缩进去然后一级一级“湮灭”。这是判断仿真是否物理正确的第一个指标发现条纹在往里缩而你的扫描方向明明是从小到大先检查 R_list 是不是反了再检查 delta 里是不是漏了 lambda/2或者把 cos 换成了 sin。波形方向确认无误后再去调画质这个顺序不要颠倒——很多新人先把画面调好看再管物理对不对结果光强分布是错的课堂提问时一问就露馅。4. 牛顿环动态仿真的四个典型坑从条纹“毛线团”到动图卡顿这一章每个坑都是动手做过一遍的人容易踩到的按“现象 → 原因 → 解决”的格式整理。它们大多不涉及复杂原理但足以让动态仿真从“好像对”变成“完全不对”。4.1 条纹稠密得像毛线团单位混用是头号嫌疑现象图像里全是密密麻麻的细条纹中心区域糊成一团完全看不出牛顿环的环形结构像一块高频干扰图。原因绝大多数情况是单位混用。r²/R 这一项里r 是网格坐标单位是米R 是曲率半径单位也是米两者相除得到米的量级才和 λ589e-9 匹配。有人把波长直接写成 589nm 忘记除以 1e9或者把曲率半径写成了 589e-3把 mm 当 m 用光程差一下子错了好几个数量级cos² 里的相位扫过成千上万个周期画面上自然全是密到无法分辨的条纹牛顿环结构直接消失。解决写代码前先做量级估算。δ r²/R λ/2 里的两项应当在同一个数量级附近如果算出来 δ 比 λ 大几个数量级说明参数单位没统一。另一个快速排查办法是看第一帧中心区域如果连中心附近都密到无法分辨基本可以断定是量级问题而不是物理公式写错。把 lambda 改成 589e-9R 保持用米再跑一次即可。4.2 中心是亮斑不是暗斑半波损失不是可选项现象条纹形态一切正常明暗环清晰但中心位置是亮斑和实验中看到的牛顿环中心暗斑相反。原因光程差公式少了半波损失项。反射式牛顿环里空气膜上表面反射的光是从玻璃进入空气属于光密到光疏无额外相位下表面反射的光是从空气进入平板玻璃属于光疏到光密反射时附加 π 相位等效 λ/2 光程差。接触点处空气膜厚度为 0本应只有这 λ/2 的光程差相位差为 π干涉极小中心必须是暗的。漏掉这一项中心相位差为 0干涉极大就变成了亮斑。解决在光程差表达式里加上 lambda/2写成 delta r2 / R lambda/2。还有一个隐蔽的变体有人加了半波损失但光强公式用了 sin²。半波损失让中心相位差为 πsin²(π) 0 也能得到暗斑看起来对了但往外的每一级明暗位置全部偏移了半个周期。自查方法中心点 r2 0 时delta lambda/2I cos²(π/2) 0这就是暗斑。如果中心不够暗把光强公式换成 cos² 再试。4.3 动图一帧一卡分辨率、帧数与延时在互相打架现象生成的 GIF 能正常打开但播放一顿一顿或者文件体积大到几十上百 MB插进 PPT 后拖不动。原因GIF 是 8 位索引色格式单帧分辨率、总帧数和帧间延时三者共同决定体积与流畅度。常见的组合是“800×800 分辨率 × 120 帧 × 0.02 秒延时”体积瞬间爆炸播放时解码也吃力。另外颜色量化会在环形边缘产生横向色带伪影亮暗过渡处出现一圈一圈的断层看起来像画质坏了。解决给 GIF 设三层约束。单帧分辨率不超过 400×400帧数在 24 到 48 之间DelayTime 不小于 0.06 秒。如果一定要高清长过程就不要用 GIF改用 VideoWriter 写 AVI分辨率保持 800×800 甚至更高颜色深度也更好。输出目标推荐方案单帧分辨率帧数延时PPT 插图GIF400×40024~480.08s高清过程记录AVI/MP4800×800不限录制帧率 30fps实时交互屏幕重绘500×500按刷新率无固定值4.4 条纹半径与理论值对不上视场宽度和采样分辨率不匹配现象用图像去量第 k 级暗纹的半径代入 r_k √(k·λ·R) 计算发现误差超过 10%而且越靠外圈误差越大。原因两个常见因素。一是视场取了 8mm 甚至更大外圈条纹在图像里的间距只有 2~3 个像素极小值位置定位误差直接吞掉了真实半径二是像素分辨率设低了外圈条纹欠采样出现混叠环带边缘变模糊量出来的半径自然对不上。解决先定目标级数再定视场宽度。量到第 10 级暗纹时让视场边缘刚好装下第 10 级按“单级暗环至少占 30 个像素”来选分辨率。定位暗纹时不要用整张图找极小值画经过中心的径向灰度剖面用 findpeaks 找极小值位置精度高很多% 取图像中心行的灰度剖面定位暗纹极小值位置 profile_row I(round(size(I,1)/2), :); % 中心行灰度 [~, locs] findpeaks(-double(profile_row)); % 灰度极小值 暗纹位置 % locs 是像素列坐标换算成径向半径后再与 sqrt(k*lambda*R) 对比注意 findpeaks 默认找极大值对灰度剖面取负号后原来的极小值变成极大值。换算半径时记得减去中心像素坐标乘上 L/pixels 的比例系数再与理论值逐级比对。findpeaks 属于信号处理工具箱没有这个工具箱就自己扫一遍数组比较相邻采样点的大小来定位极小值。误差在 1~2 个像素内正常超过 5 个像素就要回去检查视场设置。5. 让动图“会对话”滑块实时调参与理论校验5.1 拖滑块即时看变化把固定扫描变成可交互的光学实验台动态 GIF 是录好的参数过程想换 R 就得重新生成。进阶做法是放几个滑块实时重绘拖动 R 或折射率 n画面即时刷新学生能自己试出规律。下面是最小交互版拖动 R 滑块只重算光强并替换图像数据L 5e-3; pixels 500; x linspace(-L/2, L/2, pixels); [X, Y] meshgrid(x, x); r2 X.^2 Y.^2; lambda 589e-9; n 1.0; % 空气膜折射率默认空气 % 预计算光强矩阵并显示 R0 1.0; I0 uint8(cos(pi * (n * r2 / R0 lambda/2) / lambda).^2 * 255); fig figure(Color, k, Position, [100 100 650 650]); h_img imshow(I0, Border, tight); % 滑块回调改动 R 时只更新 CData不重建图像 uicontrol(Style, text, String, R (m), ... Position, [50 30 60 20], ForegroundColor, w, BackgroundColor, k); uicontrol(Style, slider, Min, 0.3, Max, 2.5, Value, R0, ... Position, [120 30 300 20], ... Callback, (src, ~) set(h_img, CData, ... uint8(cos(pi * (n * r2 / src.Value lambda/2) / lambda).^2 * 255)));关键在回调里只更新 CData不重建图像对象匿名回调捕获 r2、n、lambda省去重复读变量。滑块 Min 取 0.3、Max 取 2.5太小条纹间距快速变大视场只剩两三圈环太大条纹全部堆在中心演示效果反而差。把 n 也做成滑块还能顺手演示折射率增大导致条纹收缩交互体验比 GIF 更像一个验光实验台。5.2 自己给自己验收用理论半径校验每一帧仿真结果动态仿真做出来后我最看重的验收动作是把理论暗纹半径叠到仿真图上。取当前帧的 R、λ、n用 r_k √(k·λ·R/n) 算前 10 级暗纹位置换算成像素坐标在图上画半径标尺。偏差超过半条条纹宽就回去查量纲、查半波损失、查 n 有没有写进公式。我这几年做教学仿真的习惯是先让理论值打印在 title 里再让仿真结果去追理论值截图存档时两者同框事后翻记录也不会搞混是哪组参数产出了哪张图。先跑静态版确认中心暗斑和环数再上 GIF 确认条纹运动方向最后加滑块交互每一步都有固定检查项踩坑也能快速定位。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑