简介:《微透镜阵列光学实现卷积运算.docx》是一份面向光学信息处理与深度学习硬件加速方向研究者的技术文档,系统阐明了利用微透镜阵列(MLA)与透镜组合在光学层面模拟二维离散卷积的原理与系统设计。文档从卷积运算在图像平滑、锐化及CNN中的基础作用切入,结合same、valid、full三类卷积的矩阵展开,详细解释了基于MLA的匀光系统、P2平面强度调制(超表面)与成像系统如何共同实现卷积核权重分配和窗口内求和,同时给出了系统结构示意图、窗口划分和P2处分布等关键图示。资源共包含1个docx文档,压缩包大小约207KB,适合对光学计算、光学卷积神经网络(ONN)或相关课程设计有阅读需求的读者,既可获取从系统设计到矩阵理论验证的完整思路,也可作为光学硬件加速方向的学习参考。该文档已有120人学习,内容侧重原理推导与可行性分析,文中矩阵解释(酉矩阵与奇异值分解)进一步支撑了系统可实现任意正值传输矩阵的理论基础。
1. 微透镜阵列做卷积,等于把空间频谱切成多路并行
一张 512×512 的灰度图和 3×3 卷积核相乘,数字域至少要做约 200 万次乘加,在边缘 AI 芯片上还要反复搬运数据。而光学 4F 系统用一片透镜做傅里叶变换,把卷积变成频谱面上的相乘,整个操作在光速内结束。这个方案的瓶颈不是速度,而是单透镜系统一次只能执行一个固定卷积核,无法支撑卷积神经网络里动辄几十上百个通道的并行需求。微透镜阵列把一个大孔径拆成数百个微米级子透镜,每个子透镜成了一个独立的傅里叶变换通道,等于把单线程的光学 4F 系统变成并行流处理器。这篇内容围绕微透镜阵列光学实现卷积运算展开,讲清两种主流架构、最小验证光路的搭建方法、可编程化改造路径以及验收指标。微透镜阵列 3D 成像原理中的子孔径分割能力,在这里被拿来分割频率面,而不是分割视场,适合正在做光学 AI 加速器、机器视觉前端预处理的同行参考。
2. 微透镜阵列做卷积的两种主流架构与选型参数
2.1 架构一:在傅里叶平面按子孔径分组执行滤波
经典的光学卷积实现来自 4F 系统。输入图样 f(x,y) 经过第一枚透镜做傅里叶变换,在频谱面得到 F(u,v)。如果在频谱面放置复振幅透过率为 H(u,v) 的滤波元件,第二枚透镜再执行一次逆傅里叶变换,输出就是 f 与 h 的卷积 g = f ⊛ h,其中 h 是 H 的逆傅里叶变换,也就是卷积核。卷积核的形状、大小和频响完全由频谱面滤波元件的透过率分布决定。
单透镜 4F 系统的软肋在于频谱面是一个连续平面,一个滤波器件只能对应一个固定核。微透镜阵列的介入方式,是在频谱面后放置透镜阵列,让每个子透镜承担频谱面上的一小块局域区域。每个子透镜在这个区域内独立施加滤波函数,将结果投射到输出面的不同坐标。这样 M×N 个子透镜就同时执行 M×N 个不同的滤波,相当于把单一卷积核升级成了多核并行卷积。这里的并行度不是时分复用或波分复用,而是真正的空间并行,所有通道同时曝光、同时积分。
这种架构和微透镜阵列 3D 成像原理有不少相似处。光场相机里,微透镜阵列分割的是瞳孔或视场,每个子图像携带不同角度的光信息;而在卷积运算中分割的是频率面,每个子区域对应一个空间频段。对照理解会发现,微透镜阵列的本质是“把一个连续光场切分成多路通道”,至于通道里运输的是视差还是频率成分,完全取决于它放在光路的什么位置。
2.2 架构二:在空间域做分块重叠卷积
第二种做法不碰频谱面,而是把微透镜阵列当作空间域的分块器。物体被微透镜阵列成像为一组子图像,每个子图像承载场景不同位置的局部信息。对每个子图像单独执行卷积,再把结果拼回完整图像,这对应数字图像处理中的分块卷积,也叫 tiled convolution。这种方式的优势在于卷积核可以很小,3×3 或 5×5 都能工作,数值稳定,而且不容易受频谱采样分辨率不足的影响。
但直接分块会在子图像边界产生卷积伪影,因为子图像截断了邻域信息。常见做法是让相邻子透镜的子图像区发生重叠,重叠宽度至少是卷积核尺寸的一半,然后用加权平均融合边缘。代价是输出分辨率下降,微透镜节距和重叠量之间需要按实际卷积核大小做折中。在微透镜阵列作为光学卷积加速器的工程实现里,空间域分块比傅里叶域滤波更容易调试,因为每个子通道独立成像,串扰更小,适合验证原型。
2.3 选型参数:先定子孔径尺寸和微透镜节距
无论选哪种架构,微透镜阵列的参数都直接决定卷积结果的分辨率和并行度。下面是一张常用的选型参考表:
| 参数 | 建议范围 | 选择依据 |
|---|---|---|
| 子透镜节距 p | 25~500 μm | 决定频段划分粒度,p 越小并行通道越多,但衍射弥散斑变大 |
| 子透镜 F 数 | 2~8 | 焦距 f = p×F,决定焦平面滤波片可加工的最小特征尺寸 |
| 子孔径数 M×N | 4×4 到 32×32 | 并行卷积核的数量,受靶面尺寸和光照均匀性约束 |
| 基底材料 | BK7 / 石英 | 可见光用 BK7,近红外用石英,注意各自透过率和热膨胀系数 |
| MTF 指标 | ≥0.3 @ 奈奎斯特频率 | 低于此值,卷积结果会被系统的调制传递函数显著抹平 |
节距 p 是最核心的参数。p 越小,单个子透镜通光孔径越小,衍射极限角分辨率越低,能分辨的频谱细节越少。实际计算从衍射极限出发:最小可分辨特征尺寸 d = 1.22λF。以 λ = 632nm、F = 4 计算,d 约为 3.1μm,滤波掩模的特征尺寸必须大于这个值,否则该频率分量直接损失。换句话说,卷积核若想保留高频锐边,F 数不能选太大。
选完参数后,先在数字域把光路跑一遍很有必要。下面这段代码模拟微透镜阵列在频谱面分块滤波,用来判断 M×N 的分块策略是否合理:
import numpy as np from numpy.fft import fft2, ifft2, fftshift def mla_conv(image, kernel_list, M=4, N=4): """ 模拟频谱面上 M×N 微透镜阵列分块滤波。 image: 二维灰度图 kernel_list: 按行优先排列的 M*N 个卷积核 """ h, w = image.shape sub_h, sub_w = h // M, w // N F = fftshift(fft2(image)) # 全孔径傅里叶频谱 out = np.zeros_like(F, dtype=complex) for i in range(M): for j in range(N): # 每个子透镜获取自己负责的频段 sub_F = F[i*sub_h:(i+1)*sub_h, j*sub_w:(j+1)*sub_w] kernel = kernel_list[i*N + j] # 将卷积核补零到与子孔径等大 kp = np.zeros((sub_h, sub_w)) kh, kw = kernel.shape kp[:kh, :kw] = kernel # 对补零后的核做傅里叶变换得到频域滤波函数 H = fft2(fftshift(kp)) out[i*sub_h:(i+1)*sub_h, j*sub_w:(j+1)*sub_w] = sub_F * H g = ifft2(fftshift(out)) return np.real(g)kernel_list 里的每个二维数组代表一个子透镜通道的卷积核,按行优先排列。fftshift 把卷积核移到频域中心再做傅里叶变换,避免中心偏移带来的相位倾斜。运行后重点看两件事:一是输出图像在子块边界有没有明显跳变,二是恢复出的空间分辨率是否满足下游任务。如果 M 和 N 取值过大,每个子频段只分到很少的像素点,输出会出现“砖墙感”,这时说明子孔径分得太多,卷积核的频域支撑不足。
3. 搭一套最小验证光路:器件、对准与三步定位
3.1 器件清单与布局
搭建目标不是做产品级加速器,而是验证微透镜阵列确实能完成卷积。建议从 2×2 阵列起步,只使用四个子透镜,降低调试难度。基本器件清单如下:
- 激光源:5mW 氦氖激光器或半导体激光器,波长 632nm,单模光纤输出更稳定
- 准直扩束组件:使输出光斑直径大于输入图样对角线
- 输入图样:铬版光掩膜,上面是二值图;也可以用透射式空间光调制器输出动态图
- 傅里叶透镜 L1:焦距 100mm,口径 25mm,把输入图样变换到频谱面
- 微透镜阵列:节距 1mm,F=4,2×2 阵列,安装在六维调节架上
- 滤波掩模:紧贴微透镜阵列焦平面的振幅或相位片
- 傅里叶透镜 L2:焦距 100mm,与 L1 组成 4F 结构
- 输出 CMOS:像素尺寸 3.45μm,分辨率为 1280×1024,放在 L2 焦面采集
常见做法是把微透镜阵列放在 L1 的焦平面上,让每个子透镜各自对焦。严谨一点说,L1 先在全孔径上形成傅里叶频谱,微透镜阵列把频谱面分割成多个子区域,再由每个子透镜做一次二次傅里叶变换。因此 L1 的焦距决定频谱面大小,子透镜的焦距决定滤波片尺寸,两者要匹配。
3.2 搭建步骤
第一步:固定 L1 和光源,用刀口法找 L1 后焦面。把 CMOS 放在后焦面,看到的光斑就是输入图样的傅里叶频谱分布。此时应能观察到中心零频亮斑和周围的高频细节。
第二步:把微透镜阵列装到 L1 后焦面,微透镜面朝向 L2。让频谱中心落在四个子透镜的交界处,这样四个子透镜分别得到零频附近四个象限的频谱成分。调节倾斜角,使四象限频谱强度分布对称。
第三步:放置 L2,使 L2 的前焦面与微透镜阵列的滤波平面重合。这一步最容易出错,也最关键。如果 L2 前焦面没有和子透镜焦平面重合,逆傅里叶变换会在错误距离上执行,输出图像直接模糊一片。可以用 CMOS 前后移动找最清晰成像点,找到后用最小步进调节架锁住。
3.3 用点扩散函数判断光路是否对准
对准不需要一步到位,用点光源代替输入图样,观察输出面的点扩散函数:
- 点扩散函数呈单个亮斑,说明四个通道的相位基本一致,光路对准程度可用
- 出现四个分开的亮斑,说明各子透镜通道存在横向偏移,需要平移微透镜阵列或调整入射角
- 亮斑带有拖尾,说明滤波掩模距离子透镜焦平面过远,或者 F 数与波长不匹配
对卷积运算来说,点扩散函数的形状理论上就是卷积核的光学实现。通过逐个遮挡子透镜,可以独立检查每个通道的滤波行为。如果某一个通道的输出与预期核形状不符,优先排查该子透镜对应的掩模区域是否有灰尘、刻蚀缺陷或相位偏置。
这里给一个快速判定方法:用一条竖直亮线作为输入,采用水平方向的三点平滑核,输出应得到水平方向展宽的条形光斑。如果在 CMOS 上看到的是竖直方向展宽,说明微透镜阵列相对输入旋转了 90 度,旋转阵列架使核方向归一。
4. 可编程方向:SLM 与微透镜阵列结合的相位校正
4.1 把固定掩模换成空间光调制器
上一章的滤波掩模是固定的,对应一个固定卷积核。要做卷积神经网络推理,必须在线切换卷积核。常见做法是用液晶空间光调制器(SLM)替代振幅或相位掩模。SLM 放在子透镜焦平面位置,每个子透镜对应 SLM 上的一个子区域,通过加载不同灰度图案,改变每个通道的频域透过率 H(u,v)。
SLM 层面的坑在于像素化。常规反射式 SLM 像素间距约 3.74μm,灰度 8bit,相位深度 2π。而微透镜阵列的子透镜焦平面上,频谱尺寸可能只有几百微米,SLM 的可用区域只有几十乘几十个像素。如果滤波器的特征尺寸小于两个 SLM 像素,卷积核就体现不出来,相当于核被欠采样。规划时先把频谱半宽映射到 SLM 面板,必要时缩小 F 数或增加子透镜节距,让频谱更平缓。
4.2 纯相位编码比振幅调制更适合卷积
振幅调制会有严重的光能损耗,而且 SLM 的振幅调制本质上是偏振效应,效率和线性度受入射偏振态影响。用纯相位 SLM 加载相位调制,把复函数 H(u,v) 编码成相位全息图,是更高效的做法。常用双相位分解:把一个复值分解成两个等幅相位的叠加,代价是空间分辨率减半。或者用 GS 迭代算法生成纯相位分布,适合卷积核比较小、误差容限高的场景。
相位编码有一个额外的自由度:相位偏置可以同时修正微透镜阵列本身的加工误差。子透镜之间的光程不一致、SLM 液晶盒厚度梯度,都会带来通道间相位差。这个误差可以在数字域补,也可以在 SLM 上叠加常数偏置来校正。
4.3 三个必须处理的误差源
第一个是子透镜间相位不匹配。用干涉仪或相位恢复算法测量每个通道的相位差 Δφ_mn,再在 SLM 上叠加一个负偏置相位。下面这段代码演示了用低阶模式拟合相位误差的过程:
import numpy as np def fit_phase_correction(phase_error, n_modes=4): """ 对二维相位误差做低阶多项式拟合。 phase_error: 二维相位误差图,单位弧度 n_modes: 参与拟合的模式数,至少2 返回拟合系数和残差 """ h, w = phase_error.shape y, x = np.indices((h, w), dtype=np.float64) x = (x - w / 2) / (w / 2) # 归一化到 -1~1 y = (y - h / 2) / (h / 2) modes = [np.ones_like(x), # 平移 2 * x, # X 方向倾斜 2 * y] # Y 方向倾斜 coeffs = [] residual = phase_error.copy() for Z in modes: denom = np.sum(Z**2) c = np.sum(residual * Z) / denom coeffs.append(c) residual -= c * Z return np.array(coeffs), residual实际测量得到的 phase_error 可以先做低通滤波,去除高频噪声,再做拟合和剔除前几项低阶模式。平移项对应 SLM 上的常数偏置,倾斜项对应入射角度微调。残差最好小于 λ/10,否则会在卷积结果上表现为散斑状噪声。
第二个是频谱面采样不匹配。空间频率 u 与 SLM 像素坐标的关系是 u = x / (λf_sub),其中 f_sub 是子透镜焦距。必须保证子透镜孔径内的频谱范围不超过 SLM 可用区域的一半,否则高频频谱被截断,卷积核会发生振铃效应。
第三个是相邻通道串扰。当微透镜的 F 数偏大时,焦平面上 Airy 斑直径接近子透镜孔径,衍射光斑会渗入相邻通道。Airy 斑半径 r = 1.22λF,经验要求 r < p/4。当 p=1mm、λ=632nm 时,F 需要小于 8.1,超过这个值就要考虑改用更小 F 数的阵列或增加隔离槽。
5. 验证光学卷积结果的三个观测量与常见陷阱
光路搭好后,最先看的是点扩散函数。输入改为针孔光源,CMOS 上输出的亮斑形状就是系统实际执行的卷积核。拿这个形状和数字卷积核的傅里叶变换做对比,如果中心和主瓣位置一致,说明光学卷积已经生成。点扩散函数的半高宽如果明显大于理论值,多半是 F 数偏大或照明波长偏长,检查光源准直。
第二个观测量是子通道一致性。用一个均匀亮场作为输入,分别读取四个子通道输出的平均灰度和标准差,通道间的方差和应低于总能量的 3%。如果某个通道灰度明显偏暗,检查该子透镜对应的掩模区域是否有污损,或者入射角导致的光瞳切趾。
第三个观测量是旋转对称性。对于旋转对称的卷积核,比如高斯平滑,把输入图样旋转 180 度再卷积,输出应近似等于原输出翻转 180 度。这个检查容易实现,只需要在光路前加一个旋转架。违反对称性基本可以断定微透镜阵列安装时发生了面内旋转。
定量对比时用 PSNR 最直接,下面是计算函数:
import numpy as np def psnr(optical, digital, max_val=255): # 归一化到相同动态范围后再比较 optical = optical / optical.max() * max_val digital = digital / digital.max() * max_val mse = np.mean((optical - digital) ** 2) return 10 * np.log10(max_val ** 2 / mse)光路输出与数字模拟的 PSNR 超过 25dB,说明卷积结果主要来自光域,而不是被噪声或照明不均匀掩盖。低于 20dB 时优先排查光源散斑,激光照明下微透镜阵列边缘衍射会产生干涉条纹,换成低相干 LED 后散斑会被明显压平。
最后留意 CMOS 增益漂移。长时间曝光下,靶面暗电流引起灰度偏移,实测 PSNR 会随时间缓慢下降。解决方法是采集前做暗场减除,采集后做明场归一化,两次标定的时间间隔控制在十分钟以内。调试到点扩散函数拖尾方向与滤波掩模旋转方向一致时,整套装置就算真正握住了光学卷积的手感。
本文还有配套的精品资源,点击获取