質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
iPad

iPadは、Appleがデザインしたタブレット型コンピュータです。iPadアプリケーションは通常Xcode IDEのObjective-Cで書かれますが、iPadアプリケーションを組むためのほかのツールを使うことも可能です。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

iPhone

iPhoneとは、アップル社が開発・販売しているスマートフォンです。 同社のデジタルオーディオプレーヤーiPodの機能、電話機能、インターネットやメールなどのWeb通信機能の3つをドッキングした機器です。

解決済

【Swift/iOS】AVFoundationによるカメラの露出(明るさ)調整時に、被写体がブレる

tsuki01
tsuki01

総合スコア1753

iPad

iPadは、Appleがデザインしたタブレット型コンピュータです。iPadアプリケーションは通常Xcode IDEのObjective-Cで書かれますが、iPadアプリケーションを組むためのほかのツールを使うことも可能です。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

iPhone

iPhoneとは、アップル社が開発・販売しているスマートフォンです。 同社のデジタルオーディオプレーヤーiPodの機能、電話機能、インターネットやメールなどのWeb通信機能の3つをドッキングした機器です。

1回答

0評価

0クリップ

4259閲覧

投稿2020/06/19 11:12

編集2020/06/22 01:55

実現したいこと・発生している問題

現在、AVFoundationを利用したカメラ機能を開発しております。
iPhone標準のカメラアプリにある、露出調整(明るさ調整)と同等の機能を実装したいと考えているのですが、
実装したものだと露出を上げるほどに被写体がブレる(かくつくような動き)ようになります。

「露出を変更する = シャッタースピードが変わる」という認識でいます。
その影響で被写体がブレる現象が発生していると考えているのですが、iPhone標準のカメラではブレる現象が発生しません。

※以下、iPhoneのカメラアプリの露出調整機能
iPhoneカメラ

質問内容

どような実装を行えば、被写体がブレる現象を抑えられますでしょうか?
「露出を上げすぎないことで対応するしかない」、「ISO感度と組み合わせて実装する」など、何かアドバイスなどあればご回答をお願いしたいです。

補足情報(FW/ツールのバージョンなど)

  • 開発環境:Xcode11.2.1
  • 言語  :Swift5
  • 端末  :iPhoneX、iPadPro11インチ

参考にしたサイトなど

Swiftでカメラアプリを作成する(1) 
AVCamManual: Extending AVCam to Use Manual Capture API 
z-hao-wang / ios-pro-camera 

該当のソースコード

【露出調整箇所抜粋】
以下はAppleのサンプルソースを元に実装。
「case 1」配下で露出調整を行なっているのですが、ここの処理に問題があると想定しております。

Swift

// MARK: - Slider Action @IBAction func changeSlider(_ sender: UISlider) { let tag: Int = sender.tag do { try currentDevice!.lockForConfiguration() defer { currentDevice!.unlockForConfiguration() } // 露出、または ISO感度を設定 switch tag { case 1: // 露出調整 let p = Float64(pow(sender.value, kExposureDurationPower)) // Apply power function to expand slider's low-end range let minDurationSeconds = Float64(max(CMTimeGetSeconds(currentDevice!.activeFormat.minExposureDuration), kExposureMinimumDuration)) let maxDurationSeconds = Float64(CMTimeGetSeconds(currentDevice!.activeFormat.maxExposureDuration)) let newDurationSeconds = Float64(p * (maxDurationSeconds - minDurationSeconds)) + minDurationSeconds // Scale from 0-1 slider range to actual duration currentDevice!.setExposureModeCustom(duration: CMTimeMakeWithSeconds( newDurationSeconds, preferredTimescale: 1000*1000*1000 ), iso: AVCaptureDevice.currentISO, completionHandler: nil) case 2: // ISO感度調整 currentDevice!.setExposureModeCustom(duration: AVCaptureDevice.currentExposureDuration, iso: sender.value, completionHandler: nil) default: break } } catch { print("(error.localizedDescription)") } }

【処理全体】

Swift

