使用Swift将相机焦点设置在Tap point上

时间:2014-10-31 19:54:01

标签: ios xcode swift camera avfoundation

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

但它似乎无法奏效。

欢迎任何建议!

7 个答案:

答案 0 :(得分:12)

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

答案 1 :(得分:3)

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

答案 2 :(得分:2)

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

答案 3 :(得分:1)

原来很简单:

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

答案 4 :(得分: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到1 - 不知道为什么会出现这种情况但似乎有必要让它正常工作(虽然测试它也有点棘手)。

答案 5 :(得分:1)

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

答案 6 :(得分:1)

我使用了AVFoundation库和Camera Manager的包装器。 我正在分享代码示例。您可以调整您的项目。 顺便说一句,你不能使用前置摄像头对焦相机。它不支持它。您只能调整前置摄像头的曝光。通过稀有相机,你可以做到。

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