☰
基于自适应遗传算法的波前编码相位掩模优化实现大视场显微镜扩展景深
2026/10/3 7:52:49 网站建设 项目流程

简介:面向光学工程、图像处理及生物医学工程背景的科研人员与工程师,这套关于自适应遗传算法波前编码掩模优化的资料,聚焦大视场显微镜系统的景深扩展问题。内容为1个PDF文档,压缩包仅981KB,便于快速获取核心思路与可运行代码。已有87人学习,适合熟悉Python编程和基本优化算法的技术人员。资源围绕自适应遗传算法、波前编码与相位掩模优化展开,阐述如何在不改变光学系统结构的前提下将景深扩展约±13倍,分辨率由6.20微米变为7.81微米,同时抑制像差与视场影响。PDF中包含详细可运行的Python代码框架及中文解释,覆盖自适应遗传算法类实现、MTF与点扩散函数分析、制造约束建模、环境鲁棒性设计及深度学习解码模块,可辅助复现论文结果,并拓展至数字PCR、生物显微、内窥镜等对高景深与稳定性要求较高的实际场景。

1. 大视场显微镜的景深困局:波前编码掩模为什么值得用自适应遗传算法重做

一台大视场显微镜一旦把视场做大,景深就被光学不变量死死压住。换高倍物镜想兼顾分辨率,景深掉到微米级,稍厚一点的样本就出现“中心清楚、边缘发虚”的尴尬。波前编码(Wavefront Coding)在光瞳面放一块特殊相位掩模,把离焦敏感度摊平成一种工程上的“离焦不敏感”,再靠软件复原把中间图像解码成清晰像,这就是扩展景深(EDOF)设计的基本路径。传统做法直接套三次相位板,参数靠查表或手动试。而自适应遗传算法要做的事,是把这块掩模的相位分布当成优化问题去解,让它适配你手上那台显微镜真实的数值孔径、波长和视场约束。这篇笔记就按“理论建模 → 算法实现 → 代码参数 → 踩坑排错 → 加工验证”的顺序,把整个流程讲清楚,适合光学工程师、做显微成像重建的同学,以及被景深问题折磨的实验人员。

2. 波前编码的建模基础:光瞳离散化、离焦PSF与扩展景深评价

2.1 坐标系与光瞳离散化:先决定圆形的抽样方式

优化掩模之前,得先把光瞳的数学表达定下来。常见做法是把显微镜物镜的光瞳面离散成一个二维网格,每个网格点对应瞳面上的一个采样位置。对圆形光瞳,最稳妥的方式是生成归一化坐标,让光瞳半径对应 ρ = 1,所有相位项都基于这个归一化坐标展开。离散化尺寸 N 直接决定后续衍射计算快慢,我一般先用 64×64 或 128×128 做粗优化,等遗传算法收敛趋势稳定后再换 256×256 精修。

import numpy as np from numpy.fft import fft2, ifft2, fftshift, ifftshift class PupilMask: def __init__(self, N=128, r_pupil=0.98): """ N: 光瞳网格边长,取偶数更省事 r_pupil: 归一化光瞳半径,留一点边缘容差防止混叠 """ self.N = N self.r_pupil = r_pupil x = np.linspace(-1.0, 1.0, N, endpoint=True) X, Y = np.meshgrid(x, x) self.RHO = np.sqrt(X**2 + Y**2) # 归一化径向坐标 self.THETA = np.arctan2(Y, X) # 方位角,范围 [-pi, pi] self.circ = (self.RHO <= r_pupil).astype(float) # 圆形孔径掩模

这段代码的核心是同时生成径向坐标RHO和方位角THETA,后面写相位多项式时会反复用到。r_pupil不要直接设成 1.0,我习惯留 0.98,防止边缘采样点贴近边界后在 FFT 里产生振铃。注意np.linspace生成的网格是正方形边界,圆外部分后续乘上circ之后数值为 0,这就是离散化光瞳的标准做法。

2.2 用角谱法计算离焦PSF,而不是在空域硬算卷积

波前编码的核心思想:不改变光瞳的振幅透过率,只改变相位分布。光瞳函数写为 P(ρ,θ) = circ(ρ) · exp[j·φ(ρ,θ)]。加上离焦以后,波前像差里会多出一项二次相位项,即离焦项 W20·ρ²。这里 W20 是离焦波像差系数,单位为波长。

