レンズの公式と結像

レンズは光を集めたり発散させたりする光学素子であり、カメラ、望遠鏡、顕微鏡など多くの光学機器の心臓部です。本記事では薄レンズの公式を導出し、レンズによる結像の仕組みを理解します。

本記事の内容

  • 薄レンズの近似
  • 薄レンズの公式の導出
  • 倍率
  • 凸レンズと凹レンズの結像
  • レンズメーカーの方程式
  • Pythonでの光線追跡と可視化

前提知識

この記事を読む前に、以下の記事を読んでおくと理解が深まります。

薄レンズの近似

薄レンズの近似(thin lens approximation)とは、レンズの厚さがその焦点距離に比べて十分小さいとみなし、光線がレンズの中心面で屈折すると考える近似です。

この近似のもとでは、光軸に近い光線(近軸光線: paraxial ray)に対して、以下の3つの基本光線を考えます。

  1. 光軸に平行な光線: レンズを通過後、焦点を通る
  2. レンズの中心を通る光線: 方向を変えずに直進する
  3. 焦点を通る光線: レンズを通過後、光軸に平行になる

薄レンズの公式の導出

物体距離(レンズから物体までの距離)を $a$、像距離(レンズから像までの距離)を $b$、焦点距離を $f$ とします。

物体の高さを $h$、像の高さを $h’$ とします。光軸に平行に入射した光線は焦点 $F’$ を通り、レンズ中心を通る光線は直進します。

幾何学的導出

レンズ中心を通る光線に関する三角形の相似から:

$$ \frac{h’}{h} = -\frac{b}{a} $$

焦点を通る光線に関する三角形の相似から:

$$ \frac{h’}{h} = -\frac{b – f}{f} $$

これら2式を等置します。

$$ \begin{align} \frac{b}{a} &= \frac{b – f}{f} \\ bf &= a(b – f) \\ bf &= ab – af \\ af + bf &= ab \end{align} $$

両辺を $abf$ で割ると:

$$ \frac{1}{b} + \frac{1}{a} = \frac{1}{f} $$

$$ \boxed{\frac{1}{f} = \frac{1}{a} + \frac{1}{b}} $$

これが薄レンズの公式(thin lens equation)です。

倍率

横倍率(lateral magnification)$m$ は:

$$ \boxed{m = \frac{h’}{h} = -\frac{b}{a}} $$

  • $|m| > 1$: 拡大像
  • $|m| < 1$: 縮小像
  • $m > 0$: 正立像(虚像)
  • $m < 0$: 倒立像(実像)

凸レンズと凹レンズ

凸レンズ(収束レンズ): $f > 0$

物体の位置に応じて像が変化します。

物体距離 $a$ 像の種類 像の大きさ
$a > 2f$ 実像 縮小
$a = 2f$ 実像 等倍
$f < a < 2f$ 実像 拡大
$a = f$ 像なし(∞)
$a < f$ 虚像 拡大

凹レンズ(発散レンズ): $f < 0$

凹レンズは常に縮小の正立虚像を作ります。レンズの公式で $f < 0$ とすると $b < 0$ となり、像はレンズと同じ側にできます。

レンズメーカーの方程式

レンズの焦点距離は、レンズの屈折率と曲率半径によって決まります。レンズの屈折率を $n$、周囲媒質の屈折率を $n_0$(通常は空気で $n_0=1$)、前面の曲率半径を $R_1$、後面の曲率半径を $R_2$ とすると:

$$ \boxed{\frac{1}{f} = \left(\frac{n}{n_0} – 1\right)\left(\frac{1}{R_1} – \frac{1}{R_2}\right)} $$

これがレンズメーカーの方程式(lensmaker’s equation)です。

符号の規約

  • 光は左から右に進むとする
  • 曲面の中心が右側にあるとき $R > 0$(凸面)
  • 曲面の中心が左側にあるとき $R < 0$(凹面)

導出

球面屈折の公式を前面と後面に順に適用して導出します。

