Swift: автофокус/экспозиция и непрерывный автофокус/экспозиция одновременно?

Прямо сейчас в моем приложении камеры я позволяю пользователю касаться любого места, чтобы установить фокус и экспозицию, но как я могу получить лучшее из обоих миров, как в приложении Apple Camera?

Например, пользователь может захотеть коснуться, чтобы сфокусироваться на чем-то, что находится на переднем плане, но если сцена достаточно изменится, он должен вернуться к непрерывному автофокусу. То же самое, если пользователь направляет камеру на источник света, она должна изменить экспозицию, чтобы свет отображался правильно, а затем, когда камера возвращается к сцене, она должна снова зафиксировать экспозицию, чтобы она не была слишком темной. Тем не менее, у них все еще есть возможность сделать его немного светлее или темнее в зависимости от того, к чему они прикасаются в поле зрения камеры.

Прямо сейчас я устанавливаю свои значения по умолчанию в центр экрана, когда появляется представление:

func setDefaultFocusAndExposure() {

    let focusPoint = CGPoint(x:0.5,y:0.5)

    if let device = AVCaptureDevice.default(for:AVMediaType.video) {
        do {
            try device.lockForConfiguration()
            if device.isFocusPointOfInterestSupported {
                print(focusPoint)
                device.focusPointOfInterest = focusPoint
                device.focusMode = AVCaptureDevice.FocusMode.autoFocus
            }
            if device.isExposurePointOfInterestSupported {
                device.exposurePointOfInterest = focusPoint
                device.exposureMode = AVCaptureDevice.ExposureMode.autoExpose
            }
            device.unlockForConfiguration()

        } catch {
            // Handle errors here
            print("There was an error focusing the device's camera")
        }
    }

}

Также я позволяю пользователю устанавливать фокус и экспозицию в зависимости от того, где они касаются:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    let bounds = UIScreen.main.bounds

    let touchPoint = touches.first! as UITouch
    let screenSize = bounds.size
    let focusPoint = CGPoint(x: touchPoint.location(in: view).y / screenSize.height, y: 1.0 - touchPoint.location(in: view).x / screenSize.width)

    if let device = AVCaptureDevice.default(for:AVMediaType.video) {
        do {
            try device.lockForConfiguration()
            if device.isFocusPointOfInterestSupported {
                device.focusPointOfInterest = focusPoint
                device.focusMode = AVCaptureDevice.FocusMode.autoFocus
            }
            if device.isExposurePointOfInterestSupported {
                device.exposurePointOfInterest = focusPoint
                device.exposureMode = AVCaptureDevice.ExposureMode.autoExpose
            }
            device.unlockForConfiguration()

        } catch {
            // Handle errors here
            print("There was an error focusing the device's camera")
        }
    }
}

person Chewie The Chorkie    schedule 28.03.2018    source источник


Ответы (1)


Догадаться. Сначала я вызываю метод myViewDidAppear, который устанавливает фокус и режим экспозиции по умолчанию:

@objc func setDefaultFocusAndExposure() {

    if let device = AVCaptureDevice.default(for:AVMediaType.video) {
        do {
            try device.lockForConfiguration()
                device.isSubjectAreaChangeMonitoringEnabled = true
                device.focusMode = AVCaptureDevice.FocusMode.continuousAutoFocus
                device.exposureMode = AVCaptureDevice.ExposureMode.continuousAutoExposure
            device.unlockForConfiguration()

        } catch {
            // Handle errors here
            print("There was an error focusing the device's camera")
        }
    }
}

Хитрость здесь заключалась в том, чтобы не спутать автофокус с непрерывным автофокусом. Таким образом, по умолчанию он постоянно наблюдает за сценой и устанавливает фокус и экспозицию. Также isSubjectAreaChangeMonitorEnabled — очень важный бит. Это позволяет вам зарегистрировать уведомление для вызова функции, когда сцена меняет фокус или экспозицию, чтобы вы могли переключать режим фокусировки. Подробнее об этом скоро.

Прикосновением к экрану можно установить фокус и экспозицию в зависимости от точки:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    let bounds = UIScreen.main.bounds

    let touchPoint = touches.first! as UITouch
    let screenSize = bounds.size
    let focusPoint = CGPoint(x: touchPoint.location(in: view).y / screenSize.height, y: 1.0 - touchPoint.location(in: view).x / screenSize.width)

    if let device = AVCaptureDevice.default(for:AVMediaType.video) {
        do {
            try device.lockForConfiguration()
            if device.isFocusPointOfInterestSupported {
                device.focusPointOfInterest = focusPoint
                device.focusMode = AVCaptureDevice.FocusMode.autoFocus
            }
            if device.isExposurePointOfInterestSupported {
                device.exposurePointOfInterest = focusPoint
                device.exposureMode = AVCaptureDevice.ExposureMode.autoExpose
            }
            device.unlockForConfiguration()

        } catch {
            // Handle errors here
            print("There was an error focusing the device's camera")
        }
    }
}

Зарегистрируйте уведомление в viewDidLoad, чтобы снова установить непрерывный режим фокусировки и экспозиции. Здесь я просто вызываю функцию, которая устанавливает непрерывные настройки по умолчанию:

    NotificationCenter.default.addObserver(self,
                                           selector: #selector(self.setDefaultFocusAndExposure),
                                           name: NSNotification.Name.AVCaptureDeviceSubjectAreaDidChange,
                                           object: nil)

Не забудьте удалить наблюдателей в NotificationCenter:

deinit {
    NotificationCenter.default.removeObserver(self)
}
person Chewie The Chorkie    schedule 06.04.2018
comment
Это сработало для меня в первых двух прогонах, а затем перестало фокусироваться и устанавливать экспозицию. Что может быть причиной - person Aakash Dave; 10.01.2019
comment
Для вашего устройства убедитесь, что вы вызываете device.unlockForConfiguration() - person Chewie The Chorkie; 10.01.2019
comment
Я звоню. Я не уверен, что здесь происходит не так. Я даже использовал распознаватели жестов - person Aakash Dave; 11.01.2019