计算离焦PSF,工程上最常用的方式是角谱法。把瞳函数看作频域上的角谱分布,相干PSF等于光瞳函数的傅里叶变换模的平方;非相干情况下,PSF直接取这个结果的模方。也就是说:

h(ρ; W20) = |FFT{ P(ρ) · exp[j·k·W20·ρ²] }|²

这里的 k = 2π/λ。这个近似在显微镜物镜的数值孔径下足够准确,而且能直接把离焦参数塞进瞳函数里,做批量计算时非常快。

def psf_at(self, coeffs, w20): """ coeffs: 掩模相位多项式系数 w20: 离焦波像差系数,单位是波长倍数,比如 0.5 表示半个波长 """ phi = self.phase(coeffs) # 掩模引入的相位 phi_defocus = self.k * w20 * self.RHO**2 # 离焦相位项 P = self.circ * np.exp(1j * (phi + phi_defocus)) h = np.abs(ifft2(fftshift(P)))**2 h = fftshift(h / h.sum()) return h

这里有个容易翻车的细节:fftshift(P)放在 IFFT 之前,是让光瞳阵列的零频回到中心,算出来的PSF才能对中。如果先 IFFT 再 shift,得到的PSF中心会在角落。这个顺序我每次写都要检查一遍。h /= h.sum()归一化很重要,否则后续 OTF 计算和适应度函数会受总能量影响,导致寻优方向不稳。

2.3 用FLPD评价掩模质量:同时盯住景深和分辨率

波前编码的掩模不是随便哪个相位分布都行。评价一个掩模好坏,传统指标是 Strehl 比,但 Strehl 比只反映峰值强度,对“离焦后成像是否还能复原”不敏感。更贴合 EDOF 设计的目标是 Fisher Information 与潜分辨率的乘积,即 FLPD 指标。FLPD 高,说明系统在保持一定分辨能力的前提下,对离焦变化不敏感。

纯理论 FLPD 计算需要求 OTF 对离焦参数的偏导,实现起来繁琐。我实际做的时候用一个工程近似:固定所有掩模参数,计算一组离焦量下的 OTF,然后用“离焦变化量 + 参考焦面频谱能量”两个维度的组合来逼近 FLPD 的行为。这个近似虽然没有严格的 Fisher 信息数值,但对遗传算法寻优来说,方向性足够。

def otf_at(self, coeffs, w20): h = self.psf_at(coeffs, w20) H = fftshift(fft2(h)) return H / np.abs(H).max() # 峰值归一化,方便比较 def fitness(self, coeffs, w20_list=None, alpha=0.25): if w20_list is None: w20_list = np.array([-2.0, -1.0, -0.5, 0.0, 0.5, 1.0, 2.0]) H_list = np.array([self.otf_at(coeffs, w) for w in w20_list]) H_ref = H_list[len(H_list) // 2] # 以中间离焦面为参考 power = np.abs(H_ref)**2 + 1e-12 var = np.mean(np.abs(H_list - H_ref)**2 / power) # 高频能量占比,用径向频率加权体现分辨率 u = fftshift(np.fft.fftfreq(self.N, d=1.0 / self.N)) U, V = np.meshgrid(u, u) FREQ = np.sqrt(U**2 + V**2) freq_mask = (FREQ > 0.05) & (FREQ < 0.5) energy = np.abs(H_ref)[freq_mask].mean() return energy - alpha * var

适应度函数返回的是能量 - α·离焦变化量,遗传算法会往这个数值大的方向进化。这个近似的意义在于:能量项保证掩模没有把高频信息全丢掉,离焦变化量保证 OTF 对不同离焦面不那么敏感。α 是一个平衡系数,我通常给 0.2 到 0.5,视仿真结果来回调。

2.4 从三次相位板出发构造初始种群

自适应遗传算法需要一个初始种群,而这个种群不该是纯随机数。波前编码领域最经典的掩模是三次相位板,相位函数 φ = α(ρ³cos3θ) 或者 φ = α(x³ + y³)。三次相位板已经被证明能把离焦敏感性摊薄,所以从它附近随机生成初始个体,比完全随机撒点收敛快得多,也更不容易陷入没有物理意义的局部解。

