使用Swift在相机上设置相机焦点

在swift中使用相机的API似乎是一个不同的,我很难在一个点上集中相机。 当用户点击屏幕时,我想让相机专注于这一点

这是我的代码:

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

但它似乎没有工作。

任何build议都比欢迎!

@ryantxr更新了Swift 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 } } } } 

@Code for Swift 2更新了答案。

 override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { let screenSize = videoView.bounds.size if let touchPoint = touches.first { let x = touchPoint.locationInView(videoView).y / screenSize.height let y = 1.0 - touchPoint.locationInView(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 } } } } 

这个问题也许是iOS重复的重点 ,我发布了这个(希望明确的)解决scheme,为我工作:

使用videoView: UIView显示video,以及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 – 不知道为什么应该是这种情况,但似乎有必要让它正常工作(尽pipe它有点棘手来testing它)。

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

我使用AVFoundation库和相机pipe理器的包装。 我正在共享代码示例。 你可以调整你的项目。 顺便说一下,您无法使用前置摄像头对相机进行对焦。 它不支持它。 您只能调整前置摄像头的曝光。 通过罕见的相机,你可以做到这一点。

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

更好的解决scheme,因为它适用于所有的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 } 

结果很简单:

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