现在,在我的相机应用程序中,我可以让用户触摸任何地方以设置焦点和曝光,但是像苹果的相机应用程序一样,我如何才能兼得两者?

例如,用户可能希望触摸以聚焦在前景中的某物上,但是如果场景发生足够的变化,则应返回为ContinuousAutoFocus。同样,如果用户将相机对准光源,则应更改曝光以使其正确显示,然后,当相机返回场景时,应再次固定曝光,使其不会太暗。但是,他们仍然可以选择使它更亮或更暗,具体取决于他们通过相机 View 所触摸的物体。

现在,当 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")
        }
    }
}

这里的技巧是不要将autoFocus与ContinuousAutoFocus混淆。默认情况下,它通过这种方式不断观察场景并设置焦点和曝光。同样,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中注册通知,以将焦点和曝光模式重新设置为连续模式。在这里,我只是调用设置了continuous默认设置的函数:
    NotificationCenter.default.addObserver(self,
                                           selector: #selector(self.setDefaultFocusAndExposure),
                                           name: NSNotification.Name.AVCaptureDeviceSubjectAreaDidChange,
                                           object: nil)

不要忘记在NotificationCenter中删除观察者:
deinit {
    NotificationCenter.default.removeObserver(self)
}

08-05 22:59