カメラの撮影パラメータの話

トップはこちら

https://qiita.com/Cy-San/items/a9ba0a642e96c04fbfa3

## 概要

カメラで被写体を撮影する際に設定するパラメータの定義を記載します。
それぞれのパラメータがどのような意味か理解できるようになれると嬉しいです。

以下のような要素があります。
* 撮影画角
    * 撮影素子サイズ
    * レンズ焦点距離
* 画像の明るさ
    * 絞り値
    * シャッタスピード
    * ISO感度
* 被写界深度
* フレームレート

## 撮影画角 (Angle of view)
画像の空間の範囲を角度で表したもの。視野(Field of view)と呼ばれることもあります。
画角は撮影素子の大きさとレンズ焦点距離から決定されます。
焦点距離が同じ場合には撮影素子が大きいほど画角が広くなり広い範囲を撮影することができます。（クロップファクター）。

画角θ、レンズ焦点距離f [mm]、撮影素子サイズS [mm]の関係は以下のようになります。

```math
\theta = 2\tan^{-1} \left( \frac{S}{2f} \right)
```
Sは垂直、水平、対角線サイズのどれかを使用して計算が可能です。

Rustで実装するとこんな感じです。
```rust
use std::f64::consts::PI;

// 撮影画角を計算する関数
fn calculate_aov(sensor_size: f64, focal_length: f64) -> f64 {
    // 画角をラジアン(弧度法)で計算
    let aov_theta = 2.0 * (sensor_size / (2.0 * focal_length)).atan();
    
    // ラジアンを度に変換
    aov_theta * 180.0 / PI
}

fn main() {
    // レンズ焦点距離 f [mm]
    let focal_length = 50.0;
    
    // 撮影素子サイズ S [mm]（例としてフルサイズセンサー36mmを使用）
    let sensor_size = 36.0;

    // 撮影画角を計算
    let aov = calculate_aov(sensor_size, focal_length);

    // 結果を出力
    println!("撮影画角: {:.2} 度", aov);
}
```

### 撮影素子サイズ
撮影素子とはCCDやCMOSを使用して光信号を画像として読み込む素子のことです。
素子サイズはカメラをによって固有の部品となります。一般的には素子サイズが大きいほど高解像度化やセンサーあたりの光量が多くできるため、画質が上がります。
撮影素子は歴史的背景からインチやフィルムサイズで表現されます。
| 名称 | サイズ |説明|
|:-:|:-:|:-:|
|フルサイズ(35mmフィルム)|36mm × 24mm|一般的な35mmフィルムと同じサイズで、高画質。多くのプロ用カメラで採用。|
|APS-C|23.6mm × 15.7mm|一般的なデジタル一眼レフやミラーレスカメラで使用され、手軽なサイズ。アスペクト比が(3:2)|
|マイクロフォーサーズ|17.3mm × 13mm|小型軽量ながら高画質を維持するセンサーで、ミラーレスカメラに最適化されている。|
|1インチセンサー|13.2mm × 8.8mm|コンパクトカメラや一部の高級コンパクトカメラで使用される。|
|中判センサー|44mm × 33mm|大きいセンサーで、非常に高画質。主に中判カメラで使用。|
|スマホ用センサー|約1/2.3インチ|スマートフォンでよく使われる小型のセンサー。|

### レンズ焦点距離
撮影レンズの焦点距離は厚肉レンズの後側主点と後側焦点までの距離のことです。
先ほど書いた通り、現在の環境では撮影素子はいろいろなサイズがあるため、それぞれの撮影素子に対しての性能を単純比較するために基準となるサイズを決める必要がありました。そこで「35mm換算焦点距離」として、一般的である35mmフィルムと表現した時の焦点距離を表す方法が生まれました。

対角線撮影素子サイズS、レンズ焦点距離fとすると以下のような関係になります。
![f35.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621879/33449128-dc74-acbe-c946-4d53f2558f49.png)

```math
\displaylines{ 
d = \sqrt{36^2 + 24^2} = \sqrt{1296 + 576} = \sqrt{1872} \approx 43.3 \, \text{mm} \\

f_{35} = f \times \frac{43.3}{S}
}
```

