2012年 12月 02日

5D2 5D3 6D

ちょっと前まで5D2がラインナップに残ってたけど、6D発売と同時?に旧製品入りしたようだ。新しい 5D3 はコストパフォーマンスが若干悪く感じる。6D が出た以上 WiFi 対応以外のを買う気はしない。5D系はプロ向けっぽくなってきたので 6D 系使うのがよさそうだと思った。6Dは大したデメリットはなく価格も比較的安い (しばらく経てばもっと安くなると思うけど)

5D2 から買い替えるほどのメリットがあるかというと、6Dでもちょっと微妙な感じがする。5D2に比べた高感度特性・WiFi の機能追加が、価格分の価値があるかっていうと、なんともいえない。WiFi でのスマフォ連携機能はすごい面白いけど、そんな使わない気がするし、高感度特性は嬉しいけど、5D2 もそこまで悪くない。

5D3

メリット

  • 高感度特性
  • 1D 並の61点AF
  • 水準器
  • CF SD 同時対応
  • 視野率100%

デメリット

  • フォーカシングスクリーン交換不可
  • ちょっとでかい
  • 価格が高い
    • 現時点で26万弱 (発売後9ヶ月)
  • WiFi・GPS がない

6D

メリット

  • 高感度特性
  • WiFi・GPS 対応
  • 価格が安い
    • 現時点で最安は17万弱 (発売後数日)
  • 軽い
  • 小さい
  • フォーカシングスクリーン交換可能
    • そもそも標準スクリーンが新開発らしいけど
  • 暗い場所でのAF

デメリット

  • あおり方向の水準器がない
  • SDカードオンリー
  • 視野率97%
  • 素子サイズが誤差レベルだけどちょっと小さい
  • マルチコントローラがない
2012年 11月 21日

レンズの解像度限界

センサーの高解像度化はどこまで可能なのか、実際今はどれぐらい限界に近付いているのかが気になった。

収差が全くないレンズであっても、回折によって解像度は低下してしまう。これは物理的にどうしようもない限界だ。Wikipedia のエアリーディスクの項を読むと比較的わかりやすい気がする。

ありがいたいことにカメラにおける分解能限界の式も求めてあるので、あてはめて JS で計算してみた。

/**
 * F値 `f`, 波長 `lambda` nm における分解能 (mm)
 */
function rayleighLimit (f, lambda) {
	return 1.22 * (lambda * 0.000001 * f);
}

// 500nm は緑
console.log('rayleighLimit F32', rayleighLimit(32, 500));
//=> rayleighLimit F32 0.01952
console.log('rayleighLimit F11', rayleighLimit(11, 500));
//=> rayleighLimit F11 0.00671
console.log('rayleighLimit F8', rayleighLimit(8, 500));
//=> rayleighLimit F8 0.00488
console.log('rayleighLimit F5.6', rayleighLimit(5.6, 500));
//=> rayleighLimit F5.6 0.0034159999999999998
console.log('rayleighLimit F2.8', rayleighLimit(2.8, 500));
//=> rayleighLimit F2.8 0.0017079999999999999

光の波長によって変わるらしいが (波長が長いほど分解能は低下する)、この例では人間の目が一番感じやすいらしい緑の波長に設定した。

Canon EOS 5D Mark II のピクセルサイズは 0.0064 mm ぐらいなので、F11 ぐらいになると1ピクセルを超えてしまうようだ。Nikon D800 だとピクセルサイズが 0.0049mm ぐらいで F8 ぐらいが物理的なぎりぎりになってしまう。

結論

  • 既に割と限界ぎりぎり
  • 開放すれば回折の影響は出なくなるけど、今度は収差がでる (どれぐらいでるかはわからない。物理的に無収差にできるのかもわからない)
    • さらにはボケてしまう (ピント面外の解像度が低下する)
  • F8 がだいたい最高解像度になるみたいな話は収差と回折のバランスをとった答えのようだ
  • さらなる解像度を求めるなら大判にするしかない
2012年 09月 26日

手ぶれを無視できるシャッタースピード

手ブレについて考えたことがあるけど、ずばり焦点距離が 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」で手ブレが無視できるようになる。

画質の評価とかをする場合、十分にシャッタースピードが早いかを確認する必要がありそうだと思った。

2012年 09月 19日

写真のプリント画質と画角・人間の視力

「標準レンズ」について では、理想的なカメラと理想的なレンズを仮定して考えていたので、以下の点がひっかかっていた:

  • 超広角で撮影したとして、パースが正しくなるように大きく引き伸ばして十分な画質が得られるか
    • (十分な画質が得られなければ、リアリティが消失して「パースが正しい」ことが意味をなさないのではないか)

なので、現在のカメラで撮影された画像をプリントするとき、十分な画質を得られる最大出力サイズを考えてみることにした。

十分な画質

まずそもそも「十分な画質」とはなにかを考えないとどうしようもない。「十分な画質」について「隣あう画素同士の区別がつかない」として考えることにした。

一般的に印刷物では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を出すあたりがあやしい気がする)

2012年 09月 15日

「標準レンズ」について

