Swift:同时进行自动对焦/曝光和连续自动对焦/曝光?

标签 swift camera focus avcapturedevice exposure

现在在我的相机应用程序中,我允许用户触摸任意位置来设置焦点和曝光,但我如何才能像 Apple 的相机应用程序一样获得两全其美的效果?

例如,用户可能希望通过触摸来聚焦前景中的某物,但如果场景变化足够大,则应返回到连续自动对焦。同样,如果用户将相机指向一盏灯,它应该改变曝光以使其正确显示,然后当相机返回场景时它应该再次修复曝光以使其不会太暗。但是,他们仍然可以根据他们通过摄像头的视野触摸到的内容,将其调亮或调暗一些。

现在,当 View 出现时,我将默认设置为屏幕中心:

func setDefaultFocusAndExposure() {

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

    if let device = AVCaptureDevice.default(for:AVMediaType.video) {
        do {
            try device.lockForConfiguration()
            if device.isFocusPointOfInterestSupported {
                print(focusPoint)
                device.focusPointOfInterest = focusPoint
                device.focusMode = AVCaptureDevice.FocusMode.autoFocus
            }
            if device.isExposurePointOfInterestSupported {
                device.exposurePointOfInterest = focusPoint
                device.exposureMode = AVCaptureDevice.ExposureMode.autoExpose
            }
            device.unlockForConfiguration()

        } catch {
            // Handle errors here
            print("There was an error focusing the device's camera")
        }
    }

}

我还让用户根据他们触摸的位置设置焦点和曝光:

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

    let bounds = UIScreen.main.bounds

    let touchPoint = touches.first! as UITouch
    let screenSize = bounds.size
    let focusPoint = CGPoint(x: touchPoint.location(in: view).y / screenSize.height, y: 1.0 - touchPoint.location(in: view).x / screenSize.width)

    if let device = AVCaptureDevice.default(for:AVMediaType.video) {
        do {
            try device.lockForConfiguration()
            if device.isFocusPointOfInterestSupported {
                device.focusPointOfInterest = focusPoint
                device.focusMode = AVCaptureDevice.FocusMode.autoFocus
            }
            if device.isExposurePointOfInterestSupported {
                device.exposurePointOfInterest = focusPoint
                device.exposureMode = AVCaptureDevice.ExposureMode.autoExpose
            }
            device.unlockForConfiguration()

        } catch {
            // Handle errors here
            print("There was an error focusing the device's camera")
        }
    }
}

最佳答案

想通了。首先,我在 myViewDidAppear 上调用一个方法来设置我的默认焦点和曝光模式:

@objc func setDefaultFocusAndExposure() {

    if let device = AVCaptureDevice.default(for:AVMediaType.video) {
        do {
            try device.lockForConfiguration()
                device.isSubjectAreaChangeMonitoringEnabled = true
                device.focusMode = AVCaptureDevice.FocusMode.continuousAutoFocus
                device.exposureMode = AVCaptureDevice.ExposureMode.continuousAutoExposure
            device.unlockForConfiguration()

        } catch {
            // Handle errors here
            print("There was an error focusing the device's camera")
        }
    }
}

这里的技巧是不要将自动对焦与连续自动对焦混淆。这样默认情况下它会不断观察场景并设置焦点和曝光。 isSubjectAreaChangeMonitorEnabled 也是一个非常重要的位。这使您可以注册通知以在场景更改焦点或曝光时调用函数,以便您可以切换焦点模式。稍后会详细介绍。

在屏幕上的触摸可以根据一点设置焦点和曝光:

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

    let bounds = UIScreen.main.bounds

    let touchPoint = touches.first! as UITouch
    let screenSize = bounds.size
    let focusPoint = CGPoint(x: touchPoint.location(in: view).y / screenSize.height, y: 1.0 - touchPoint.location(in: view).x / screenSize.width)

    if let device = AVCaptureDevice.default(for:AVMediaType.video) {
        do {
            try device.lockForConfiguration()
            if device.isFocusPointOfInterestSupported {
                device.focusPointOfInterest = focusPoint
                device.focusMode = AVCaptureDevice.FocusMode.autoFocus
            }
            if device.isExposurePointOfInterestSupported {
                device.exposurePointOfInterest = focusPoint
                device.exposureMode = AVCaptureDevice.ExposureMode.autoExpose
            }
            device.unlockForConfiguration()

        } catch {
            // Handle errors here
            print("There was an error focusing the device's camera")
        }
    }
}

在 viewDidLoad 中注册通知以将焦点和曝光模式设置回连续。这里我只是调用设置连续默认设置的函数:

    NotificationCenter.default.addObserver(self,
                                           selector: #selector(self.setDefaultFocusAndExposure),
                                           name: NSNotification.Name.AVCaptureDeviceSubjectAreaDidChange,
                                           object: nil)

不要忘记在 NotificationCenter 中移除观察者:

deinit {
    NotificationCenter.default.removeObserver(self)
}

关于Swift:同时进行自动对焦/曝光和连续自动对焦/曝光?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49541837/

相关文章:

swift - swift 3 在iPhone 5 屏幕上更新约束后图片不存在

ios - 将 Swift._SwiftDeferredNSArray' (0x1096d26b8) 获取到核心数据中的 'NSMutableArray

ios - 我正在制作一个可以自行拍摄全景照片的 iOS 应用

wpf - 选择选项卡项内容时如何聚焦 WPF 选项卡项?

ios - 使用通知从后台唤醒 iOS 应用程序

ios - 如何从方法中快速更新 UI

c# - 如何在 Windows Phone 中旋转相机查看器?

c# - 准确的捏合缩放

java - JavaFX 2 小程序能否请求焦点并因此关注浏览器/选项卡?

jQuery focus() 在 FireFox 中不起作用,但在 Chrome 中起作用