理想的なレンズは1点から出た光を正確に1点に集めますが、実際のレンズでは光線が1点に集まらず、像がぼけたり歪んだりします。この現象を収差(aberration)といいます。光学系の設計では、収差を理解し補正することが極めて重要です。
本記事の内容
- 収差とは何か
- ザイデルの5収差(単色収差)
- 色収差
- 収差の補正方法
- Pythonでの可視化
前提知識
この記事を読む前に、以下の記事を読んでおくと理解が深まります。
収差とは
薄レンズの公式 $1/f = 1/a + 1/b$ は近軸近似(paraxial approximation)のもとで成り立ちます。近軸近似とは:
$$ \sin\theta \approx \theta $$
と近似することです。しかし実際には:
$$ \sin\theta = \theta – \frac{\theta^3}{3!} + \frac{\theta^5}{5!} – \cdots $$
この $\theta^3$ 以降の高次項が収差の原因です。$\theta^3$ の項に起因する収差を3次収差(third-order aberration)またはザイデル収差(Seidel aberrations)と呼びます。
ザイデルの5収差
1. 球面収差(Spherical aberration)
球面収差は、光軸に平行な光線がレンズに入射したとき、光軸からの距離 $h$(入射高)によって焦点位置がずれる現象です。
光軸に近い光線(近軸光線)の焦点距離を $f_0$、入射高 $h$ の光線の焦点距離を $f(h)$ とすると:
$$ f(h) \approx f_0 – C_s h^2 $$
ここで $C_s$ は球面収差係数です。光軸から離れた光線ほど手前で焦点を結ぶため、焦点がぼけます。
球面収差は軸上の物点でも発生する唯一のザイデル収差であり、軸上収差とも呼ばれます。
2. コマ収差(Coma)
コマ収差は、光軸から外れた物点からの光が、レンズの異なる高さの帯域(ゾーン)を通過することで生じます。像が彗星の尾のような非対称な形状になるため「コマ」(彗星)と呼ばれます。
入射高 $h$ の光線による像のずれは $h^2$ に比例し、像面上で同心円状のリングパターンを形成します。
3. 非点収差(Astigmatism)
非点収差は、光軸から離れた物点に対して、子午面(meridional plane)と矢状面(sagittal plane)での焦点位置が異なる現象です。
子午面内の焦点距離を $f_t$、矢状面内の焦点距離を $f_s$ とすると:
$$ \Delta f = f_t – f_s \neq 0 $$
この差が非点収差です。点像が子午方向と矢状方向で異なる位置に線像として結像します。
4. 像面湾曲(Field curvature)
像面湾曲(ペッツバール湾曲とも呼ばれる)は、平面物体の像が平面ではなく曲面上に結像する現象です。
ペッツバール曲率半径 $R_p$ は:
$$ \frac{1}{R_p} = \sum_i \frac{1}{n_i f_i} $$
ここで $n_i$、$f_i$ は $i$ 番目のレンズの屈折率と焦点距離です。
5. 歪曲収差(Distortion)
歪曲収差は、像の形状が物体の形状に対して歪む現象です。倍率が像高に依存するため生じます。
- 樽型歪曲(barrel distortion): 周辺に向かって倍率が減少
- 糸巻き型歪曲(pincushion distortion): 周辺に向かって倍率が増加
歪曲率 $D$ は:
$$ D = \frac{y’ – y’_0}{y’_0} \times 100 \, [\%] $$
ここで $y’$ は実際の像の高さ、$y’_0$ は理想的な像の高さです。
色収差(Chromatic aberration)
色収差は波長(色)によって屈折率が異なる分散に起因する収差です。ザイデル収差とは異なり、近軸光線でも発生します。
軸上色収差
異なる波長の光が異なる焦点距離を持つ現象です。
$$ \Delta f = f_{\text{red}} – f_{\text{blue}} $$
倍率色収差
異なる波長で像の大きさが異なる現象です。
アッベ数
レンズ材料の分散特性を表すアッベ数 $V_d$ は:
$$ V_d = \frac{n_d – 1}{n_F – n_C} $$
ここで $n_d$(587.6 nm)、$n_F$(486.1 nm)、$n_C$(656.3 nm)はそれぞれの波長での屈折率です。アッベ数が大きいほど分散が小さいことを意味します。
収差の補正方法
| 収差 | 主な補正方法 |
|---|---|
| 球面収差 | 非球面レンズ、組み合わせレンズ |
| コマ収差 | アプラナートレンズ(正弦条件の満足) |
| 非点収差 | レンズ形状の最適化 |
| 像面湾曲 | ペッツバール条件の調整 |
| 歪曲収差 | 対称型レンズ系(絞りに対して対称) |
| 色収差 | アクロマートレンズ(2枚の異種ガラスを組合せ) |
アクロマートレンズは、クラウンガラス(低分散)とフリントガラス(高分散)を組み合わせることで色収差を補正します。2色(通常は赤と青)の焦点を一致させます。
Pythonでの実装
球面収差の可視化
import numpy as np
import matplotlib.pyplot as plt
# --- 球面収差のシミュレーション ---
# 球面レンズのスネルの法則による光線追跡
R = 50.0 # 曲率半径 [mm]
n = 1.5 # 屈折率
f_paraxial = R / (n - 1) # 近軸焦点距離
# 入射高 h の光線が球面で屈折する
h = np.linspace(0.1, 20, 100) # 入射高 [mm]
# 球面上の入射点
theta_surface = np.arcsin(h / R) # 球面上の角度
theta_i = theta_surface # 入射角(光軸に平行な入射)
theta_r = np.arcsin(np.sin(theta_i) / n) # 屈折角
# 屈折後の光線が光軸と交差する位置(焦点位置)
# 幾何学的計算
deviation = theta_i - theta_r
# 光軸との交点
z_focus = R * (1 - np.cos(theta_surface)) + h / np.tan(theta_surface - deviation + theta_r)
# 簡易計算: 近似的な焦点位置
f_actual = R / (n - 1) * (1 - (n + 1) / (4 * n * (n - 1)) * (h / R)**2)
longitudinal_sa = f_actual - f_paraxial # 縦の球面収差
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# 左: 縦の球面収差
axes[0].plot(h, longitudinal_sa, 'b-', linewidth=2)
axes[0].set_xlabel('Ray height h [mm]', fontsize=12)
axes[0].set_ylabel('Longitudinal SA [mm]', fontsize=12)
axes[0].set_title('Longitudinal Spherical Aberration', fontsize=13)
axes[0].grid(True, alpha=0.3)
axes[0].axhline(y=0, color='gray', linewidth=0.5)
# 右: 光線図
axes[1].set_xlim(-10, f_paraxial + 20)
axes[1].set_ylim(-25, 25)
# レンズ(簡易描画)
lens_y = np.linspace(-22, 22, 100)
lens_x = R - np.sqrt(np.maximum(R**2 - lens_y**2, 0))
axes[1].plot(lens_x, lens_y, 'b-', linewidth=2)
# 光線
h_rays = np.array([2, 5, 8, 11, 14, 17, 20])
colors = plt.cm.viridis(np.linspace(0.2, 0.9, len(h_rays)))
for h_val, col in zip(h_rays, colors):
f_val = R / (n - 1) * (1 - (n + 1) / (4 * n * (n - 1)) * (h_val / R)**2)
# 入射光線(光軸に平行)
axes[1].plot([-10, 0], [h_val, h_val], color=col, linewidth=1, alpha=0.7)
# 屈折後の光線
axes[1].plot([0, f_val], [h_val, 0], color=col, linewidth=1, alpha=0.7)
axes[1].axhline(y=0, color='gray', linewidth=0.5)
axes[1].axvline(x=f_paraxial, color='red', linestyle='--', alpha=0.5, label=f'Paraxial focus = {f_paraxial:.1f} mm')
axes[1].set_xlabel('z [mm]', fontsize=12)
axes[1].set_ylabel('y [mm]', fontsize=12)
axes[1].set_title('Spherical Aberration: Ray Trace', fontsize=13)
axes[1].legend(fontsize=10)
plt.tight_layout()
plt.show()
歪曲収差の可視化
import numpy as np
import matplotlib.pyplot as plt
# --- 歪曲収差の可視化 ---
def distort_barrel(x, y, k=-0.1):
"""樽型歪曲"""
r2 = x**2 + y**2
factor = 1 + k * r2
return x * factor, y * factor
def distort_pincushion(x, y, k=0.1):
"""糸巻き型歪曲"""
r2 = x**2 + y**2
factor = 1 + k * r2
return x * factor, y * factor
# グリッド生成
n_lines = 11
t = np.linspace(-1, 1, n_lines)
s = np.linspace(-1, 1, 200)
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
# 無歪曲
for ti in t:
axes[0].plot(s, np.full_like(s, ti), 'b-', linewidth=0.8)
axes[0].plot(np.full_like(s, ti), s, 'b-', linewidth=0.8)
axes[0].set_title('No distortion', fontsize=13)
axes[0].set_xlim(-1.3, 1.3)
axes[0].set_ylim(-1.3, 1.3)
axes[0].set_aspect('equal')
# 樽型歪曲
for ti in t:
x_h, y_h = distort_barrel(s, np.full_like(s, ti), k=-0.2)
axes[1].plot(x_h, y_h, 'r-', linewidth=0.8)
x_v, y_v = distort_barrel(np.full_like(s, ti), s, k=-0.2)
axes[1].plot(x_v, y_v, 'r-', linewidth=0.8)
axes[1].set_title('Barrel distortion (k < 0)', fontsize=13)
axes[1].set_xlim(-1.3, 1.3)
axes[1].set_ylim(-1.3, 1.3)
axes[1].set_aspect('equal')
# 糸巻き型歪曲
for ti in t:
x_h, y_h = distort_pincushion(s, np.full_like(s, ti), k=0.2)
axes[2].plot(x_h, y_h, 'g-', linewidth=0.8)
x_v, y_v = distort_pincushion(np.full_like(s, ti), s, k=0.2)
axes[2].plot(x_v, y_v, 'g-', linewidth=0.8)
axes[2].set_title('Pincushion distortion (k > 0)', fontsize=13)
axes[2].set_xlim(-1.3, 1.3)
axes[2].set_ylim(-1.3, 1.3)
axes[2].set_aspect('equal')
for ax in axes:
ax.grid(True, alpha=0.2)
plt.suptitle('Distortion Aberration', fontsize=14, y=1.02)
plt.tight_layout()
plt.show()
色収差の可視化
import numpy as np
import matplotlib.pyplot as plt
# --- 色収差のシミュレーション ---
# コーシーの分散公式
A, B = 1.5168, 0.00414 # BK7近似
wavelengths = {'violet': 0.400, 'blue': 0.486, 'green': 0.546, 'red': 0.656}
colors_plot = {'violet': 'violet', 'blue': 'blue', 'green': 'green', 'red': 'red'}
R = 100.0 # 曲率半径 [mm]
fig, ax = plt.subplots(figsize=(12, 5))
for name, wl in wavelengths.items():
n = A + B / wl**2
f = R / (n - 1) # 近軸焦点距離
# 光線描画(光軸に平行に入射高 h=10mm で入射)
h = 10.0
ax.plot([-20, 0], [h, h], color=colors_plot[name], linewidth=1.5, alpha=0.8)
ax.plot([0, f], [h, 0], color=colors_plot[name], linewidth=1.5, alpha=0.8,
label=f'{name} ({wl*1000:.0f}nm): f={f:.1f}mm')
# 下側の光線も描画
ax.plot([-20, 0], [-h, -h], color=colors_plot[name], linewidth=1.5, alpha=0.8)
ax.plot([0, f], [-h, 0], color=colors_plot[name], linewidth=1.5, alpha=0.8)
# レンズ
ax.plot([0, 0], [-15, 15], 'k-', linewidth=3)
ax.axhline(y=0, color='gray', linewidth=0.5)
ax.set_xlabel('z [mm]', fontsize=12)
ax.set_ylabel('y [mm]', fontsize=12)
ax.set_title('Chromatic Aberration (Longitudinal)', fontsize=13)
ax.legend(fontsize=10, loc='upper right')
ax.set_xlim(-25, 220)
ax.set_ylim(-18, 18)
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
まとめ
本記事では、光学系における収差の種類と補正方法について解説しました。
- ザイデルの5収差(単色収差): 球面収差、コマ収差、非点収差、像面湾曲、歪曲収差
- 色収差: 分散による焦点距離・倍率の波長依存性
- 球面収差: 入射高によって焦点がずれる(非球面レンズで補正)
- 歪曲収差: 樽型と糸巻き型(対称レンズ系で補正)
- 色収差: アクロマートレンズ(異種ガラスの組み合わせ)で補正
次のステップとして、波動光学の記事も参考にしてください。