DepthAPIとiPhone Xと私

## はじめに
この記事は[Livesense - 自 Advent Calendar 2017](https://qiita.com/advent-calendar/2017/livesense-ji)、9日目の記事です。
さて、本日、12月9日は何の日でしょうか?

そう。**自**分(私、shinfkd)の誕生日です。
ハッピーバースデー俺。35歳になりました。
定年です。
もうちょっと現役でいたいので、頑張ってプログラミングします。

さて、そんな12月9日。
**自**分の誕生日にからめて、何か誕生日ネタでもやろうかと考えてみたのですが、びっくりするくらい何もアイデアが浮かんでこなかったので、**自**己満足で趣味の写真に絡めて、iOS11のDepthAPIについて書いてみようと思います。

## DepthAPIとは
iPhoneでは、iPhone 7 Plusにて初めてデュアルカメラが搭載されました。
これは、単に広角/望遠の2種類のレンズが搭載されたというだけではなく、ポートレートモードを実現するためにも利用されています。
その、ポートレートモード時に使用されるのが、今回のテーマでもある深度情報(DepthData)です。
iPhone 7 Plus発売時のiOS10では、この深度情報に関するAPIが公開されていませんでしたが、iOS11からは公開され、開発者が利用することができます。
さらに、対応している端末もiPhone 8 Plus / iPhone Xと増えたため、今後利用シーンが増えるかも…?しれない?ということでちょっと調べてみました。

### 深度情報とは
さっそくDepth APIについて話していく前に、まずは深度情報について考えてみましょう。
深度情報。聞き慣れない言葉ですね。
簡単に言えば、撮影している対象との距離・奥行きの情報です。
今までの、1つのカメラによる撮影では、レンズに対して入ってくる光の情報のみのため、奥行きを計測することができませんでした。
しかし、iPhone 7/8 PlusとiPhone Xでは、2つのカメラを用いることによりそれを可能にしています。
では、どうしてカメラを2つ利用すると深度情報を得ることができるのでしょうか？

### どうやって深度情報を計測しているのか
簡単に言うと、視差を利用して計測しています。
例えば、下図のように2つのピンホールカメラがあった場合を考えてみましょう
<img width="787" alt="スクリーンショット 2017-12-07 20.58.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/37188/b8619f06-5837-3756-91f8-e08b81132939.png">

この時、対象の人を写すために入ってくるカメラの光は下図のようになります。
<img width="786" alt="スクリーンショット 2017-12-07 21.46.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/37188/cc97ccf5-09a4-30d5-eeac-743de24bcda1.png">

この状態から、人を遠ざけてみましょう。
すると、近くにいたときに比べて、センサー面で受け取る光が近づいていることがわかります。
<img width="786" alt="スクリーンショット 2017-12-07 21.51.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/37188/3baa35d7-87ae-3f7a-1ea4-5ce8228af477.png">

このように、光の感知場所の距離が離れているほど近くにあり、感知場所の距離が近いほど遠くに存在するということがわかります。
この、それぞれの距離を比率で計算することにより、深度を計測しています。

## ボケの表現
### 深度情報を用いたボケ
では、深度情報が得られると何が嬉しいのでしょうか。
最も一般的な実用例が、上述したポートレートモードでよく使用される「ボケ」の表現です。
実は、一般的なスマートフォンのカメラでは仕組み的に綺麗なボケを作ることが難しく、そのために深度情報を用いて擬似的にボケを作り出しているのです。
つまり、対象となる手前にあるものには何もエフェクトをかけず、遠くにあるものにボケのエフェクトをかけることで実現しています。
実際にiPhone Xで試してみましょう。
下の写真は、iPhone Xのポートレートモードで撮影した写真を、ポートレートのOn/Offで比較したものになります。

| エフェクト無し | エフェクト有り |
|:-----------------|:------------------|
| ![IMG_6853.jpg](https://qiita-image-store.s3.amazonaws.com/0/37188/2182467e-1b08-0070-0f78-467376087871.jpeg) | ![IMG_6853 2.jpg](https://qiita-image-store.s3.amazonaws.com/0/37188/299b9bf4-773b-b0f5-b845-a71084cea303.jpeg) |

本来そんなにボケていない写真に対して、エフェクトをかけているだけということがよくわかりますね。
しかし、普通に画像加工ソフトで行うのに比べて、実際の深度情報を元に加工を行っているため、違和感が少なく綺麗に表現できています。
さらに、深度情報を別に保持しているという利点から、CMで行われているような対象以外の背景を消すといったことも簡単に実現できます。

![IMG_6853 3.jpg](https://qiita-image-store.s3.amazonaws.com/0/37188/c2aef71d-634a-a972-7f87-437e2854ba5c.jpeg)

### 一眼レフカメラ等でのボケ
一方、一眼レフカメラ等で撮影した際のボケは、エフェクトなどではもちろんなく、ピントが合っていないことにより発生します。
これは、絞りという入ってくる光の量を調整する機能により実現しており、ざっくりの概念は下記の図のとおりとなります。(詳しい説明をすると長くなるので、絞りを開いて光を多くレンズに取り込むと、ピントが合っているもの以外がボケやすく、絞りを絞って光の量を少なくすると、ピントを合わせたもの以外の光でもはっきり写りやすくなる。あるいはピントが合う範囲(被写界深度)が広がる。くらいに理解してもらえれば大丈夫です。)

#### 絞りを開いた状態
<img width="787" alt="スクリーンショット 2017-12-07 23.54.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/37188/f6c322ae-ae5b-bbe4-da02-fb3147b73806.png">
図のとおり、絞りが開いていて光が多くレンズに入ってくる場合、ピントが合っている対象物以外の結像点は、センサーの位置からはだいぶずれてしまい、センサーに光が届いたときにはかなりぼやけてしまうことがわかります。

#### 絞りを絞った状態
<img width="786" alt="スクリーンショット 2017-12-07 23.55.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/37188/e7221e64-c2fd-1892-1025-71a432c699cf.png">
一方、絞りを絞った場合は、レンズに入ってくる光の量が少なくなり、絞りを開いたときに比べて、ピントが合っていない背景の木の光も、ぼやけ具合が小さくなっていることがわかります。
(昔懐かしの、テレフォンカードに空いた穴を通して見ると、目が悪い人でもくっきり見えるというのと同じ原理ですね)
このように、普通のカメラでは大きい絞りとレンズ焦点距離により手軽に実現できるボケが、スマートフォンで実現するには2つのカメラによる深度情報の計算、エフェクトの追加という手間がかかることがわかります。
しかし、深度情報を用いて擬似的に好きなエフェクトを掛けることができるということは、大きな利点にもなります。

## DepthAPIの利用方法・活用方法
では、実際にDepthDataを利用するにはどうしたらいいのでしょうか。
DepthData及びそれを利用するために必要なAPIは[AVFoundation](https://developer.apple.com/documentation/avfoundation)に含まれており、下記のようなコードを書くことでじｋ…
って言うところで、解説コードを書こうと思いましたが、Appleが用意している[サンプルコード](https://developer.apple.com/library/content/samplecode/AVCam/Introduction/Intro.html)まんまになりそうなのと、上の解説で力使いすぎて時間切れなのでこのあたりで…。
最後に、サンプルコードを動かしてみた動画を載せておきます。

### サンプルコード実行動画
![demo.gif](https://qiita-image-store.s3.amazonaws.com/0/37188/1d1b4cdc-986c-ee71-3f0b-c416dae0ec15.gif)

深度情報が可視化され、近くにあるものほど明るく、遠くにあるものが暗くなっていることがわかりますね :)

## まとめ
いかがでしたでしょうか。
なんだよ、ただ白黒になっただけじゃんって思いました?

いえいえ、これが実はとても素晴らしい情報なんです。
例えば、iPhone Xで実現したFace IDは、この技術を用いており、単なる平面的な画像による顔認識ではなく、3次元の凹凸まで含めた情報を用いることで個人を識別しています。

他にも、深度情報を用いれば手軽に背景だけを別画面に合成できますし、ARKitと組み合わせれば…とかって考えると夢が広がりませんか?
今のところ使える機種が限られているのが非常に残念ですが、殆どの機種に搭載されるときが来たら、きっと面白い、便利なアプリが増えてくることでしょう。

今後が楽しみですね！

それでは皆さん、Happy Birthday!!🎂