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.