我一般把初始种群设定成两种来源的混合:一部分个体直接是三次相位板的系数加上小幅扰动,另一部分在系数边界范围内做均匀随机。这样既保留了经过验证的结构先验,又给遗传算法提供了探索空间。后面主循环代码里会用init_population函数体现这个策略。

到这里,建模和评价的基础已经立住了:光瞳是二维离散网格,PSF用角谱法算,适应度是频域能量和离焦稳定性的加权组合,初始种群靠近经典解。下一章进入自适应遗传算法本身。

3. 自适应遗传算法优化掩模:代码框架、算子与参数表

3.1 掩模参数化编码

掩模的相位分布需要被表示成基因。这里我用一个六维实数向量,每一项对应一个多项式基底的系数。之所以用实数编码而不是二进制,是因为相位系数是连续量,实数编码能避免二进制串的“汉明悬崖”问题,也让交叉和变异算子更容易保持数值平滑。

相位函数定义为:

φ(ρ,θ) = a·ρ³·cos(θ) + b·ρ³·cos(3θ) + c·ρ²·cos(2θ) + d·ρ² + e·ρ⁴ + f·ρ³·cos(θ)

其中 a、b、c、d、e、f 就是被测的个体。这个基底选得比较杂,里面既有三次相位项,也有像散、球差类项。原因很简单:纯三次相位板在对称光学系统里效果不错,但大视场显微镜的边缘视场往往伴随离轴像差,需要引入非对称项来补偿。自适应遗传算法的价值恰恰在于它能根据适应度自动决定这些项的组合和权重。

def phase(self, coeffs): rho = self.RHO theta = self.THETA a, b, c, d, e, f = coeffs phi = (a * rho**3 * np.cos(theta) + b * rho**3 * np.cos(3 * theta) + c * rho**2 * np.cos(2 * theta) + d * rho**2 + e * rho**4 + f * rho**3 * np.sin(3 * theta)) return phi

注意代码里 f 项用了 sin(3θ),而不是 cos(3θ)。这是为了给相位分布提供旋转方向上的多样性。因为显微镜光瞳是圆对称的,cos 项和 sin 项在旋转对称系统里往往可以互相补充,让算法有更多机会找到非对称解。

3.2 自适应交叉与变异概率

常规遗传算法的交叉概率和变异概率是固定值,比如 PC=0.8、PM=0.05。这样做的问题在于进化后期,种群趋于收敛,个体适应度差异变小,固定的大交叉概率容易破坏已经找到的好解,小变异概率又很难跳出局部最优。自适应遗传算法的核心改进,是让 PC 和 PM 随个体适应度实时调整。

典型策略是 Srinivas 提出的公式:

