✖
✖
手ぶれを無視できるシャッタースピード
手ブレについて考えたことがあるけど、ずばり焦点距離が x のとき、特定カメラの性能で 1px 以内に手ぶれが収まるシャッタースピードを求める関数が欲しかったので書いた。
/**
* `focalLength`mm の焦点距離のとき 1px 以内に手ぶれが収まる最低限のシャッタースピード
* `opts.sensorSize.width`: センササイズ (横)
* `opts.pixels.width`: ピクセル数 (横)
* `opts.jiggle_angle`: 手ぶれの角速度 (角度/秒)
*
* (focalLength * Math.tan(degreeToRadians(2) * speed)) / (opts.sensorSize.width / opts.pixels.width) == 1;
* focalLength * Math.tan(degreeToRadians(2) * speed) == (opts.sensorSize.width / opts.pixels.width);
* Math.tan(degreeToRadians(2) * speed) == (opts.sensorSize.width / opts.pixels.width) / focalLength;
* degreeToRadians(2) * speed == Math.atan( (opts.sensorSize.width / opts.pixels.width) / focalLength );
* speed == Math.atan( (opts.sensorSize.width / opts.pixels.width) / focalLength ) / degreeToRadians(2);
*/
function minimunSpeedByFocalLength (focalLength, opts) {
if (!opts) opts = {};
if (!opts.jiggle_angle) opts.jiggle_angle = minimunSpeedByFocalLength.JIGGLE_ANGLE.ADVANCED;
return Math.atan( (opts.sensorSize.width / opts.pixels.width) / focalLength ) / degreeToRadians(opts.jiggle_angle);
}
minimunSpeedByFocalLength.JIGGLE_ANGLE = { // 手ぶれ限界 角速度(角度/秒)
NOVICE : 5,
ADVANCED : 2
}; で
var sensorSize = {
width: 36,
height: 24
};
var pixels = {
width: 5616,
height: 3744
};
function show (f) {
var speed = 1 / minimunSpeedByFocalLength(f, {
sensorSize : sensorSize,
pixels : pixels
});
console.log("%dmm 1/%dsec (スピード%d倍=%d段)",
f,
Math.floor(speed),
~~(speed / f),
Math.sqrt(speed / f).toFixed(2)
);
}
// NOVICE
show(24); //=> 24mm 1/326sec (スピード13倍=3.69段)
show(50); //=> 50mm 1/680sec (スピード13倍=3.69段)
show(100); //=> 100mm 1/1361sec (スピード13倍=3.69段)
show(200); //=> 200mm 1/2722sec (スピード13倍=3.69段)
// ADVANCED
show(24); //=> 24mm 1/130sec (スピード5倍=2.33段)
show(50); //=> 50mm 1/272sec (スピード5倍=2.33段)
show(100); //=> 100mm 1/544sec (スピード5倍=2.33段)
show(200); //=> 200mm 1/1089sec (スピード5倍=2.33段) 手ぶれ補正4段分ぐらいあってようやく、いわゆる「焦点距離分の1」で手ブレが無視できるようになる。
画質の評価とかをする場合、十分にシャッタースピードが早いかを確認する必要がありそうだと思った。
✖
✖
✖
✖
✖
✖
✖
写真のプリント画質と画角・人間の視力
「標準レンズ」について では、理想的なカメラと理想的なレンズを仮定して考えていたので、以下の点がひっかかっていた:
- 超広角で撮影したとして、パースが正しくなるように大きく引き伸ばして十分な画質が得られるか
- (十分な画質が得られなければ、リアリティが消失して「パースが正しい」ことが意味をなさないのではないか)
なので、現在のカメラで撮影された画像をプリントするとき、十分な画質を得られる最大出力サイズを考えてみることにした。
十分な画質
まずそもそも「十分な画質」とはなにかを考えないとどうしようもない。「十分な画質」について「隣あう画素同士の区別がつかない」として考えることにした。
一般的に印刷物では300dpi程度が必要と言われていたりするけど、根拠がよくわかっていなかった。Facebook でぶつぶつ呟いていたら、視力の定義から考えてみたらどうかとの話だったので、そこから考えることにした。
「視力は分単位で表した視角の逆数で表す。例えば、5mの距離から約1.45mmの切れ目を判別できると視力1.0となる」(Wikipedia) らしいので、とりあえず視力1.0のときに、ある距離において見分けられる最小の角度を求めた。
// 視力が `visualAcuity` のとき、見分けられる最小の角度 (radian)
// 視力の定義: 分単位で表した視角の逆数
// 視力 1.0 は 1.45444... 幅を5mの位置から見て識別できること
// console.log( 1 / (radiansToDegree(angleByDistanceAndSize(5000, 1.454444)) * 60), angleByDistanceAndSize(5000, 1.454444) );
// console.log( 1 / (radiansToDegree(angleByDistanceAndSize(10000, 1.454444)) * 60), angleByDistanceAndSize(10000, 1.454444) );
function angularSubtenseByVisualAcuity (visualAcuity) {
if (!visualAcuity) visualAcuity = 1;
return angleByDistanceAndSize(5000, 1.454444) / visualAcuity;
} これで特定の距離のときにどれぐらい目で見分けられるかがわかるので、これを元に特定の距離のときにどれぐらい dpi が必要かを求められる。
// `visualAcuity` の視力を持つ人について、`distance` (mm) 離れた距離にある印刷物に求められる最低の dpi
function dpiByDistanceAndVisualAcuity (distance, visualAcuity) {
return 25.4 / sizeByDistanceAndAngle(distance, angularSubtenseByVisualAcuity(visualAcuity));
} 最大出力サイズ
必要な dpi が求まれば、あとはカメラが撮影可能な画素数にかかってくる。
var pixels = {
width: 5616,
height: 3744
};
// 視力 1.0 の人が 50cm の距離で見たとき、ドットの見分けがつかない限りで最大の印刷サイズ
console.log(pixels.width / dpiByDistanceAndVisualAcuity(500, 1.0) * 25.4, 'mm');
//=> 816.8157504 'mm'
// 視力 1.5 の人が 100cm の距離で見たとき、ドットの見分けがつかない限りで最大の印刷サイズ
// 大きく印刷するほど近付いてみる余地が生まれるので、より要求される画質があがると仮定
console.log(pixels.width / dpiByDistanceAndVisualAcuity(1000, 1.5) * 25.4, 'mm');
//=> 1089.087662933585 'mm' 5616×3744は 5D Mark II の場合だけど、最近の高スペックデジカメだとこんなものっぽい。
こうしてみると紙の規格的にはA0がギリギリ限界ぐらいになりそうに思う。
出力サイズにおいてパースが自然な焦点距離
ついでにこれまでのの組合せで、最大限画質を考慮して拡大しつつパースが正しくなる最小の焦点距離を求めた。これは単にカメラの性能と、人間の目の性能によって決まる。
// 視力 1.5 の人について、最大限画質を考慮して拡大しつつパースが正しくなる最小の焦点距離
// 1000mm の位置を仮定してるが、これは距離が変わっても一緒
console.log(~~angleToFocalLength(36, angleByDistanceAndSize(1000, pixels.width / dpiByDistanceAndVisualAcuity(1000, 1.5) * 25.4)), 'mm');
//=> 33 'mm'
// 視力 1.0
console.log(~~angleToFocalLength(36, angleByDistanceAndSize(1000, pixels.width / dpiByDistanceAndVisualAcuity(1000, 1.0) * 25.4)), 'mm');
//=> 22 'mm' 安全圏に収めるなら 35mm だろうし、多少画質を犠牲にしても広く見せたいなら 20mm ぐらいまでいいんじゃないか、という感じになった。
いろいろ間違っているかもしれないのであんまり信用しないでください (特に視力から必要DPIを出すあたりがあやしい気がする)
✖
✖
土曜日は等々力渓谷に行った。そんなに広くないなあというのと、結構人が多いなあという印象だった。とにかく途中で腹が痛くなって死ぬかと思ってよく覚えてない。
日曜日は神代植物公園に行った。あまり花は咲いておらず、かなり早い時間に行ったので人も少なかった。温室内の休憩所が快適だった。
月曜日は生田緑地のかわさき宙と緑の科学館でプラネタリウムを見に行った。午前11時ぐらいについたのだけれど、既に15時の回しか空いておらず、かなり待ち時間が発生したので、日本民家園を見てまわった。
日本民家園は非常に久しぶりに入ったけれど、結構いろんな建築があって面白かった。
プラネタリウムは、入るときに双眼鏡を渡されて、なんだろうと思ったけど、写される星々が非常に細かくて、天の川を双眼鏡で見るとちゃんと星が見えるとか、隣のアンドロメダ銀河が見えるとかで、びっくりした。400円で見れるので非常にコストパフォーマンスが良く感じる。

