固定値だけど実装するならこんな感じ
```rust
// 35mm換算焦点距離を計算する関数
fn calculate_35mm_equivalent(focal_length: f64, sensor_diagonal: f64) -> f64 {
    // 35mmフルサイズセンサーの対角線長は43.3mm
    let full_frame_diagonal = 43.3;

    // 35mm換算焦点距離の計算
    focal_length * (full_frame_diagonal / sensor_diagonal)
}

fn main() {
    // 実際のレンズの焦点距離 (mm)
    let focal_length = 50.0;

    // 使用しているセンサーの対角線長 (mm) （例: APS-Cセンサーは約28.4mm）
    let sensor_diagonal = 28.4;

    // 35mm換算焦点距離を計算
    let equivalent_focal_length = calculate_35mm_equivalent(focal_length, sensor_diagonal);

    // 結果を表示
    println!("35mm換算焦点距離: {:.2} mm", equivalent_focal_length);
}

```
焦点距離によって以下のように呼ばれます。
| f < 50[mm] | 50[mm] | 50[mm] < f |
|:-:|:-:|:-:|
|広角レンズ|標準レンズ|望遠レンズ|

広角レンズで撮影した場合は、遠くの被写体は近くの被写体よりも小さく見えるようになります。
望遠レンズで撮影した場合は、遠くの被写体と近くの被写体の大きさの変化が少なくなります。(遠近感がなくなる)

上記の35mm換算焦点距離の計算式からもわかるように、撮影素子サイズと焦点距離は反作用します。
撮影素子サイズとレンズを組み合わせることによって狙った画角に調整して撮影を行うことができます。

:::note info
レンズ沼にはまろう
:::


## 画像の明るさ

撮影した画像が暗いと、極端に暗い部分が黒つぶれしてしまったり、熱や電気的なノイズのような外れ値を読み取ってしまった場合に強調表示されてしまうといった問題が発生します。
撮影した画像が明るすぎる場合には、明るい部分が白とびしてしまったりします。
そのため画像の特徴量を全て含めるように適切な明るさにして撮影してあげる必要があります。
この表現できる範囲のことを「ダイナミックレンジ(センサーが認識できる最大値と最小値の幅)」や「ラチチュード（露出寛容度）」と読んだりします。

:::note info
正確には意味合いは違いますが、どちらも超えると白とびや黒つぶれが発生するので同じような使われ方をしているイメージです。
:::

明るさのパラメータは「露出のトライアングル」と呼ばれており、絞り、シャッタスピード、ISO感度の３つがあります。

### 絞り
撮影レンズのサイズが大きいと集められる光の量が多くなるため明るい写真を撮影することができます。
焦点距離が離れると光源から発射されたエネルギーは分散してしまいます。例えば焦点距離が２倍になった場合面積は４倍になります。

焦点距離とレンズの直径で割った値を「Fナンバ」と呼びます。
Fナンバは値が小さいと光を集める性能が高くなります。

関係をレンズ直径D、焦点距離fとすると以下のようになる。
```math
Fナンバ = \frac{f}{D}
```
明るさの数値はFナンバの２乗に反比例する作用するため、F * √２ を行うと明るさは半分になります。

絞りはこのレンズの直径サイズDを可変させることで、画像の明るさを調整することができる機構ということですね。
絞りで設定した値は「F値」と呼ばれることが多いと思います。
全開まで絞りを開いた値を開放F値と呼び、それ以上F値を小さくすることはできません。

### シャッタスピード
撮影素子が光を受ける時間を調整するのがシャッタです。
シャッタを使って光を撮影素子に当てる時間のことをシャッタースピード（露光時間）と言います。
1/1000秒や1/2秒などの時間で表現されます。当たる時間が２倍になれば明るさも２倍になります。
機械的に光量を調整するメカニカルシャッタと電子的に調整する電子シャッタがあります。
電子シャッタは機械部分がないため高速に動作させることが可能です。

### ISO感度
フィルムの光の感度を100として基準にした場合の撮影素子の感度設定のことです。
設定を大きくすると、アナログ信号処理回路で信号を増幅して感度が上がります。

:::note info
オペアンプ沼にはまろう
:::

増幅する場合、信号とノイズの差があまりないため、信号を目的の大きさまで増幅すると必然的にノイズの影響も大きくなります。

これらの絞り、シャッタスピード、ISO感度にはそれぞれ特徴があります。
絞りによるピントへの影響、シャッタースピードによる移動ぶれ、ISO感度によるノイズ。
それらを考慮しながら、いい明るさで画像を撮影できるように調整することが必要です。

カメラによっては、問題ないラチチュードの範囲に収めるように撮影面の情報を制御部分にフィードバックして制御することで、自動撮影やオートフォーカスなどの機能を実現しているものもあります。

移動ぶれに関しては１画素以下のぶれであれば画像の影響は十分に小さいです。
被写体のぶれ量が１画素以下になるためのシャッタースピードを計算することができます。