屈折率 $n_1$ から $n_2$ の球面境界(曲率半径 $R$)での屈折公式は:

$$ \frac{n_1}{s} + \frac{n_2}{s’} = \frac{n_2 – n_1}{R} $$

前面($n_0 \to n$、曲率半径 $R_1$):

$$ \frac{n_0}{s_1} + \frac{n}{s_1′} = \frac{n – n_0}{R_1} $$

後面($n \to n_0$、曲率半径 $R_2$)。薄レンズ近似より $s_2 = -s_1’$:

$$ \frac{n}{s_2} + \frac{n_0}{s_2′} = \frac{n_0 – n}{R_2} $$

2式を足し合わせると:

$$ \frac{n_0}{s_1} + \frac{n_0}{s_2′} = (n – n_0)\left(\frac{1}{R_1} – \frac{1}{R_2}\right) $$

$s_1 = a$、$s_2′ = b$ とおき、$n_0$ で割って $1/a + 1/b = 1/f$ と対応させると、レンズメーカーの方程式が得られます。

Pythonでの実装

薄レンズの結像シミュレーション

import numpy as np
import matplotlib.pyplot as plt

def thin_lens_image(a, f):
    """薄レンズの公式から像距離を計算"""
    if abs(1/f - 1/a) < 1e-10:
        return np.inf  # 物体が焦点上
    b = 1.0 / (1.0/f - 1.0/a)
    return b

def draw_lens_diagram(a, f, h=1.0, ax=None):
    """光線追跡による結像図を描画"""
    if ax is None:
        fig, ax = plt.subplots(figsize=(12, 5))

    b = thin_lens_image(a, f)
    m = -b / a
    h_prime = m * h

    # レンズ(中心に縦線)
    lens_height = max(abs(h), abs(h_prime), 2) * 1.5
    ax.plot([0, 0], [-lens_height, lens_height], 'b-', linewidth=2, label='Lens')

    # 光軸
    x_range = max(abs(a), abs(b), abs(2*f)) * 1.3
    ax.axhline(y=0, color='gray', linewidth=0.5)

    # 焦点
    ax.plot([-f, f], [0, 0], 'rx', markersize=10)
    ax.annotate('F', xy=(-f, -0.3), fontsize=11, color='red', ha='center')
    ax.annotate("F'", xy=(f, -0.3), fontsize=11, color='red', ha='center')

    # 物体(矢印)
    ax.annotate('', xy=(-a, h), xytext=(-a, 0),
                arrowprops=dict(arrowstyle='->', color='green', lw=2))
    ax.text(-a, h + 0.2, 'Object', ha='center', fontsize=10, color='green')

    # 光線1: 光軸に平行 → 焦点を通る
    ax.plot([-a, 0], [h, h], 'r-', linewidth=1, alpha=0.7)
    if np.isfinite(b):
        ax.plot([0, b], [h, h_prime], 'r-', linewidth=1, alpha=0.7)

    # 光線2: レンズ中心を通る
    if np.isfinite(b):
        ax.plot([-a, b], [h, h_prime], 'orange', linewidth=1, alpha=0.7)

    # 光線3: 焦点を通る → 光軸に平行
    slope_to_F = (h - 0) / (-a - (-f))
    y_at_lens = h + slope_to_F * (0 - (-a))
    # 前焦点を通る光線がレンズに到達する高さ
    y_at_lens_3 = h * f / (a - f) if abs(a - f) > 1e-10 else h
    # 前焦点からレンズまで
    ax.plot([-a, 0], [h, h + (0 - (-a)) * (0 - h) / ((-f) - (-a))], 'm-', linewidth=1, alpha=0.7)

    # 像(矢印)
    if np.isfinite(b) and abs(b) < x_range * 2:
        if b > 0:  # 実像
            ax.annotate('', xy=(b, h_prime), xytext=(b, 0),
                        arrowprops=dict(arrowstyle='->', color='blue', lw=2))
            ax.text(b, h_prime - 0.4 * np.sign(h_prime), 'Real image',
                    ha='center', fontsize=10, color='blue')
        else:  # 虚像
            ax.annotate('', xy=(b, h_prime), xytext=(b, 0),
                        arrowprops=dict(arrowstyle='->', color='purple', lw=2, ls='--'))
            ax.text(b, h_prime + 0.3, 'Virtual image',
                    ha='center', fontsize=10, color='purple')

    ax.set_xlim(-x_range, x_range)
    ax.set_ylim(-lens_height, lens_height)
    ax.set_xlabel('z [arbitrary unit]', fontsize=11)
    ax.set_ylabel('y [arbitrary unit]', fontsize=11)
    ax.set_aspect('equal')
    ax.grid(True, alpha=0.3)

    return ax

