2014-10-31 110 views
4

在swift中使用相機的API看起來很不同,但我很難將相機對焦在一個點上。當用戶點擊我希望相機專注於這一點用Swift設置拍照點的相機對焦

屏幕這是我的代碼:

func focusCamera(point:CGPoint) 
    { 
     var screenRect:CGRect = bounds 
     var focusX = Float(point.x/screenRect.width) 
     var focusY = Float(point.y/screenRect.height) 

     _currentDevice.lockForConfiguration(nil) 
     _currentDevice.setFocusModeLockedWithLensPosition(focusX) 
     { 
      time in 
      self._currentDevice.unlockForConfiguration() 
     } 

     _currentDevice.setFocusModeLockedWithLensPosition(focusY) 
     { 
       time in 
       self._currentDevice.unlockForConfiguration() 
     } 
    } 

但它似乎沒有工作。

任何建議都比歡迎!

回答

0

原來它很簡單:

_currentDevice.lockForConfiguration(nil) 
_currentDevice.focusPointOfInterest = tap.locationInView(self) 
_currentDevice.unlockForConfiguration() 
+3

能否請您提供更多信息...我是初學者,我不知道在哪裏把這段代碼 – 2015-04-08 22:14:24

1

這個問題也許是iOS tap to focus,我在那裏張貼工作對我來說這(希望明確的)解決方案重複:

隨着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)) { 
      device.focusPointOfInterest = focusPoint 
      device.focusMode = AVCaptureFocusMode.ContinuousAutoExposure 
      device.exposurePointOfInterest = focusPoint 
      device.exposureMode = AVCaptureExposureMode.ContinuousAutoExposure 
      device.unlockForConfiguration() 
     } 
    } 
} 

注意,我不得不調換xy座標,並將x座標從1重新映射到0而不是0到1 - 不知道爲什麼應該是這種情況,但它似乎有必要讓它正常工作(儘管測試它也有點棘手)。

1

雨燕2.0

if let device = captureDevice { 
    do { 
    try device.lockForConfiguration() 
    device.focusPointOfInterest = focusPoint 
    device.focusMode = AVCaptureFocusMode.ContinuousAutoFocus 
    device.exposurePointOfInterest = focusPoint 
    device.exposureMode = AVCaptureExposureMode.ContinuousAutoExposure 
    } catch let error as NSError { 
    print(error.localizedDescription) 
    } 
} 
+0

檢查@ ryantxr的答案如何計算focusPoint variab樂。 – SeanRobinson159 2016-06-16 15:01:23

2

更新從@code答案斯威夫特2.

​​
+0

完美答案!注意X和Y座標,它們是本例中*最重要的部分。根據apple文檔:「[focusPointOfInterest]表示一個CGPoint,其中{0,0}對應於圖片區域的左上角,{1,1}對應於橫向模式下的右下角,並且home按鈕處於打開狀態正確的「 – SeanRobinson159 2016-06-16 15:00:09

+0

該文件還說,我們應該在'AVCaptureVideoPreviewLayer' captureDevicePointOfInterest中使用點轉換方法。這個答案對我來說不正確,可能是因爲它忽略了設備方向。我寧願使用'CaptureDevicePointOfInterest'。 – fabb 2017-01-05 14:17:27

+0

此外,如果'videoView'與原始設備圖像輸出不具有相同的寬高比(例如,使用'videoGravity'時),此答案無法正常工作。 – fabb 2017-01-05 14:25:32

1

我用AVFoundation庫和包裝,攝像頭管理。 我正在共享代碼示例。你可以調整你的項目。順便說一下,您無法使用前置攝像頭對相機進行對焦。它不支持它。您只能調整前置攝像頭的曝光。通過罕見的相機,你可以做到這一點。

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

    let screenSize = cameraView.bounds.size 
    let frameSize:CGSize = view.frame.size 
    if let touchPoint = touches.first { 

     var location:CGPoint = touchPoint.locationInView(cameraView) 

     if cameraManager.cameraDevice == .Front { 
      print("Front camera is used") 

      location.x = frameSize.width - location.x; 
     } 
     else { 
      print("Back camera is used") 
     } 

     let x = location.x/frameSize.width 
     let y = 1.0 - (location.x/frameSize.width) 

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

     print("POINT : X: \(x), Y: \(y)") 


     let captureDevice = (AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo) as! [AVCaptureDevice]).filter{$0.position == .Back}.first 

     if let device = captureDevice { 
      do { 
       try device.lockForConfiguration() 

       let support:Bool = device.focusPointOfInterestSupported 

       if support { 

        print("focusPointOfInterestSupported: \(support)") 

        device.focusPointOfInterest = focusPoint 

        // device.focusMode = .ContinuousAutoFocus 
        device.focusMode = .AutoFocus 
        // device.focusMode = .Locked 

        device.unlockForConfiguration() 

        print("Focus point was set successfully") 
       } 
       else{ 
        print("focusPointOfInterestSupported is not supported: \(support)") 
       } 
      } 
      catch { 
       // just ignore 
       print("Focus point error") 
      } 
     } 
    } 
} 
9

更新回答從@ryantxr爲夫特3:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 
     let screenSize = videoView.bounds.size 
     if let touchPoint = touches.first { 
      let x = touchPoint.location(in: videoView).y/screenSize.height 
      let y = 1.0 - touchPoint.location(in: videoView).x/screenSize.width 
      let focusPoint = CGPoint(x: x, y: y) 

      if let device = captureDevice { 
       do { 
        try device.lockForConfiguration() 

        device.focusPointOfInterest = focusPoint 
        //device.focusMode = .continuousAutoFocus 
        device.focusMode = .autoFocus 
        //device.focusMode = .locked 
        device.exposurePointOfInterest = focusPoint 
        device.exposureMode = AVCaptureExposureMode.continuousAutoExposure 
        device.unlockForConfiguration() 
       } 
       catch { 
        // just ignore 
       } 
      } 
     } 
    } 
1

更好的解決方案,因爲它可以正確處理所有videoGravity模式,也當預覽層縱橫比爲從設備比率不同:

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

    guard let touchPoint = touches.first else { return } 

    // precondition: the videoView contains the previewLayer, and the frames of the two are being kept equal 
    let touchPointInPreviewLayer = touchPoint.location(in: videoView) 
    let focusPoint = previewLayer.captureDevicePointOfInterest(for: touchPointInPreviewLayer) 

    // etc 
}