18

我正在开发一个 iOS 应用程序,其中一个功能是扫描 QR 码。为此,我使用了出色的库 ZBar。扫描工作正常,通常非常快。但是,当您使用较小的 QR 码时,扫描时间会更长,这主要是因为自动对焦需要一些时间来调整。我正在试验并注意到可以使用以下代码锁定焦点:

AVCaptureDevice *cameraDevice = readerView.device;
if ([cameraDevice lockForConfiguration:nil]) {
     [cameraDevice setFocusMode:AVCaptureFocusModeLocked];
     [cameraDevice unlockForConfiguration];
}

在成功扫描后使用此代码时,即将进行的扫描非常快。这让我想知道,我可以在扫描一个代码之前以某种方式锁定焦点吗?该应用程序只会扫描相当小的二维码,因此永远不需要关注远处的东西。当然,我可以实现诸如点击聚焦之类的东西,但最好我想避免那个额外的步骤。有没有办法做到这一点?或者在处理较小的二维码时是否有另一种加快速度的方法?

// 亚历山大

4

2 回答 2

23

在 iOS7 中,这现在是可能的!

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

  1. AVCaptureAutoFocusRangeRestrictionNone - 默认,无限制
  2. AVCaptureAutoFocusRangeRestrictionNear - 重要的主体靠近相机
  3. AVCaptureAutoFocusRangeRestrictionFar - 重要的主体远离相机

要检查该方法是否可用,我们应该首先检查属性 autoFocusRangeRestrictionSupported 是否为真。而且由于它仅在 iOS7 及更高版本中受支持,我们还应该使用 respondsToSelector,这样我们就不会在早期的 iO​​S 版本中遇到异常。
所以生成的代码应该是这样的:

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];
    }
}

根据我的初步测试,这似乎在某种程度上加快了小 QR 码的扫描速度:)

更新 - iOS8

在 iOS8 中,Apple 为我们提供了许多新的相机 API 供我们使用。这种新方法之一是:

- (void)setFocusModeLockedWithLensPosition:(float)lensPosition completionHandler:(void (^)(CMTime syncTime))handler

此方法通过将镜头移动到 0.0 和 1.0 之间的位置来锁定焦点。我玩弄了这个方法,将镜头锁定在接近的值。但是,总的来说,它引起的问题比解决的问题多。您必须将 QR 码/条形码保持在非常特定的距离,当您拥有不同大小的代码时,这可能会导致问题。
但。我想我找到了一个很好的替代方法来完全锁定焦点。当用户按下扫描按钮时,我将镜头锁定在近距离,完成后我将相机切换回自动对焦。这为我们提供了保持自动对焦的好处,但会迫使相机在可能找到 QR 码/条形码的近距离开始。这结合:

cameraDevice.autoFocusRangeRestriction = AVCaptureAutoFocusRangeRestrictionNear;

和:

cameraDevice.focusPointOfInterest = CGPointMake(0.5,0.5);

结果是一个非常活泼的扫描仪。我还使用 iOS7 中引入的 API 构建了一个自定义扫描仪,而不是使用 ZBar。主要是因为 ZBar-libs 已经过时了,当 iPhone 5 引入 ARMv7s 时,我现在不得不为 ARM64 重新编译它。

// 亚历山大

于 2013-09-25T10:31:39.983 回答
6

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 的一种方法

于 2014-12-06T03:54:42.833 回答