収差の種類と補正

理想的なレンズは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収差(単色収差): 球面収差、コマ収差、非点収差、像面湾曲、歪曲収差
  • 色収差: 分散による焦点距離・倍率の波長依存性
  • 球面収差: 入射高によって焦点がずれる(非球面レンズで補正)
  • 歪曲収差: 樽型と糸巻き型(対称レンズ系で補正)
  • 色収差: アクロマートレンズ(異種ガラスの組み合わせ)で補正

次のステップとして、波動光学の記事も参考にしてください。