iPhone 15 Pro/Pro Max で発生する、近距離でカメラのフォーカスが合わない問題への対応
※この記事は Luup Developers Advent Calendar の13日目の記事です。
こんにちは、11月にLuupに入社したてほやほやのつぼやん(@tsuboyan5)です。iOSエンジニアとして、Software Developmentチームで楽しくLUUPアプリの開発に携わっています。
今回はカメラについての話題です。
カメラを扱っているiOSのアプリには広く影響している内容だと思いますので、ぜひご覧いただければと思います!
はじめに
LUUPアプリでは、車両のQRコードを読み取って、鍵の開錠を行うことができます。
しかし、iPhone 15 Pro を使うユーザ様より、「QRコードにカメラを近づけるとフォーカスが合いません」という内容の問い合わせがありました。
手元で検証したところ、以下の画像の様に近距離のフォーカスが合わなくなっていました。
フォーカスが合わなくてQR読み取りができない様子 (iPhone 15 Pro, LUUP v1.69.0)
QRコードの読み取りにおいて、近距離で撮影することは自然なことであるため、この問題が解決できないか、調査をはじめました。
おさらい:カメラの種類
原因の調査の前に、iPhoneのカメラについておさらいしておきたいと思います。
端末によって搭載されているカメラの個数・種類は異なっているので、気にかけておく必要があります。
iPhoneモデル | 超広角カメラ | 広角カメラ(メインカメラ) | 望遠カメラ |
---|---|---|---|
8 / SE (第2・3世代) / XR | ❌ | ⭕️ | ❌ |
8 Plus / X / XS / XS Max | ❌ | ⭕️ | ⭕️ |
11・12・13・14・15 (無印 / mini / Plus) | ⭕️ | ⭕️ | ❌ |
11・12・13・14・15 (Pro / Pro Max) | ⭕️ | ⭕️ | ⭕️ |
すべての端末には共通して広角カメラが搭載されており、これがメインのカメラとして使われています。
超広角カメラ・望遠カメラは、端末のモデルやシリーズによって、搭載/非搭載が変わります。
原因調査
LUUPアプリで使われているカメラの種類
LUUPアプリでは、元々キャプチャーデバイスを以下のように作成しており、カメラの種類の指定はしていませんでした。
let device = AVCaptureDevice.default(for: .video)
この場合、基本的にはメインカメラである広角カメラが使用されます。
広角カメラの最短撮影距離の調査
iPhone 15 Proでは、広角カメラがサポートする最短撮影距離(フォーカスを合わせられる最短の距離)が変わっている可能性があるので、調査してみます。
カメラの最短撮影距離は、以下のように minimumFocusDistance プロパティで取得することができます。
print(device.minimumFocusDistance) // mm 単位で最短撮影距離が出力される
以下は、手持ちのiPhoneで広角カメラの最短撮影距離を出力した結果です。
iPhoneモデル | 最短撮影距離 |
---|---|
8 | 10cm |
12 Pro | 12cm |
15 Pro | 20cm |
なんと、iPhone 15 Pro では、最短撮影距離が非常に長くなっており、被写体との距離が20cm以下ではフォーカスが合わなくなっているようでした。
ハードウェアレベルの話になるため、これでは広角カメラだけで近距離の撮影をすることはできないという結論になりました。
対応策
その1. 超広角カメラを使う
広角カメラで近距離のフォーカスを合わせられないのであれば、別のカメラを使用するしかありません。
iPhone 15 Pro
の超広角カメラの最短撮影距離は 2cm であり、短距離でフォーカスを合わせることができます。
そのため、超広角カメラを指定することが、今回の問題に対処する最もシンプルな解となります。
実装としては以下のように、DeviceType に.builtInUltraWideCamera
を指定するだけで、超広角カメラを使用できるようになります。ただし、超広角カメラが利用できない場合は device
が nil になります。
let device = AVCaptureDevice.default(
.builtInUltraWideCamera, // 超広角カメラを利用する
for: AVMediaType.video,
position: .back
)
その2. 超広角カメラと広角カメラ両方を有効にした上でズーム倍率を調整する
LUUPアプリでは、これまでの広角カメラを使ったQRコード読み取りの使用感を崩さないために、この解決策を取りました。(v1.71.0 にてリリース済み)
超広角カメラと広角カメラを有効にした上で、ズームレベルを調整することで、これまでの広角カメラの画角を維持しながら短距離のフォーカスを合わせられるようになります。
実装としては以下のように、DeviceType に .builtInDualWideCamera
を指定して、広角・超広角の2つのカメラが有効となるキャプチャデバイスを作成した上で、広角カメラが使われる画角になるようズーム倍率を調整します。
こうすることで、OS側が被写体との距離、明るさなどにより自動でカメラを切り替えてくれます。
let device = AVCaptureDevice.default(
.builtInDualWideCamera, // 超広角カメラと広角カメラを利用する
for: AVMediaType.video,
position: .back
)
// そのままでは超広角カメラの画角になるため、広角カメラの画角になるようズームレベルを調整する
guard let zoomFactor = device?.virtualDeviceSwitchOverVideoZoomFactors.first else { return }
try? device?.lockForConfiguration()
device?.videoZoomFactor = CGFloat(truncating: zoomFactor)
device?.unlockForConfiguration()
virtualDeviceSwitchOverVideoZoomFactors
にはカメラが切り替わるポイントのズーム倍率の配列が格納されています。今回は、超広角カメラと広角カメラの倍率が切り替わるポイントの値が1つだけ格納されているため、.first
で取り出してvideoZoomFactor
にセットしています。
実際の動作は以下のようになります。端末を被写体に近づけるとカメラが切り替わりフォーカスが合っている様子がわかります。
カメラが切り替わりフォーカスが合う様子 (iPhone 15 Pro)
まとめ
発生していた問題:LUUPアプリでは iPhone 15 Pro で近距離のQRコードを読み取ろうとすると、フォーカスが合わない問題が発生していた
原因:iPhone 15 Pro の広角カメラの最短撮影距離(フォーカスが合わせられる距離)が20cmと、以前の端末と比較して長くなっていた
解決策:超広角カメラを使用する。LUUPアプリでは、広角カメラ使用時の画角を維持したかったため、超広角カメラと広角カメラ両方を有効にした上でズーム倍率を調整することで対応した
参考文献
宣伝
Luupではソフトウェアエンジニアを積極的に募集しています。採用情報もぜひ、ご参照ください!
Discussion
minimum focus distanceは日本語では最短撮影距離と呼ばれおり、焦点距離(focal length)とは別の概念として扱われています。
撮影距離と焦点距離を混同してしまうと分かりづらいと思いますのでfocus distanceは撮影距離と表現していただけるとありがたいです。
コメントありがとうございます。
ご指摘いただいた通りで、「撮影距離」に修正しました。