錯乱円径(=ボケ量?)のグラフを ggplot2 で表示する


動機

写真の話です。

写真において、ピントが合っている(とみなせる)範囲のことを、「被写界深度」と呼びます。被写界深度は、レンズの焦点距離F値・被写体との距離・許容錯乱円径によって変わります(被写界深度 - Wikipedia)。

ピントが合っている範囲が分かるのは良いのですが、ピントが合っていない部分のボケ量も知りたい。「ピントが合っている位置からどれくらい離れたらどれくらいボケるのか」を、写真表現のためにつかみたい、と思いました。しかしその指標を見つけることはできませんでした1

なんか指標はないかなと思っていたところ、被写界深度計算式の「許容錯乱円径」が使えそうかなと感じてきました。許容錯乱円径は許容できる錯乱円の直径のことで、錯乱円とは、ピントが合っていないものが円形にボケることを言います。これはつまりボケ量のことなのではないか? ということで、被写界深度の式を変形して、ピントからどれだけ離れると錯乱円径がどのように変わるかをグラフで見たいと思いました。

グラフ描画にはR2を使うことにしました。R でグラフを描くには ggplot2 が良いと教えてもらったので、それを使うことにしました。課題はありますが、とりあえずこれまでしたことをまとめておきたいので、記事にしています。

どんなんできたの

こんなグラフができました。X がピント合焦点からの距離(mm)、Y が錯乱円径(mm)(のはず)です。レンズの焦点距離が35mm、F値は2.8、ピントが合っている位置までの距離が 5000mm (=5m) としています。

前方:

f:id:seibe2:20190102222706p:plain

後方:

f:id:seibe2:20190102222643p:plain

どうやって作ったの

前方被写界深度は、

{ \displaystyle
 D_F = \frac{\epsilon F s^ 2}{f^ 2 + \epsilon F s}
}

後方被写界深度は、

{ \displaystyle
 D_R = \frac{\epsilon F s^ 2}{f^ 2 - \epsilon F s}
}

です( f焦点距離 F は F 値、 s はレンズ面からピントが合っている位置までの距離、 \epsilon は許容錯乱円径)(参考:『高校数学でわかる光とレンズ 光の性質から、幾何光学、波動光学の核心まで』(竹内 淳) / カメラの被写界深度の計算 - 高精度計算サイト)。

これを  \epsilon について解きます。今回はWolfram先生(Wolfram|Alpha: Computational Intelligence)にご協力をいただきました。

結果、前方においては

{ \displaystyle
\epsilon = - \frac {D_F f^ 2}{D_F F s - F s^ 2}
}

となり、後方においては、

{ \displaystyle
\epsilon = \frac {D_R f^ 2}{D_R F s + F s^ 2}
}

となるようです。

(2019/1/5追記開始)ちなみに、{ D_R = - D_F} とおいたときは、

{ \displaystyle
\epsilon = \frac {D_F f^ 2}{D_F F s - F s^ 2}
}

となります。これは前方においての式の結果を負の側にするだけとなりますので、下記の式で統一的に錯乱円径を示せることになるかと思います:

{ \displaystyle
\epsilon = \left| \frac {D f^ 2}{D F s + F s^ 2}\right|
}

(2019/1/5追記終了)

これを、ggplot2 でプロットすることにします。

正規分布など好きな関数の曲線を描きたい - Qiita」を、参考にさせていただきました。これをもとに、RConsole で以下のように入力して、上記のグラフを得ました。

前方:

> g2 <- ggplot(data=data.frame(X=c(0,4000)), aes(x=X))
> g2 <- g2 + stat_function(fun=function(x, f, F, s) - (x * f^2)/(x * F * s - F * s^2 ), args=list(f=35, F=2.8, s=5000), colour="red")
> g2

後方:

> g2 <- ggplot(data=data.frame(X=c(0,4000)), aes(x=X))
> g2 <- g2 + stat_function(fun=function(x, f, F, s) (x * f^2)/(x * F * s + F * s^2 ), args=list(f=35, F=2.8, s=5000), colour="blue")
> g2

 D_F, D_R を x軸とする方法は分からなかったので、x にしています。

また、stat_functionfun=function 部分は、function(使用する変数) 式 という書き方にするようです。使用する変数を入れず、args=list(...)の部分のみにf=35を記載していたので、エラー出てしまい、つまづいてしまいました。

考察

被写界深度を計算してくれるサイト(カメラの被写界深度の計算 - 高精度計算サイト)によれば、同条件で許容錯乱円径を0.03mm とした場合において、前方被写界深度は 1,276.6mm、後方被写界深度は 2,608.7mm ということで、目視ですが大体合っているように思えます。

後方よりも前方の方がピント距離からのボケ量が大きいことも分かりました。後方 2m では、錯乱円径は0.025mm ですが、前方 2m では 0.055mm となり、よりたくさんボケるようですね。

また、後方については 100m までのグラフを出してみました。以下のグラフです。

f:id:seibe2:20190102223204p:plain

これによれば、距離が伸びても、あまり錯乱円径は広がらないようです。後景においては、一定量以上はどれだけ距離を伸ばしてもあまりボケ量は変わらない、ということかと思います。

課題

したい順に並べています。

  1. 変数を入力したら結果が出るようにしたい(毎回上のような入力をするのは面倒、さくっとCUIのを作れたら良いのですが)
  2. 前方部分と後方部分を合わせて、一つのグラフにしたい(ピントを合わせた距離から前後にどれだけボケるのかを一望したい)
  3. 許容錯乱円径を与えて、その線を引きたい(すぐにできそう)
    1. の線との交点をグラフに載せたい(被写界深度も分かってお得)
  4. グラフを意味明瞭にしたい("X", "Y"とか意味不明なので。簡単にできそう)
  5. 近似式ではない式で計算したい(現在、 s \approx s - f焦点距離よりもピント距離の方が充分に大きい)として計算しているため)

するかどうかはわかりません。


  1. なにかご存じでしたら教えて頂ければ幸甚にございます / (2019/1/5追記:ありました:フォーマットサイズによるボケ量の変化 | 五海里

  2. なんとなく