PC = k1 * (f_max - f') / (f_max - f_avg) PM = k2 * (f_max - f) / (f_max - f_avg)

其中 f_max 是当前种群最大适应度,f_avg 是平均适应度,f' 是参与交叉的两个个体中较大的适应度,f 是当前个体的适应度。适应度接近最优的个体,交叉和变异概率自动降低,保护优秀基因;适应度较差的个体,概率提高,促使它大规模搜索。

实际做的时候要加下限,否则适应度最高的个体会完全不参与交叉和变异,导致进化停滞。我一般取 k1=1.0,k2=0.15,同时强制 PC 不低于 0.1,PM 不低于 0.02。

def adaptive_pc(f_max, f_avg, f_parent, k1=1.0, floor=0.1): if f_max - f_avg < 1e-12: return floor return max(floor, k1 * (f_max - f_parent) / (f_max - f_avg)) def adaptive_pm(f_max, f_avg, f_individual, k2=0.15, floor=0.02): if f_max - f_avg < 1e-12: return floor return max(floor, k2 * (f_max - f_individual) / (f_max - f_avg))

参数说明:adaptive_pc用于每一对父母,取两个个体里适应度较大的那个计算,如果这对父母已经很优秀,就降低交叉概率。adaptive_pm按个体计算,适应度越高变异越小。这个策略比固定参数在波前编码掩模优化上稳定得多,最直观的表现是适应度曲线后期不再剧烈抖动。

3.3 多视场加权适应度

标题里强调了“大视场显微镜系统”,这里有个单视场模型替代不了的难题:中心视场和边缘视场的像差特性不同,同一个掩模在轴上的表现和离轴的表现会有明显差异。如果只用中心视场做优化,得到的掩模会在边缘视场翻车。

常规做法是做视场抽样:选取中心、0.5 视场、0.7 视场、边缘视场这几个代表位置,分别计算 PSF 或 OTF,再按权重合并成总适应度。离轴视场通常权重更高,因为边缘本身成像质量就差,需要掩模补偿更多。

def multi_field_fitness(pupil, coeffs, field_weights, w20_list): total = 0.0 for field_idx, weight in enumerate(field_weights): # 离轴视场引入额外的相位偏移,简化为对光瞳相位加一个低阶倾斜项 tilt = 0.0 if field_idx > 0: tilt = 0.15 * field_idx pupil.tilt_phase = tilt total += weight * pupil.fitness(coeffs, w20_list) return total

这段只是展示加权思路:每个视场给一个权重,最后加权求和。真正做的时候,离轴视场的光瞳相位还会包含彗差、像散等视场相关项,需要从光学设计软件里导出。代码里用一个简化tilt代表离轴带来的波前偏移,用于说明逻辑,完整系统里应该替换成实际像差数据。

3.4 主循环代码

到这里,把所有零件组装成完整的自适应遗传算法主循环。种群规模我推荐 40 到 80,代数 150 到 250。个体选择用锦标赛选择,每轮从种群里随机抽 3 个个体,挑适应度最高的进入父代池,这样能维持选择压力又避免过早收敛。

交叉算子采用模拟二进制交叉(SBX),对这种连续参数优化比算术交叉更稳。SBX 的分布指数 η 取 2,生成的子代会围绕父代附近小范围展开,配合自适应概率不会破坏优秀个体。

def sbx_crossover(p1, p2, eta=2.0): mask = np.random.rand(p1.size) < 0.5 u = np.random.rand(p1.size) beta = np.where(u <= 0.5, (2 * u) ** (1 / (eta + 1)), 1.0 / (2 * (1 - u)) ** (1 / (eta + 1))) c1 = 0.5 * ((1 + beta) * p1 + (1 - beta) * p2) c2 = 0.5 * ((1 - beta) * p1 + (1 + beta) * p2) return np.where(mask, c1, p1), np.where(mask, c2, p2) def gaussian_mutation(individual, sigma=0.05, bounds=(-2.0, 2.0)): mutated = individual + sigma * np.random.randn(individual.size) return np.clip(mutated, bounds[0], bounds[1])

主循环结构如下:

def optimize_mask(pupil, pop_size=60, max_gen=200, dim=6, bounds=(-2.0, 2.0)): bounds_lo, bounds_hi = bounds pop = init_population(pop_size, dim, bounds) # 经典三次相位附近 + 随机解 fitness = np.array([multi_field_fitness(pupil, ind, field_weights, w20_list) for ind in pop]) best_sofar = None best_fitness = -np.inf for gen in range(max_gen): f_max = fitness.max() f_avg = fitness.mean() elites = pop[np.argsort(fitness)[-2:]] # 精英保留两个 new_pop = [] while len(new_pop) < pop_size - 2: p1, p2 = tournament_select(pop, fitness, k=3) pc = adaptive_pc(f_max, f_avg, max(fitness[idx1], fitness[idx2])) if np.random.rand() < pc: c1, c2 = sbx_crossover(p1, p2) else: c1, c2 = p1.copy(), p2.copy() pm = adaptive_pm(f_max, f_avg, fitness[idx1]) if np.random.rand() < pm: c1 = gaussian_mutation(c1) pm2 = adaptive_pm(f_max, f_avg, fitness[idx2]) if np.random.rand() < pm2: c2 = gaussian_mutation(c2) new_pop.extend([c1, c2]) pop = np.vstack([np.array(new_pop[:pop_size - 2]), elites]) fitness = np.array([multi_field_fitness(pupil, ind, field_weights, w20_list) for ind in pop]) if fitness.max() > best_fitness: best_fitness = fitness.max() best_sofar = pop[fitness.argmax()].copy() return best_sofar, best_fitness

这段代码的逻辑说明:每一代先用锦标赛选择挑父代,再根据父代的适应度动态决定是否交叉、是否变异。精英保留两个最优个体直接进入下一代,避免最优解被交叉变异破坏。init_population里混入三次相位板附近个体和随机个体,是让初始种群既不过度单一也不完全盲目。参数说明:pop_size=60是我在大视场显微镜场景下常用的值,如果视场抽样点很多,可以考虑加到 80;max_gen=200对六维实数参数通常足够,超过 200 代后多数情况只是在小范围内微调。

3.5 参数推荐表

下面这张参数表是我在多个掩模优化仿真上摸过的经验值,可以直接作为第一版尝试的起点。

参数推荐值说明
光瞳网格 N64 粗优化 / 128 精优化256 仅在最终验证时用
种群规模60参数维度低,种群不用太大
最大代数200连续 30 代无改进就提前终止
交叉分布指数 η2.0SBX 专用,偏局部搜索
变异高斯扰动 σ0.05系数范围是 [-2, 2] 时适用
α(适应度平衡系数)0.25能量项和离焦敏感性之间折中
视场权重中心 1.0,0.5视场 1.2,边缘 1.5边缘视场本身像差大,需要更多优化预算

提示:这些参数不是物理定律,是出发值。每次换物镜或换波长,α 和视场权重基本都要重调,后面避坑章节会详细讲怎么判断参数设错了。

4. 波前编码掩模优化避坑:五个常翻车的现象与排查

4.1 优化到最后最优解全是零相位

现象:遗传算法跑完,返回的系数全部接近 0,相当于没有掩模。适应度曲线确实在上升,但最终结果毫无意义。

原因:适应度函数里能量项占主导,而没有任何相位时 OTF 在参考焦面上能量最高,离焦变化量的惩罚加权不够。遗传算法发现“什么都不做”就是当前目标下的最优解。这是波前编码优化里最容易踩的坑,本质原因是掩模的目的是牺牲一点焦内质量换取离焦宽容度,但适应的度函数只奖励后者而没有惩罚前者。

解决:一是把适应度函数改成相对基准比较,不要把绝对能量放在目标函数里,而是计算加掩模后的离焦稳定性和无掩模系统的离焦稳定性之差;二是对掩模相位幅度加一个软约束惩罚,比如penalty = -lambda_coeff * (np.sum(coeffs**2)),让遗传算法必须付出“相位代价”才能换取稳定性的收益。我常用第二个方案,λ 从 0.01 起调。

4.2 迭代到 100 代之后适应度纹丝不动

现象:前 50 代适应度快速上升,到后面曲线变成一条平线,怎么跑都突破不了。

原因:种群多样性耗尽。自适应概率保护高适应度个体导致优秀个体快速占据种群,交叉产生的新个体和父代太像,变异步长 0.05 在这个阶段已经无法帮助个体跳出局部最优。

解决:做“自适应重启”,每 30 代检测一次f_max - f_avg,如果小于某个阈值,保留最优个体,其余个体用三次相位板附近重新初始化;或者把变异 σ 临时调大到 0.3 跑 5 代,再恢复 0.05。我在实际代码里常用前者,因为重启能带来更大的搜索步幅。

4.3 仿真PSF和实验PSF对不上

现象:仿真里掩模表现完美,图像复原效果很好,但同样的掩模装到显微镜上,拍出来的中间图像和仿真完全不是一回事。

原因:这是一个三因素叠加问题。第一,仿真里默认波长是单色光,实际光源有带宽,而波前编码掩模的相位是波长的函数,不同波长的相位延迟不同;第二,光瞳网格的采样间隔没有对应到真实的像元尺寸,导致 PSF 的空间尺度不对;第三,掩模的对准误差,比如偏心或旋转,会直接改变相位分布。

解决:仿真阶段就用平均波长加带宽做多波长加权优化,而不是单波长算到底。加工装调时用无掩模的 PSF 做基准,测量实际 W20 值,再替换到仿真里重新评估。如果实验 PSF 和仿真 PSF 的半高全宽对不上,优先怀疑光瞳采样率而不是算法。

4.4 适应度函数过于平滑,算法像在瞎猜

现象:随机生成的初始种群适应度几乎全部相同,选择压力起不来,遗传算法前几十代都在原地打转。

原因:OTF 本身是一个平滑函数,峰值归一化后,不同掩模参数下的能量差异可能只有百分之几。适应度函数里如果只取均值,微小的差异会被噪声淹没。

解决:把 OTFO 的频率轴做对数加权,或者直接对 OTF 取对数后再算差值。np.log10(np.abs(H) + 1e-6)能把低频和高频的能量差异放大。还有一个工程技巧:适应度计算时每次固定种子,保证同一组参数在同一次运行里适应度可重复。否则随机数波动会掩盖真实差异。

4.5 多视场加权后边缘还是糊

现象:加了视场权重,优化出来的掩模在中心视场挺好,边缘视场的中高频仍然明显衰减,复原后边缘图像抹得厉害。

原因:离轴视场的光瞳相位不只是加一个倾斜项那么简单。实际大视场显微镜的边缘视场存在场曲、彗差、像散等复杂波前误差,如果仿真里只用一个 tilt 近似,遗传算法根本感知不到真实边缘视场的恶劣条件。

解决:从光学设计软件里以 Zernike 系数形式导出各视场波前误差,作为多视场仿真里的真实光瞳相位基底。我的习惯是至少取中心、0.5 视场、0.7 视场和全视场四个抽样点,边缘视场权重给到中心视场的 1.5 倍以上。这个数据质量和权重设置直接影响最终掩模在真实系统上的表现,偷懒不得。

5. 从优化结果到实拍恢复:重建算法、加工校验与我的调试习惯

5.1 用合成模型数据验证掩模:离焦栈生成与Wiener重建

拿到最优掩模系数后,第一步不是直接加工,而是用合成数据做端到端验证。生成一个高分辨率测试图,比如分辨率板图案或随机纹理,分别用不同离焦量下的 PSF 卷积,加入适量高斯噪声,得到离焦图像栈。然后对图像栈做 Wiener 滤波重建。

Wiener 滤波在频域的实现非常直接:

def wiener_deconvolution(image_stack, otf_stack, noise_power=0.01): numerator = np.zeros_like(otf_stack[0], dtype=complex) denominator = np.zeros_like(otf_stack[0], dtype=float) for img, H in zip(image_stack, otf_stack): I = fft2(img) numerator += np.conj(H) * I denominator += np.abs(H)**2 H_hat = numerator / (denominator + noise_power) return np.abs(ifft2(H_hat))

这里的noise_power是正则化参数,取 0.0001 到 0.01 之间,取决于噪声水平。它同时是所有离焦面OTF的合成孔径合并,本质是把多个离焦面在不同频率上的信息互补起来。如果重建结果在离焦范围两端都保持清晰,这个掩模才算真正达到了设计目标。

5.2 掩模实物加工与对准检查

仿真通过后进入加工环节。相位掩模通常做在光学玻璃基底上,用灰度光刻和离子束刻蚀把相位分布转成浮雕结构。相位幅值换算有个最基本的公式:刻蚀深度 d = λ / (n - 1),其中 n 是基底折射率。熔石英在 550nm 波长下 n≈1.46,2π 相位对应深度约 1.03μm。

加工成离散多台阶后,掩模的相位分布会和连续理想分布有偏差。我的做法是把台阶化的相位分布重新回到仿真里算一遍 OTF,看看实体化的掩模比连续相位掩模掉了多少性能。如果衍射效率下降超过 20%,就需要增加台阶数,或者换用连续灰度光刻工艺。对准检查方面,掩模装到光瞳共轭面后如果偏心超过光瞳半径的 1%,很容易引入额外彗差,直接的表现是复原图像出现方向性模糊。

5.3 我的调试顺序和最后提醒

整个流程跑通后,我一般固定一套固定的调试顺序:先用 64 网格跑 50 代粗看适应度曲线是否正常,再换 128 网格跑完整 200 代,拿到最优系数后立刻存档,连同每一代的最优个体和适应度曲线都保留下来。这比只存一个最终结果聪明得多,因为一旦发现加工出来的掩模有问题,还能回头往历史种群里找替代个体,不用重跑整个算法。这个习惯救过我很多次,算是用血泪经验换来的后悔药。

重建阶段如果发现图像边缘还是有一圈模糊,第一反应不是调算法,而是检查掩模和光瞳的对准状态。波前编码是个软硬件强耦合的系统,任何一端的松动都会让最终输出变得糟糕。先把无掩模状态下拍摄的PSF和仿真基准对比一遍,绝大多数“玄学问题”其实都出在W20标定或者光瞳采样不一致上。

希望这套从优化到验证的流程能帮你在自己的大视场显微镜系统里少走几步弯路。扩展景深设计最忌讳一步到位直接上硬件,花两天时间把仿真链路调通,后面加工和装配会省下一个量级的时间。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询