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