IOS для фокусировки
Я использовал этот код для достижения Tap-to-Focus в приложении для пользовательских камер iOS, но он не работает. Здесь код
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
let touchPer = touches.anyObject() as UITouch
let screenSize = UIScreen.mainScreen().bounds.size
var focus_x = touchPer.locationInView(self.view).x / screenSize.width
var focus_y = touchPer.locationInView(self.view).y / screenSize.height
if let device = captureDevice {
if(device.lockForConfiguration(nil)) {
device.focusMode = AVCaptureFocusMode.ContinuousAutoFocus
device.focusPointOfInterest = CGPointMake(focus_x, focus_y)
device.exposureMode = AVCaptureExposureMode.ContinuousAutoExposure
device.unlockForConfiguration()
}
}
}
Ответы
Ответ 1
device.focusPointOfInterest = focusPoint
device.focusMode = AVCaptureFocusMode.AutoFocus
device.exposurePointOfInterest = focusPoint
device.exposureMode = AVCaptureExposureMode.ContinuousAutoExposure
Я не понимаю, почему это работает, но это так.
Ответ 2
При отображении видео videoView: UIView
и cameraDevice: AVCaptureDevice
для меня работает следующее:
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
var touchPoint = touches.first as! UITouch
var screenSize = videoView.bounds.size
var focusPoint = CGPoint(x: touchPoint.locationInView(videoView).y / screenSize.height, y: 1.0 - touchPoint.locationInView(videoView.x / screenSize.width)
if let device = cameraDevice {
if(device.lockForConfiguration(nil)) {
if device.focusPointOfInterestSupported {
device.focusPointOfInterest = focusPoint
device.focusMode = AVCaptureFocusMode.AutoFocus
}
if device.exposurePointOfInterestSupported {
device.exposurePointOfInterest = focusPoint
device.exposureMode = AVCaptureExposureMode.AutoExpose
}
device.unlockForConfiguration()
}
}
}
Обратите внимание, что мне пришлось поменять местами координаты x
и y
и переназначить координату x
от 1 до 0 вместо 0 до 1 - не уверен, почему это должно быть так, но кажется чтобы заставить его работать правильно (хотя и немного сложно проверить его).
Изменить: Документация Apple объясняет причину преобразования координат.
Кроме того, устройство может поддерживать интересующую точку фокусировки. Вы тестируете поддержку с помощью focusPointOfInterestSupported. Если он поддерживается, вы устанавливаете фокус с помощью focusPointOfInterest. Вы передаете CGPoint, где {0,0} представляет верхнюю левую часть области изображения, а {1,1} представляет нижний правый в альбомном режиме с кнопкой "домой" справа - это применяется, даже если устройство находится в портретном режиме.
В моем примере я использовал .ContinuousAutoFocus
и .ContinuousAutoExposure
, но документация указывает .AutoFocus
правильный выбор. Как ни странно, в документации не упоминается .AutoExpose
, но я использую его в своем коде, и он отлично работает.
Я также модифицировал свой примерный код, чтобы включить теги .focusPointOfInterestSupported
и .exposurePointOfInterestSupported
- в документации также упоминаются методы isFocusModeSupported:
и isExposureModeSupported:
для заданного режима фокусировки/экспозиции, чтобы проверить, доступна ли она для данного прежде чем устанавливать его, но я предполагаю, что устройство поддерживает режимы интереса, а также поддерживает автоматические режимы. В моем приложении все работает нормально.
Ответ 3
Лучший способ задать интересующую точку интереса:
-
сначала вычислите интересующую точку:
let devicePoint: CGPoint = (self.previewView.layer as! AVCaptureVideoPreviewLayer).captureDevicePointOfInterestForPoint(gestureRecognizer.locationInView(gestureRecognizer.view))
-
после этого задайте интересующую точку фокусировки:
let device: AVCaptureDevice! = self.videoDeviceInput!.device
do {
try device.lockForConfiguration()
if device.focusPointOfInterestSupported && device.isFocusModeSupported(focusMode){
device.focusPointOfInterest = devicePoint
device.focusMode = focusMode
}
device.unlockForConfiguration()
}catch{
print(error)
}
Ответ 4
Решение Swift 3.0
Преобразованный Коди отвечает на рабочее решение с Swift 3.
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touchPoint = touches.first! as UITouch
let screenSize = cameraView.bounds.size
let focusPoint = CGPoint(x: touchPoint.location(in: cameraView).y / screenSize.height, y: 1.0 - touchPoint.location(in: cameraView).x / screenSize.width)
if let device = captureDevice {
do {
try device.lockForConfiguration()
if device.isFocusPointOfInterestSupported {
device.focusPointOfInterest = focusPoint
device.focusMode = AVCaptureFocusMode.autoFocus
}
if device.isExposurePointOfInterestSupported {
device.exposurePointOfInterest = focusPoint
device.exposureMode = AVCaptureExposureMode.autoExpose
}
device.unlockForConfiguration()
} catch {
// Handle errors here
}
}
}
Ответ 5
Вы должны вызвать методы в правильном порядке:
if(device.lockForConfiguration(nil)) {
device.focusPointOfInterest = CGPointMake(focus_x, focus_y)
device.focusMode = AVCaptureFocusMode.ContinuousAutoFocus
device.exposureMode = AVCaptureExposureMode.ContinuousAutoExposure
device.unlockForConfiguration()
}
Задайте интересующую точку перед настройкой режима фокусировки, иначе фокус будет сделан на предыдущей интересующей точке.
То же самое относится к exposurePointOfInterest
.