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

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

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

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

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")
        }
    }
}

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)
}
Другие вопросы по тегам