「標準レンズ」の何が標準なのか、ここ数日考えてひとまず自分なりに結論を出したのでまとめてメモ

結論

一般的な鑑賞環境において、パースが自然、すなわち肉眼で見るパースとほぼ同じであること

前提

写真のパースは、一般的に説明するときには、焦点距離によって変化して、広角では遠近感が強調され、望遠では圧縮される、とされているが、厳密にはこれだけだと説明が不十分である。焦点距離の違いは、単に画像をどの大きさで (すなわち画角で) トリミングするかの違いでしかない。これは、無限の解像度を持つカメラと、無限の解像度を持ち収差のない超広角レンズさえあれば、後処理でトリミングすればいいだけなので、それ以上長い焦点距離のレンズなどいらないということを意味する。本質的に、レンズはパースを変化させない。

ではどこでパースの変化が起きるかというと、それは鑑賞環境、つまり出力サイズ (プリントサイズ) と、鑑賞者までの距離になってくる。もし広角レンズ、例えば17mmで撮影したとしても、2m 幅でそれをプリントしたものを、1m の距離から見れば、肉眼で見た場合のパースと同じになる。あくまで、あの強調されたパースは狭い出力サイズに無理矢理画像をつめこむから生まれている。カメラのファインダーの像の大きさというのも固定なので、レンズを変えるとパースが変化したように見える。

疑問

レンズ自体にパースの変化がないのに「標準レンズはパースが自然」というのはおかしい。どんな画角であろうと、出力サイズと鑑賞位置が「正しい」ければ、パースは自然になるはずである。

であるなら、出力サイズと鑑賞位置が暗黙のうちに決定されているのではないか

検証

とりあえずイメージできるように焦点距離から画角を求められるようにする。 Wikipediaによると、焦点距離からの画角は以下で求められる (JavaScript の式になおしてある)

// `size` (mm) サイズの素子で、焦点距離が `f` (mm) のときの画角 (radian)
function angleOfView (size, f) {
	return 2 * Math.atan(size / (2 * f));
}

例えば、35mm フルサイズで 50mm の焦点距離を持つレンズを使った場合、水平画角は angleOfView(36, 50) で求められる (JS の三角関数との兼ね合いで表示時以外はラジアンで表現) この場合だと、39.6度ぐらいになる。

// 一応ラジアン変換
function radiansToDegree (radian) {
	return radian * (180 / Math.PI);
}

function degreeToRadians (degree) {
	return degree * (Math.PI / 180);
}

この状態で撮影した写真を、同じ画角だけ占有するように出力サイズと鑑賞位置を調整するようにすれば、パースは崩れないことになる。

なので、以下のような関数を考える (鑑賞者が点・占有物を面にしたとき、面側に直角がくる直角三角形が2つ並ぶイメージ)。

// `distance` (mm) 離れた距離にある `size` (mm) のものが視野を占有する画角 (radian)
function angleByDistanceAndSize (distance, size) {
	var half = size / 2;
	return Math.atan(half / distance) * 2;
}

これを使うと、「30cm の距離で A4用紙を見る場合に占有される水平画角」は angleByDistanceAndSize(300, 297) で求められる (52度ぐらい)

52度の画角を持つレンズの焦点距離を求めると、「30cm の距離の A4用紙にプリントした場合にパースがぴったりになる焦点距離」が求められるはずなので、以下のような関数を定義した (angleOfView の逆関数)

// `size` (mm) サイズの素子で、画角が `angle` (radian) のときの焦点距離 (mm)
function angleToFocalLength (size, angle) {
	var a = Math.tan(angle / 2);
	return size / a / 2;
}

angleToFocalLength(36, angleByDistanceAndSize(300, 297)) とすれば、「30cm の距離の A4用紙にプリントした場合にパースがぴったりになる焦点距離」として 36mm が求められる。すなわちこの鑑賞環境の場合、36mm で撮影した写真だと、パースが最も自然になる。

同じように、一般的な鑑賞環境を想像して、最も自然なパースになる焦点距離がいくつかを求めてみる。

// 20cm で L版 (スナップ写真を自宅で見る)
angleToFocalLength(36, angleByDistanceAndSize(200, 127)) //=> 56mm

// 30cm で A4 (ちょっと大きめに出力したものを手元で見る)
angleToFocalLength(36, angleByDistanceAndSize(300, 297)) //=> 36mm

// 50cm で A3 (ちょっと大きめに出力したものを手元で見る)
angleToFocalLength(36, angleByDistanceAndSize(500, 420)) //=> 42mm

// 100cm で A3 (写真展みたいなところでちょっと離れて見る)
angleToFocalLength(36, angleByDistanceAndSize(1000, 420)) //=> 85mm

// 倍率0.71倍のファインダー
50 / 0.71 //=> 70mm
( angleToFocalLength(36, angleByDistanceAndSize(x, sizeByDistanceAndAngle(x, angleOfView(36, 50)) * 0.71)) )

と、だいたい標準と呼ばれるような焦点距離におさまってる。つまり、このような鑑賞環境においては「標準レンズ」と呼ばれるものを使っておくと、パースが自然に見える。