```math
t_s \leq \frac{S \times R}{v \times f \times N}

```

実装すると以下のような感じです。
```rust
// シャッタースピードを分数形式に変換する関数
fn to_fractional_shutter_speed(shutter_speed: f64) -> String {
    if shutter_speed >= 1.0 {
        format!("{:.0}秒", shutter_speed) // 1秒以上の場合はそのまま秒として出力
    } else {
        let denominator = (1.0 / shutter_speed).round(); // 1/shutter_speedの逆数を求める
        format!("1/{:.0}秒", denominator) // 1/xの形式で出力
    }
}

fn calculate_shutter_speed(r: f64, v: f64, f: f64, s: f64, n: u32) -> f64 {
    // シャッタースピードを計算
    let t_s = (s * r) / (v * f * n as f64);
    t_s
}

fn main() {
    // 各パラメータの設定
    let distance_to_subject = 10.0;   // 被写体までの距離 R [m]
    let subject_speed = 5.0;          // 被写体の移動速度 v [m/秒]
    let focal_length = 50.0;          // レンズの焦点距離 f [mm]
    let sensor_size = 36.0;           // 撮影素子のサイズ S [mm]
    let pixel_count = 4000;           // 撮影素子の画素数 N

    // シャッタースピードの計算
    let shutter_speed = calculate_shutter_speed(
        distance_to_subject, 
        subject_speed, 
        focal_length, 
        sensor_size, 
        pixel_count
    );

    // 小数のシャッタースピードを分数形式に変換して表示
    let fractional_shutter_speed = to_fractional_shutter_speed(shutter_speed);
    println!("シャッタースピード: {}", fractional_shutter_speed);
}

```

移動する被写体をぶれなく撮影するためにはシャッタスピードを早くする必要があるが光量がたりなくなるため、絞りやISO感度などの数値も変更する必要が出てくるがピントやノイズの問題なども考える必要が出てきますね。
そのため、照明などを使用して物理的に明るくすることも有効な方法になります。

## 被写界深度
非常にざっくり説明するとピントが合う範囲のことです。
レンズモデルのカメラではピントという概念があります。

ある点光源と撮影面があった場合に光源をレンズ方向にずらすと、結像する場所は撮影面から離れる方向に移動します。
この時、撮影面では光源が分散されて面積を持つ円として撮影されます。
この円のことを錯乱円と呼びます。この錯乱円の許容できる大きさの最大値を許容錯乱円と呼びます。
レンズ方向と反対側にずらしても同じように錯乱円は発生します。
![DOF.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621879/70cb4742-9617-6393-f03b-b8ff4f4d758f.png)
このピントが合っていると許容できる範囲を被写界深度と呼びます。
上記の特性があるため、レンズ焦点距離、絞り、被写体距離、撮影素子サイズといった要素で変化するパラメータです。
ピントが合っている範囲が広い場合は、「被写界深度が深い」と表現されます。
ピントが合っている範囲が狭い場合は、「被写界深度が浅い」と表現されます。
どちらが悪いというわけではなく、画像の表現としてどちらも使用されるパラメータで自分が表現したい物に合わせて適切に設定できるとよさそうです。
例えば、画像処理を行うのであれば、被写界深度は深い画像の方が情報量は多いでしょう。しかし、機械学習などによって被写体のみを学習させたい場合などには被写界深度が浅い画像の方が適切な可能性もあります。（ただし、後処理で加工する場合は情報量が多い方が無難ですね）

被写界深度には以下のような特性があると言えます。
* 前側被写界深度よりも、後側被写界深度の方が深い
* 絞り値が同じであれば、レンズ焦点距離が短いほど深い
* レンズ焦点距離が同じであれば、絞り値が大きいほど深い
* 被写体距離が遠いほど深い

## フレームレート
動画像は複数枚の画像を切り替えるように表示することで実現しています。
胃病あたりに切り替えて表示する画像枚数のことをフレームレート[fps]と呼びます。
電子シャッタは高速に動作させることができるため、連続した画像を撮影することができます。
蛍光灯などの光源は東日本では100Hz、西日本では120Hzで点滅しているため、動画像にした場合画像ごとに明るさが異なる現象(フリッカ)が起きます。

:::note info
日本では、50Hzと60Hzの地域があり、東日本は50Hz、西日本は60Hzとなっています。 
これは、明治時代、関東ではドイツから50Hzの発電機を、関西ではアメリカから60Hzの発電機を輸入していたことが原因といわれています。
負の遺産ですね。
:::