import UIKit import AVFoundation class ViewController: UIViewController { @IBOutlet weak var cameraView: UIView! // プレビュー配置先のView var captureSession = AVCaptureSession() // セッション管理用 var mainCamera: AVCaptureDevice? // メインカメラ用 var innerCamera: AVCaptureDevice? // インカメラ用意 var currentDevice: AVCaptureDevice? // 現在利用中のカメラ用 var photoOutput : AVCapturePhotoOutput? // キャプチャーの出力データを受け付けるオブジェクト var cameraPreviewLayer : AVCaptureVideoPreviewLayer?// プレビュー表示用のレイヤ @IBOutlet weak var brightnessSlider: UISlider! // 露出用スライダー @IBOutlet weak var isoSlider: UISlider! // ISO感度用スライダー // 露出制御時用の定数 let kExposureDurationPower : Float = 4 // Higher numbers will give the slider more sensitivity at shorter durations let kExposureMinimumDuration: Float64 = 1.0/2000 // Limit exposure duration to a useful range // MARK: - Life Cycle override func viewDidLoad() { super.viewDidLoad() // カメラ周り設定 self.setupCaptureSession() self.setupDevice() self.setupInputOutput() self.setupPreviewLayer() self.captureSession.startRunning() // スライダー初期設定 self.setupSlider() } // スライダー初期設定 func setupSlider() { // 露出用スライダー設定 brightnessSlider.minimumValue = 0.0 brightnessSlider.maximumValue = 1.0 self.brightnessSlider.value = 0.5 // ISO感度用スライダー設定 isoSlider.minimumValue = Float(currentDevice!.activeFormat.minISO) isoSlider.maximumValue = Float(currentDevice!.activeFormat.maxISO) self.isoSlider.value = (isoSlider.minimumValue + isoSlider.maximumValue) / 2 } // MARK: - Camera Setting // カメラの画質の設定 func setupCaptureSession() { captureSession.sessionPreset = AVCaptureSession.Preset.photo } // デバイスの設定 func setupDevice() { // カメラデバイスのプロパティ設定 let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera], mediaType: AVMediaType.video, position: AVCaptureDevice.Position.unspecified) // カメラデバイスの取得 let devices = deviceDiscoverySession.devices for device in devices { if device.position == AVCaptureDevice.Position.back { mainCamera = device } else if device.position == AVCaptureDevice.Position.front { innerCamera = device } } // 起動時のカメラを設定 currentDevice = mainCamera // 露出とISO感度の初期値設定 do { try mainCamera!.lockForConfiguration() defer { mainCamera!.unlockForConfiguration() } mainCamera!.exposureMode = .custom mainCamera!.setExposureModeCustom(duration: AVCaptureDevice.currentExposureDuration, iso: AVCaptureDevice.currentISO, completionHandler: nil) } catch { print("(error.localizedDescription)") } } // 入出力データの設定 func setupInputOutput() { do { // 入力を初期化 let captureDeviceInput = try AVCaptureDeviceInput(device: currentDevice!) captureSession.addInput(captureDeviceInput) // 出力を初期化 photoOutput = AVCapturePhotoOutput() photoOutput!.setPreparedPhotoSettingsArray([AVCapturePhotoSettings(format: [AVVideoCodecKey : AVVideoCodecType.jpeg])], completionHandler: nil) captureSession.addOutput(photoOutput!) } catch { print(error) } } // カメラプレビュー用のレイヤを設定 func setupPreviewLayer() { // プレビューレイヤを初期化 self.cameraPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession) self.cameraPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill self.cameraPreviewLayer?.connection?.videoOrientation = AVCaptureVideoOrientation.portrait self.cameraPreviewLayer?.frame = view.frame self.cameraPreviewLayer?.frame = self.cameraView.bounds self.cameraView.layer.insertSublayer(self.cameraPreviewLayer!, at: 0) } // MARK: - Slider Action @IBAction func changeSlider(_ sender: UISlider) { let tag: Int = sender.tag do { try currentDevice!.lockForConfiguration() defer { currentDevice!.unlockForConfiguration() } // 露出、または ISO感度を設定 switch tag { case 1: let p = Float64(pow(sender.value, kExposureDurationPower)) // Apply power function to expand slider's low-end range let minDurationSeconds = Float64(max(CMTimeGetSeconds(currentDevice!.activeFormat.minExposureDuration), kExposureMinimumDuration)) let maxDurationSeconds = Float64(CMTimeGetSeconds(currentDevice!.activeFormat.maxExposureDuration)) let newDurationSeconds = Float64(p * (maxDurationSeconds - minDurationSeconds)) + minDurationSeconds // Scale from 0-1 slider range to actual duration currentDevice!.setExposureModeCustom(duration: CMTimeMakeWithSeconds( newDurationSeconds, preferredTimescale: 1000*1000*1000 ), iso: AVCaptureDevice.currentISO, completionHandler: nil) case 2: currentDevice!.setExposureModeCustom(duration: AVCaptureDevice.currentExposureDuration, iso: sender.value, completionHandler: nil) default: break } } catch { print("(error.localizedDescription)") } } }

2020.06.22追記

発生している現象をGIFにしてみました。
露出を上げる前は問題なくカメラプレビューが表示されますが、
露出を上げると、カメラプレビュー自体がブレるような動きになってしまいます。
※iPhoneの標準カメラアプリではこの様な現象は発生しないため、何か特殊な処理が必要なのでしょうか。

GIF

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

iPad

iPadは、Appleがデザインしたタブレット型コンピュータです。iPadアプリケーションは通常Xcode IDEのObjective-Cで書かれますが、iPadアプリケーションを組むためのほかのツールを使うことも可能です。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

iPhone

iPhoneとは、アップル社が開発・販売しているスマートフォンです。 同社のデジタルオーディオプレーヤーiPodの機能、電話機能、インターネットやメールなどのWeb通信機能の3つをドッキングした機器です。