ちなみに魚眼レンズは、画像の作りかたが人間の眼とは違うので上記のルールには全くあてはまらない。angleOfView の式もあてはまらない (もっと広く写るように設計されてる)

2011年 12月 30日

株式会社はてなを退職

はてなに入社しました | Wed, Apr 1. 2009 - 氾濫原 から2年9ヶ月ぐらい経った。

新しい職場は決まっているけれど、うまく働けるか心配だ。

神奈川県に引越したので、たくさんのアニメが最速になった。

これからもよろしくお願い致します。

2011年 12月 20日

自宅の光回線を解約した。EVO WiMAX 付属の WiMAX + テザリングだけでどんぐらい生きていけるか試してみます。

課題

  • Windows 機の Wi-Fi の調子が悪い
  • PS3 がネットワークに繋らない

PS3 に関してはイーサネットコンバーターを買おうかと思っている……

 -

3.0 / 5.0

はこべさんに「え、PS3 無線LAN ついてますよ?」って言われて、いやーそんなはずは…… と言ってしまったが、無線LAN機能は普通についていて、普通に接続できた。

2011年 12月 13日

microdata の itemref の解釈

microdata の itemref の解釈がよくわからない。

itemref で指定した ID を持つ要素の下もまた、そのアイテムのプロパティとして加える的なことが書いてあるが、じゃあ itemref で指定した ID を持つ要素が、別の itemscope の中にあったらどうなるのか?というのがよくわからない。

たぶんどちらにも属するプロパティになる?ような気がするけど、うまく仕様を読めていない。

All itemref attributes in a Document must be such that there are no cycles in the graph formed from representing each item in the Document as a node in the graph and each property of an item whose value is another item as an edge in the graph connecting those two items.

500 Can't connect to whatwg.org:443 (certificate verify failed)

たぶんこの辺なんだけど、英語が難しくて正確に理解できないので書きながら理解することを試みる……

All itemref attributes in a Document must be such はいいとして、そのあとの区切りがどこに入ってるのか…

  • All itemref attributes in a Document must be such
    • that there are no cycles in the graph formed from representing
      • each item in the Document as a node in the graph
      • and
      • each property of an item whose value is another item as an edge in the graph
    • connecting those two items.

こう読むのかなあ。文意としては「どんな場合でも循環参照がおきてはならない」で、事例が書いてあると思う、のでそれぞれ訳したい感じだけど、うまく訳せない……

しかし、ここは単に循環参照に言及しているだけで、1つの itemprop が複数のアイテムに属するかどうかとは関係ないか…

2011年 12月 08日

Picasa web の画像

Picasa web の画像って直接貼れるんだなあ。あと URL 中の s700 とかを s1920 とか s280 に変えると自由な画像サイズになる。でも恒久的なURLである根拠がないので、安心してはる感じにはならない…… と思って根拠をさがした。


<img src="/images/entry/IMG_7521-1920.avif"/>

https://picasaweb.google.com/114431815111528304586/2011128#5683411105636128482

一通りさがして、ないなーと思ったけど、アルバムのページには「HTML を貼り付けてウェブサイトに埋め込む」というのがあって、この中の img は上記のような形式のURLになっているので、不変と思ってよさそうな気がする。

FAQ には

You can only embed images into a webpage that are 800 pixels or smaller along the largest dimension.

404 Not Found

と書いてあって、800px までなら自由に貼れるように読める。たぶん 800px ってのは Google+ が出る前の基準な気がするので (根拠なし)、今は 2048px まで貼れるのかな…… 一応、安全にウェブサイトに貼れるのは 800px までっぽい。

画像ストレージ再考

自分のサーバーに画像を置くのは厳しい。

  • 容量的
  • 借りているサーバーのネットワークスピード

とかがあるので、できればウェブサービスに置いておきたいという要求があり、今のところはてなフォトライフを使っている。はてなフォトライフは無料でも30MB/月で十分だろうというのと、CDN (アカマイ) を経由していて、画像サイズに制限がないのもよい。

Picasa も昔検討したことがあって、そのときは 800px までしか無料でアップロードできず諦めたのだけれど、Google+ のリリースにより 2048px までは容量にカウントされない、すなわち実質的容量無制限になったので、候補にあがってきた。ネットワーク的にも Google の配信なので信頼がおける。

Picasa を使うとして

しかし Picasa はインターフェイス的に僕にはちょっと使いにくい感じなのと、画像を簡単に貼りつけられる方法がないのがネックになっている。前者はたぶん慣れれば大丈夫なので、後者は実装で解決してみたい。

アップロードとかは Picasa 側でやるので、最新のアップロード画像から貼りつけるインターフェイスだけ実装することを考えたが、Picasa がユーザーの最新画像のフィードを吐いていないようなので、それをなんとかして作るところからになった。

写真一覧のフィードは調べていたら普通にあった…

撮った時刻でソートするようにした

そもそも PIcasa 側で JSONP に対応していることがわかった

404 Not Found に普通に書いてあった。リファレンスの読みかたがよくわかっていなかった…