4f-система
4f-система — классическая оптическая конфигурация для пространственной фильтрации. В этом туториале мы построим 4f-систему и продемонстрируем её применение для фильтрации высоких частот.
Теория
Структура 4f-системы
вход → f → L1 → f → Фурье-плоскость → f → L2 → f → выходСистема состоит из двух линз с одинаковым фокусным расстоянием , расположенных на расстоянии друг от друга.
Оптическое Фурье-преобразование
В фокальной плоскости первой линзы (Фурье-плоскости) формируется Фурье-образ входного поля:
где — пространственные частоты.
Фильтрация
Размещая маску в Фурье-плоскости, можно модифицировать спектр сигнала:
- Низкочастотный фильтр — пропускает только центральную часть
- Высокочастотный фильтр — блокирует центр
- Полосовой фильтр — пропускает кольцо частот
Шаг 1: Настройка симуляции
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
from svetlanna import SimulationParameters, Wavefront
from svetlanna.elements import ThinLens, FreeSpace, Aperture, RoundAperture
from svetlanna.units import ureg
# Параметры с высоким разрешением
params = SimulationParameters.from_ranges(
w_range=(-5*ureg.mm, 5*ureg.mm), w_points=1024,
h_range=(-5*ureg.mm, 5*ureg.mm), h_points=1024,
wavelength=632.8*ureg.nm
)
f = 100*ureg.mm # Фокусное расстояние линзШаг 2: Создание тестового объекта
Создадим объект с периодической структурой (решётку):
# Координатные сетки
W, H = torch.meshgrid(params.axes.W, params.axes.H, indexing='xy')
# Решётка с периодом 0.5 мм
period = 0.5e-3
grating = (torch.cos(2 * torch.pi * W / period) > 0).float()
# Добавим круглую апертуру
R = 2e-3
circular_mask = (W**2 + H**2 < R**2).float()
# Тестовый объект
test_object = grating * circular_mask
# Создаём волновой фронт с этим объектом
wf_input = Wavefront(test_object.to(torch.complex64))Шаг 3: Построение 4f-системы
class FourFSystem(nn.Module):
"""4f-система с опциональным фильтром в Фурье-плоскости."""
def __init__(self, params, focal_length, filter_mask=None):
super().__init__()
self.params = params
self.f = focal_length
# Элементы
self.prop_f = FreeSpace(params, distance=focal_length, method="AS")
self.lens1 = ThinLens(params, focal_length=focal_length)
self.lens2 = ThinLens(params, focal_length=focal_length)
# Фильтр
if filter_mask is not None:
self.filter = Aperture(params, mask=filter_mask)
else:
self.filter = None
def forward(self, wf, return_fourier=False):
# Первая половина: вход → Фурье-плоскость
wf = self.prop_f(wf)
wf = self.lens1(wf)
wf = self.prop_f(wf)
# Сохраняем Фурье-плоскость
wf_fourier = wf.clone() if return_fourier else None
# Применяем фильтр
if self.filter is not None:
wf = self.filter(wf)
# Вторая половина: Фурье-плоскость → выход
wf = self.prop_f(wf)
wf = self.lens2(wf)
wf = self.prop_f(wf)
if return_fourier:
return wf, wf_fourier
return wfШаг 4: Система без фильтра
Проверим, что 4f-система воспроизводит входной объект (с инверсией):
# 4f-система без фильтра
system_no_filter = FourFSystem(params, f)
# Прохождение через систему
wf_output, wf_fourier = system_no_filter(wf_input, return_fourier=True)
# Визуализация
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
axes[0].imshow(wf_input.intensity.cpu(), cmap='gray')
axes[0].set_title('Входной объект')
axes[1].imshow(torch.log1p(wf_fourier.intensity).cpu(), cmap='hot')
axes[1].set_title('Фурье-плоскость (log)')
axes[2].imshow(wf_output.intensity.cpu(), cmap='gray')
axes[2].set_title('Выход (инвертированный)')
plt.tight_layout()
plt.show()Шаг 5: Низкочастотный фильтр
Создадим фильтр, пропускающий только низкие пространственные частоты:
# Низкочастотный фильтр — круг в центре
filter_radius = 0.3e-3 # Радиус в Фурье-плоскости
low_pass_filter = (W**2 + H**2 < filter_radius**2).float()
# 4f-система с низкочастотным фильтром
system_lowpass = FourFSystem(params, f, filter_mask=low_pass_filter)
# Фильтрация
wf_lowpass = system_lowpass(wf_input)
# Результат — размытое изображение (удалены мелкие детали)
plt.figure(figsize=(12, 4))
plt.subplot(131)
plt.imshow(wf_input.intensity.cpu(), cmap='gray')
plt.title('Вход')
plt.subplot(132)
plt.imshow(low_pass_filter.cpu(), cmap='gray')
plt.title('Фильтр (низкие частоты)')
plt.subplot(133)
plt.imshow(wf_lowpass.intensity.cpu(), cmap='gray')
plt.title('После фильтрации')
plt.tight_layout()
plt.show()Шаг 6: Высокочастотный фильтр
Фильтр, пропускающий только высокие частоты (выделение границ):
# Высокочастотный фильтр — блокируем центр
block_radius = 0.15e-3
high_pass_filter = (W**2 + H**2 > block_radius**2).float()
# 4f-система с высокочастотным фильтром
system_highpass = FourFSystem(params, f, filter_mask=high_pass_filter)
# Фильтрация
wf_highpass = system_highpass(wf_input)
# Результат — видны только краяШаг 7: Анализ спектра
def plot_spectrum(wf_fourier, params, title="Спектр"):
"""Визуализация спектра с правильными осями частот."""
# Пространственные частоты
dx = params.axes.W[1] - params.axes.W[0]
freq_max = 1 / (2 * dx) # Частота Найквиста
fig, ax = plt.subplots(figsize=(6, 6))
im = ax.imshow(
torch.log1p(wf_fourier.intensity).cpu(),
cmap='hot',
extent=[-freq_max*1e-3, freq_max*1e-3, -freq_max*1e-3, freq_max*1e-3]
)
ax.set_xlabel('$f_x$, мм$^{-1}$')
ax.set_ylabel('$f_y$, мм$^{-1}$')
ax.set_title(title)
plt.colorbar(im, ax=ax, label='log(I + 1)')
return figШаг 8: Полосовой фильтр
Выделяем определённую полосу частот:
# Полосовой фильтр
inner_radius = 0.2e-3
outer_radius = 0.5e-3
R_sq = W**2 + H**2
bandpass_filter = ((R_sq > inner_radius**2) & (R_sq < outer_radius**2)).float()
system_bandpass = FourFSystem(params, f, filter_mask=bandpass_filter)
wf_bandpass = system_bandpass(wf_input)Полный код
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
from svetlanna import SimulationParameters, Wavefront
from svetlanna.elements import ThinLens, FreeSpace, Aperture
from svetlanna.units import ureg
# Параметры
params = SimulationParameters.from_ranges(
w_range=(-5*ureg.mm, 5*ureg.mm), w_points=1024,
h_range=(-5*ureg.mm, 5*ureg.mm), h_points=1024,
wavelength=632.8*ureg.nm
)
f = 100*ureg.mm
# Координаты
W, H = torch.meshgrid(params.axes.W, params.axes.H, indexing='xy')
# Тестовый объект — решётка
period = 0.5e-3
grating = (torch.cos(2 * torch.pi * W / period) > 0).float()
circular_mask = (W**2 + H**2 < (2e-3)**2).float()
test_object = grating * circular_mask
wf_input = Wavefront(test_object.to(torch.complex64))
# 4f-система
class FourFSystem(nn.Module):
def __init__(self, params, focal_length, filter_mask=None):
super().__init__()
self.prop = FreeSpace(params, distance=focal_length, method="AS")
self.lens1 = ThinLens(params, focal_length=focal_length)
self.lens2 = ThinLens(params, focal_length=focal_length)
self.filter = Aperture(params, mask=filter_mask) if filter_mask is not None else None
def forward(self, wf):
wf = self.prop(self.lens1(self.prop(wf)))
if self.filter:
wf = self.filter(wf)
wf = self.prop(self.lens2(self.prop(wf)))
return wf
# Низкочастотный фильтр
lp_filter = (W**2 + H**2 < (0.3e-3)**2).float()
system = FourFSystem(params, f, lp_filter)
# Результат
wf_out = system(wf_input)
print(f"Входная интенсивность: {wf_input.max_intensity:.3f}")
print(f"Выходная интенсивность: {wf_out.max_intensity:.3f}")Выводы
- 4f-система реализует оптическое Фурье-преобразование
- В Фурье-плоскости можно размещать фильтры для модификации спектра
- Низкочастотный фильтр размывает изображение
- Высокочастотный фильтр выделяет границы
- Полосовой фильтр выделяет структуры определённого масштаба
Что дальше?
- Восстановление фазы — итеративные алгоритмы
- Оптические системы — сборка систем