# --- 3つの結像パターンを描画 ---
fig, axes = plt.subplots(3, 1, figsize=(12, 12))

f = 2.0

# ケース1: a > 2f(縮小実像)
draw_lens_diagram(a=6.0, f=f, h=1.0, ax=axes[0])
axes[0].set_title('Case 1: a > 2f → Reduced real image', fontsize=12)

# ケース2: f < a < 2f(拡大実像)
draw_lens_diagram(a=3.0, f=f, h=1.0, ax=axes[1])
axes[1].set_title('Case 2: f < a < 2f → Magnified real image', fontsize=12)

# ケース3: a < f(拡大虚像)
draw_lens_diagram(a=1.0, f=f, h=1.0, ax=axes[2])
axes[2].set_title('Case 3: a < f → Magnified virtual image', fontsize=12)

plt.tight_layout()
plt.show()

物体距離と像距離の関係

import numpy as np
import matplotlib.pyplot as plt

# --- 物体距離に対する像距離と倍率のグラフ ---
f = 5.0  # 焦点距離
a = np.linspace(0.5, 30, 1000)

# 薄レンズの公式
b = 1.0 / (1.0/f - 1.0/a)
m = -b / a

fig, axes = plt.subplots(1, 2, figsize=(14, 5))

# 像距離
axes[0].plot(a, b, 'b-', linewidth=2)
axes[0].axhline(y=f, color='r', linestyle='--', alpha=0.5, label=f'b = f = {f}')
axes[0].axvline(x=f, color='g', linestyle='--', alpha=0.5, label=f'a = f = {f}')
axes[0].set_xlabel('Object distance a', fontsize=12)
axes[0].set_ylabel('Image distance b', fontsize=12)
axes[0].set_title('Image distance vs Object distance', fontsize=13)
axes[0].set_xlim(0, 30)
axes[0].set_ylim(-30, 30)
axes[0].legend(fontsize=11)
axes[0].grid(True, alpha=0.3)

# 倍率
axes[1].plot(a, m, 'r-', linewidth=2)
axes[1].axhline(y=-1, color='gray', linestyle='--', alpha=0.5, label='m = -1 (equal size)')
axes[1].axhline(y=0, color='gray', linewidth=0.5)
axes[1].axvline(x=f, color='g', linestyle='--', alpha=0.5, label=f'a = f = {f}')
axes[1].set_xlabel('Object distance a', fontsize=12)
axes[1].set_ylabel('Magnification m', fontsize=12)
axes[1].set_title('Magnification vs Object distance', fontsize=13)
axes[1].set_xlim(0, 30)
axes[1].set_ylim(-5, 5)
axes[1].legend(fontsize=11)
axes[1].grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

まとめ

本記事では、レンズの公式と結像について解説しました。

  • 薄レンズの公式: $1/f = 1/a + 1/b$
  • 横倍率: $m = -b/a$
  • 凸レンズ: 物体の位置に応じて実像・虚像を作る
  • 凹レンズ: 常に縮小正立虚像を作る
  • レンズメーカーの方程式: $1/f = (n/n_0 – 1)(1/R_1 – 1/R_2)$

次のステップとして、以下の記事も参考にしてください。