在iOS上设置初始焦距

在iOS上设置初始焦距,ios,camera,focus,qr-code,Ios,Camera,Focus,Qr Code,我正在开发一个iOS应用程序,其中一个功能是扫描二维码。为此,我使用了优秀的库ZBar。扫描效果很好,通常速度很快。但是,当您使用较小的二维码时,扫描需要更长的时间,这主要是因为自动对焦需要一些时间来调整。我正在试验,注意到可以使用以下代码锁定焦点: AVCaptureDevice *cameraDevice = readerView.device; if ([cameraDevice lockForConfiguration:nil]) { [cameraDevice setFocu

我正在开发一个iOS应用程序,其中一个功能是扫描二维码。为此,我使用了优秀的库ZBar。扫描效果很好,通常速度很快。但是,当您使用较小的二维码时,扫描需要更长的时间,这主要是因为自动对焦需要一些时间来调整。我正在试验,注意到可以使用以下代码锁定焦点:

AVCaptureDevice *cameraDevice = readerView.device;
if ([cameraDevice lockForConfiguration:nil]) {
     [cameraDevice setFocusMode:AVCaptureFocusModeLocked];
     [cameraDevice unlockForConfiguration];
}
当成功扫描后使用此代码时,接下来的扫描非常快。这让我想知道,我能在扫描一个代码之前锁定焦点吗?该应用程序将只扫描相当小的二维码,因此永远不需要关注遥远的事物。当然,我可以实现像点击聚焦这样的功能,但我更愿意避免那个额外的步骤。 有没有办法做到这一点?或者,在处理较小的二维码时,是否有其他方法可以加快速度


//Alexander

在iOS7中,这现在是可能的

Apple已将属性autoFocusRangeRestriction添加到AVCaptureDevice类中。此属性属于enum AVCaptureAutoFocusRangeRestriction,它有三个不同的值:

  • AVCaptureAutoFocusRangeRestrictionNone-默认值,无限制
  • AVCaptureAutoFocusRangeRestrictionNear-重要的对象靠近相机
  • AVCaptureAutoFocusRangeRestrictionFar-重要的对象远离相机
  • 要检查该方法是否可用,我们应该首先检查autoFocusRangeRestrictionSupported属性是否为true。由于它仅在iOS7及以后的版本中受支持,我们还应该使用respondsToSelector,以便在早期的iOS版本中不会出现异常。
    因此,生成的代码应该如下所示:

    AVCaptureDevice *cameraDevice = zbarReaderView.device;
    if ([cameraDevice respondsToSelector:@selector(isAutoFocusRangeRestrictionSupported)] && cameraDevice.autoFocusRangeRestrictionSupported) {
        // If we are on an iOS version that supports AutoFocusRangeRestriction and the device supports it
        // Set the focus range to "near"
        if ([cameraDevice lockForConfiguration:nil]) {
            cameraDevice.autoFocusRangeRestriction = AVCaptureAutoFocusRangeRestrictionNear;
            [cameraDevice unlockForConfiguration];
        }
    }
    
    根据我最初的测试,这似乎在一定程度上加快了小二维码的扫描速度:)

    更新-iOS8 有了iOS8,苹果为我们提供了许多新的摄像头API。其中一种新方法是:

    - (void)setFocusModeLockedWithLensPosition:(float)lensPosition completionHandler:(void (^)(CMTime syncTime))handler
    
    此方法通过将镜头移动到0.0和1.0之间的位置来锁定焦点。我使用了这种方法,将镜头锁定在接近的值。然而,总的来说,它带来了更多的问题,然后才得以解决。您必须将二维码/条形码保持在一个非常特定的距离,当您有不同大小的代码时,这可能会导致问题。
    但是我想我已经找到了一个很好的替代锁定焦点的方法。当用户按下扫描按钮时,我将镜头锁定在近距离,当完成后,我将相机切换回自动对焦。这为我们提供了保持自动对焦的好处,但会迫使相机在可能找到二维码/条形码的近距离处开始拍摄。这与:

    cameraDevice.autoFocusRangeRestriction = AVCaptureAutoFocusRangeRestrictionNear;
    
    以及:

    结果是一个相当快的扫描仪。 我还使用iOS7中引入的API构建了一个自定义扫描仪,而不是使用ZBar。主要是因为ZBar libs已经过时了,就像iphone5推出ARMv7s时一样,我现在不得不为ARM64重新编译它


    //Alexander最近在iOS 8中添加了此配置!这几乎就像他们读取堆栈溢出一样

        /*!
     @method setFocusModeLockedWithLensPosition:completionHandler:
     @abstract
        Sets focusMode to AVCaptureFocusModeLocked and locks lensPosition at an explicit value.
    
     @param lensPosition
        The lens position, as described in the documentation for the lensPosition property. A value of AVCaptureLensPositionCurrent can be used
        to indicate that the caller does not wish to specify a value for lensPosition.
     @param handler
        A block to be called when lensPosition has been set to the value specified and focusMode is set to AVCaptureFocusModeLocked. If
        setFocusModeLockedWithLensPosition:completionHandler: is called multiple times, the completion handlers will be called in FIFO order. 
        The block receives a timestamp which matches that of the first buffer to which all settings have been applied. Note that the timestamp 
        is synchronized to the device clock, and thus must be converted to the master clock prior to comparison with the timestamps of buffers 
        delivered via an AVCaptureVideoDataOutput. The client may pass nil for the handler parameter if knowledge of the operation's completion 
        is not required.
    
     @discussion
        This is the only way of setting lensPosition.
        This method throws an NSRangeException if lensPosition is set to an unsupported level.
        This method throws an NSGenericException if called without first obtaining exclusive access to the receiver using lockForConfiguration:.
    */
    - (void)setFocusModeLockedWithLensPosition:(float)lensPosition completionHandler:(void (^)(CMTime syncTime))handler NS_AVAILABLE_IOS(8_0);
    

    编辑:这是AVCaptureDevice的一种方法相关:@amigable clark kant,是的,这似乎基本上是同一个问题,只是他想把焦点锁定在尽可能远的地方。似乎我当前的解决方案(第一次成功扫描后锁定焦点)或“点击对焦”是目前最好的解决方案。现在我如何强制照片应用程序近距离对焦?:-)轻敲屏幕总是想聚焦在背景上。我已经学会了锁定微距镜头的焦距,但我希望我可以用焦距限制器来代替。此外,API中是否有可以返回焦距的内容?这可能有助于创建一个应用程序,将位置信息添加到图片中,您需要的是主题位置,而不是设备位置。是的,这几乎就像他们真的在听一样:)我使用这种方法锁定焦点。但大多数时候,它造成的问题比解决的问题还多。您必须将二维码/条形码保持在一个非常特定的距离,当您有不同大小的代码时,这可能会导致问题。然而,我认为我找到了一个完全锁定焦点的很好的替代方法。当用户按下扫描按钮时,我会近距离锁定焦距,一旦完成,我会将相机切换回自动焦距。这样我们可以使用自动对焦,但相机的起始位置很好。
        /*!
     @method setFocusModeLockedWithLensPosition:completionHandler:
     @abstract
        Sets focusMode to AVCaptureFocusModeLocked and locks lensPosition at an explicit value.
    
     @param lensPosition
        The lens position, as described in the documentation for the lensPosition property. A value of AVCaptureLensPositionCurrent can be used
        to indicate that the caller does not wish to specify a value for lensPosition.
     @param handler
        A block to be called when lensPosition has been set to the value specified and focusMode is set to AVCaptureFocusModeLocked. If
        setFocusModeLockedWithLensPosition:completionHandler: is called multiple times, the completion handlers will be called in FIFO order. 
        The block receives a timestamp which matches that of the first buffer to which all settings have been applied. Note that the timestamp 
        is synchronized to the device clock, and thus must be converted to the master clock prior to comparison with the timestamps of buffers 
        delivered via an AVCaptureVideoDataOutput. The client may pass nil for the handler parameter if knowledge of the operation's completion 
        is not required.
    
     @discussion
        This is the only way of setting lensPosition.
        This method throws an NSRangeException if lensPosition is set to an unsupported level.
        This method throws an NSGenericException if called without first obtaining exclusive access to the receiver using lockForConfiguration:.
    */
    - (void)setFocusModeLockedWithLensPosition:(float)lensPosition completionHandler:(void (^)(CMTime syncTime))handler NS_AVAILABLE_IOS(8_0);