xcode 使用 Swift 将相机焦点设置在点击点上

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26682450/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 06:03:49  来源:igfitidea点击:

Set Camera Focus On Tap Point With Swift

iosxcodeswiftcameraavfoundation

提问by Aggressor

The API for using the camera in swift seems a but different and I am having a hard time focusing the camera on a point. When the user taps the screen I want the camera to focus on that point

快速使用相机的 API 似乎有所不同,我很难将相机聚焦在一个点上。当用户点击屏幕时,我希望相机专注于该点

This is my code:

这是我的代码:

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

But it doesnt seem to work.

但它似乎不起作用。

Any suggestions are more than welcome!

任何建议都非常受欢迎!

采纳答案by Aggressor

Turns out its very simple:

事实证明它非常简单:

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

回答by OxyFlax

Updated answer from @ryantxr for Swift 3:

来自@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
                }
            }
        }
    }

回答by fabb

Better solution, as it works correctly for all videoGravitymodes, also when the preview layer aspect ratio is different from the device ratio:

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

回答by ryantxr

Updated answer from @Code for Swift 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
            }
        }
    }
}

回答by gkhanacer

I used AVFoundationlibrary and a wrapper that Camera Manager. I am sharing to code sample. You can adapt your project. By the way, you cannot focus the camera using front-camera. It doesn't support it. You can only adjust exposure for front-camera. By rare-camera, you can do it.

我使用了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{
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()
        }
    }
}
.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") } } } }

回答by Cody

This question maybe is a duplicate of iOS tap to focus, where I posted this (hopefully explicit) solution that worked for me:

这个问题可能是iOS tap to focus的重复,我在那里发布了这个(希望是明确的)对我有用的解决方案:

With a videoView: UIViewdisplaying the video, and cameraDevice: AVCaptureDevice, the following seems to work for me:

通过videoView: UIView显示视频和cameraDevice: AVCaptureDevice,以下内容似乎对我有用:

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

Note that I had to swap the xand ycoordinates, and remap the xcoord from 1 to 0 instead of 0 to 1 — not sure why that should be the case but it seems to be necessary to get it to work right (though it's a little tricky to test it too).

请注意,我必须交换xy坐标,并将坐标x从 1重新映射到 0 而不是 0 到 1 - 不知道为什么会这样,但似乎有必要让它正常工作(尽管这有点棘手也测试一下)。

回答by Cody

Swift 2.0

斯威夫特 2.0

##代码##