iOS轻触以聚焦

laik7k3q  于 2022-11-19  发布在  iOS
关注(0)|答案(8)|浏览(129)

我用这段代码在iOS自定义相机应用中实现了点击对焦,但它不起作用。

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    let touchPer = touches.anyObject() as UITouch
    let screenSize = UIScreen.mainScreen().bounds.size
    var focus_x = touchPer.locationInView(self.view).x / screenSize.width
    var focus_y = touchPer.locationInView(self.view).y / screenSize.height

    if let device = captureDevice {
        if(device.lockForConfiguration(nil)) {
            device.focusMode = AVCaptureFocusMode.ContinuousAutoFocus

            device.focusPointOfInterest = CGPointMake(focus_x, focus_y)
            device.exposureMode = AVCaptureExposureMode.ContinuousAutoExposure
            device.unlockForConfiguration()
        }
    }
}
nhhxz33t

nhhxz33t1#

使用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)) {
            if device.focusPointOfInterestSupported {
                device.focusPointOfInterest = focusPoint
                device.focusMode = AVCaptureFocusMode.AutoFocus
            }
            if device.exposurePointOfInterestSupported {
                device.exposurePointOfInterest = focusPoint
                device.exposureMode = AVCaptureExposureMode.AutoExpose
            }
            device.unlockForConfiguration()
        }
    }
}

请注意,我必须交换xy坐标,并将x坐标从1重新Map到0,而不是从0Map到1 -不知道为什么会这样,但似乎有必要让它正常工作(尽管测试它也有点棘手)。
编辑:Apple的文档解释了坐标变换的原因。
此外,设备可能支持感兴趣的焦点。您可以使用focusPointOfInterestSupported测试是否支持。如果支持,则使用focusPointOfInterest设置焦点。您传递一个CGPoint,其中{0,0}表示图片区域的左上角,{1,1}表示横向模式下的右下角,主页按钮位于右侧-即使设备处于纵向模式,这也适用。
在我的示例中,我使用了.ContinuousAutoFocus.ContinuousAutoExposure,但文档指出.AutoFocus是正确的选择。奇怪的是,文档没有提到.AutoExpose,但我在代码中使用了它,它工作得很好。
我还修改了我的示例代码以包含.focusPointOfInterestSupported.exposurePointOfInterestSupported测试-文档中还提到,在设置之前,对给定的聚焦/曝光模式使用isFocusModeSupported:isExposureModeSupported:方法来测试它在给定的设备上是否可用,但我假设如果设备支持兴趣点模式,那么它也支持自动模式。这一切似乎在我的应用程序中运行良好。

unftdfkk

unftdfkk2#

Swift 3.0解决方案

用Swift 3将Cody的答案转换为工作解决方案。

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    let touchPoint = touches.first! as UITouch
    let screenSize = cameraView.bounds.size
    let focusPoint = CGPoint(x: touchPoint.location(in: cameraView).y / screenSize.height, y: 1.0 - touchPoint.location(in: cameraView).x / screenSize.width)

    if let device = captureDevice {
        do {
            try device.lockForConfiguration()
            if device.isFocusPointOfInterestSupported {
                device.focusPointOfInterest = focusPoint
                device.focusMode = AVCaptureFocusMode.autoFocus
            }
            if device.isExposurePointOfInterestSupported {
                device.exposurePointOfInterest = focusPoint
                device.exposureMode = AVCaptureExposureMode.autoExpose
            }
            device.unlockForConfiguration()

        } catch {
            // Handle errors here
        }
    }
}
toe95027

toe950273#

device.focusPointOfInterest = focusPoint
 device.focusMode = AVCaptureFocusMode.AutoFocus
 device.exposurePointOfInterest = focusPoint
 device.exposureMode = AVCaptureExposureMode.ContinuousAutoExposure

我不知道为什么会这样,但确实如此。

0vvn1miw

0vvn1miw4#

你应该在focusPointOfInterest上读一读Apple docs,它说了三件重要的事情:
1.设置此属性的值不会启动聚焦操作。若要将照相机聚焦在感兴趣的点上,请首先设置此属性的值,然后将focusMode属性设置为autoFocus或continuousAutoFocus。
1.此属性的CGPoint值使用一个坐标系,其中{0,0}是图片区域的左上角,{1,1}是右下角。此坐标系始终相对于横向设备方向,主页按钮在右侧,而与实际的设备方向无关。您可以使用AVCaptureVideoPreviewLayer方法在此坐标系和视图坐标之间进行转换。
1.在更改此属性的值之前,必须调用lockForConfiguration()以获取对设备配置属性的独占访问权限。否则,设置此属性的值将引发异常。配置完设备后,请调用unlockForConfiguration()以释放锁定并允许其他设备配置设置。
下面是一个实现,它可以完成所有这些任务:

// In your camera preview view    
@objc private func cameraViewTapped(with gestureRecognizer: UITapGestureRecognizer) {
    let location = gestureRecognizer.location(in: self)
    addFocusIndicatorView(at: location) // If you want to indicate it in the UI

    // This is the point you want to pass to your capture device
    let captureDeviceLocation = previewLayer.captureDevicePointConverted(fromLayerPoint: location)

    // Somehow pass the point to where your AVCaptureDevice is
    viewDelegate?.cameraPreviewView(self, didTapToFocusAt: captureDeviceLocation) 
}

// In your camera controller
func focus(at point: CGPoint) {
    guard let device = videoDevice else {
        return
    }

    guard device.isFocusPointOfInterestSupported, device.isExposurePointOfInterestSupported else {
        return
    }

    do {
        try device.lockForConfiguration()

        device.focusPointOfInterest = point
        device.exposurePointOfInterest = point

        device.focusMode = .continuousAutoFocus
        device.exposureMode = .continuousAutoExposure

        device.unlockForConfiguration()
    } catch {
        print(error)
    }
}
qmb5sa22

qmb5sa225#

设置焦点兴趣点的更好方法:

  • 首先计算兴趣点:
let devicePoint: CGPoint = (self.previewView.layer as!  AVCaptureVideoPreviewLayer).captureDevicePointOfInterestForPoint(gestureRecognizer.locationInView(gestureRecognizer.view))
  • 之后,设置感兴趣的焦点:
let device: AVCaptureDevice! = self.videoDeviceInput!.device

    do {
        try device.lockForConfiguration()

        if device.focusPointOfInterestSupported && device.isFocusModeSupported(focusMode){

            device.focusPointOfInterest = devicePoint
            device.focusMode = focusMode
        }

        device.unlockForConfiguration()

    }catch{
        print(error)
    }
i2byvkas

i2byvkas6#

您必须以正确的顺序调用这些方法:

if(device.lockForConfiguration(nil)) {

    device.focusPointOfInterest = CGPointMake(focus_x, focus_y)
    device.focusMode = AVCaptureFocusMode.ContinuousAutoFocus

    device.exposureMode = AVCaptureExposureMode.ContinuousAutoExposure
    device.unlockForConfiguration()
}

在设置聚焦模式之前设置关注点,否则将在前一个关注点上进行聚焦。
这同样适用于exposurePointOfInterest

fdbelqdn

fdbelqdn7#

Swift 5.0版本

// The back camera as default device
var captureDevice: AVCaptureDevice? {
    return AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back)
}

// The camera view.
var cameraView: UIView!

// The layer that contains the camera output
var previewLayer: AVCaptureVideoPreviewLayer

// The focus square view - the yellow one ;)
var squareFocusView: UIView

// User taps on screen to select focus
@IBAction func tapToFocus(_ sender: UITapGestureRecognizer) {
    // make sure we capture one tap only
    if (sender.state == .ended) {
        
        guard let captureDevice = captureDevice else {
            return
        }
        
        let tappedFocusPoint = sender.location(in: cameraView)
        
        // we need to move the focus point to be the center of the tap instead of (0.0, 0.0)
        let centerX = tappedFocusPoint.x - (squareFocusView.frame.size.width / 2.0)
        let centerY = tappedFocusPoint.y - (squareFocusView.frame.size.height / 2.0)

        let focusPoint = CGPoint(x: centerX, y: centerY)
        
        // we need to remap the point because of different coordination systems.
        let convertedFocusPoint = previewLayer.captureDevicePointConverted(fromLayerPoint: focusPoint)
        
        do {
            // changing focusMode and exposureMode requires the device config to be locked.
            try captureDevice.lockForConfiguration()
            
            if (captureDevice.isFocusModeSupported(.autoFocus) && captureDevice.isFocusPointOfInterestSupported) {
                captureDevice.focusPointOfInterest = convertedFocusPoint
                captureDevice.focusMode = .autoFocus
            }
            
            if (captureDevice.isExposureModeSupported(.autoExpose) && captureDevice.isExposurePointOfInterestSupported) {
                captureDevice.exposurePointOfInterest = convertedFocusPoint
                captureDevice.exposureMode = .autoExpose
            }
            
            // unlocks device config
            captureDevice.unlockForConfiguration()
            
        } catch {
            // handle error here
        }
    }
}
k2arahey

k2arahey8#

雨燕4:

public override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    var touchPoint = touches.first as! UITouch
    let cameraView = cameraViewController.view
    var screenSize = cameraView!.bounds.size
    var focusPoint = CGPoint(x: touchPoint.location(in: cameraView).y / screenSize.height, y: 1.0 - touchPoint.location(in: cameraView).x / screenSize.width)
    
    
    
    
    if #available(iOS 10.0, *) {
        let device = AVCaptureDevice.default(.builtInWideAngleCamera,
                                             for: .video, position: .unspecified)
        
        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{
            
        }
           
  
            
        
    } else {
        // Fallback on earlier versions
    }
     
}

相关问题