【问题标题】:Why is scanning barcodes using the new iOS 7 API really slow?为什么使用新的 iOS 7 API 扫描条形码真的很慢?
【发布时间】:2014-02-11 07:43:59
【问题描述】:

我目前正在尝试使用 iOS 7 的最新 api 来扫描代码 39 条码,但这让我发疯。我必须以特定的方式握住手机 10 秒钟,以便它检测到它。我将它与 Red Laser、Zbar 等进行了比较,即使它有点歪斜,他们也可以在 1 秒内对其进行分析。我不确定这是因为我加载捕获会话的方式还是什么。我会很感激帮助。有关如何提高性能的任何建议?

这是我在 viewDidLoad 方法中加载扫描仪的方式:

    //Initialize Laser View
    laserView = [[UIView alloc] init];
    laserView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleBottomMargin;
    laserView.layer.borderColor = [UIColor redColor].CGColor;
    laserView.layer.borderWidth = 8;
    laserView.layer.cornerRadius = 10;
    [self.view addSubview:laserView];

    //Start Session
    scannerSession = [[AVCaptureSession alloc] init];
    scannerDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    //Define Error Messages
    NSError *error = nil;

    //Define Input
    scannerInput = [AVCaptureDeviceInput deviceInputWithDevice:scannerDevice error:&error];

    //Check if Device has a Camera
    if (scannerInput) {
        [scannerSession addInput:scannerInput];
    } else {
        NSLog(@"Error: %@", error);
    }

    // Locks the configuration
    BOOL success = [scannerDevice lockForConfiguration:nil];
    if (success) {
        if ([scannerDevice isAutoFocusRangeRestrictionSupported]) {

            // Restricts the autofocus to near range (new in iOS 7)
            [scannerDevice setAutoFocusRangeRestriction:AVCaptureAutoFocusRangeRestrictionNear];
        }
    }
    // unlocks the configuration
    [scannerDevice unlockForConfiguration];

    //Define Output & Metadata Object Types
    scannerOutput = [[AVCaptureMetadataOutput alloc] init];
    [scannerOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    [scannerSession addOutput:scannerOutput];
    scannerOutput.metadataObjectTypes = [scannerOutput availableMetadataObjectTypes];

    //Create Video Preview Layer
    scannerPreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession:scannerSession];
    scannerPreviewLayer.frame = self.view.bounds;
    scannerPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    [self.view.layer addSublayer:scannerPreviewLayer];

    //Start Session
    [scannerSession startRunning];
    [self.view bringSubviewToFront:cancelButton];
    [self.view bringSubviewToFront:laserView];

还有:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {

    //Prepare Laser View
    CGRect laser = CGRectZero;

    //Format Date
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"M/d"];

    //Format Time
    NSDateFormatter *timeFormatter = [[NSDateFormatter alloc] init];
    [timeFormatter setDateFormat:@"h:ma"];

    //Define Barcode Types to Recognize
    AVMetadataMachineReadableCodeObject *barCodeObject;
    NSString *idNumber = nil;
    NSArray *barCodeTypes = @[AVMetadataObjectTypeCode39Code];

    if ([metadataObjects count] > 1) {

        NSLog(@"%lu Barcodes Found.", (unsigned long)[metadataObjects count]);

    }

    //Get String Value For Every Barcode (That Matches The Type We're Looking For)
    for (AVMetadataObject *metadata in metadataObjects) {


        for (NSString *type in barCodeTypes) {


            //If The Barcode Is The Type We Need Then Get Data
            if ([metadata.type isEqualToString:type]) {

                barCodeObject = (AVMetadataMachineReadableCodeObject *)[scannerPreviewLayer transformedMetadataObjectForMetadataObject:(AVMetadataMachineReadableCodeObject *)metadata];
                laser = barCodeObject.bounds;
                idNumber = [(AVMetadataMachineReadableCodeObject *)metadata stringValue];
                break;
            }
        }

        // If IDNumber Found
        if (idNumber != nil) {

            //Stop Session
            [scannerSession stopRunning];
            [self vibrate];

            NSLog(@"ID: %@", idNumber);

            break;
        }

        //If IDNumber Is Not Found
        else {

            NSLog(@"No ID Found.");
        }
    }

    //Update Laser
    laserView.frame = laser;
}

【问题讨论】:

  • 您是否进行了时间分析以了解哪些代码行会降低您的应用程序的速度?
  • 我实际上经历了完全相反的结果。
  • @KingPolygon 在提高条码检测性能方面祝你好运。我遇到了类似的结果,很困惑。
  • Apple 的原生 iOS 条码扫描器是垃圾:medium.com/arthurs-coding-tips/…

标签: ios objective-c avcapturesession avcapturedevice


【解决方案1】:

我在使用 AVCaptureSession 时遇到了类似的问题,捕获非常慢,有时需要很长时间才能完成。

不知道我的解决方案是否对你有好处,但绝对可以帮助其他寻找这个问题的人,就像我一样。

AVCaptureSession *captureSession = [AVCaptureSession new];
captureSession.sessionPreset = AVCaptureSessionPresetHigh;

使用此代码,您可以强制相机进行高质量预设。

希望这会对某人有所帮助。

【讨论】:

  • 为什么? AVCaptureSessionPresetPhoto 有更好的分辨率
【解决方案2】:

尝试放大一点... videoDevice.videoZoomFactor = 2.0;

【讨论】:

    【解决方案3】:

    这在很大程度上与图像质量(焦点、眩光、照明等)有关。在非常好的条件下,您应该获得几乎瞬时的扫描。

    【讨论】:

      【解决方案4】:

      我建议你在你的委托函数 captureOutput: 中添加一个 NSLog

      您会看到它被多次调用,只是为了扫描一次条形码。根据Why is allocating or initializing NSDateFormatter considered "expensive"?,初始化 NSDateFormatter 是一项非常昂贵的操作。

      我建议您在委托函数之外创建 NSDateFormatter 并重新使用它,而不是在每次调用函数时都创建它。这应该使您的应用程序更具响应性。

      【讨论】:

        猜你喜欢
        • 2018-05-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-16
        • 2016-03-22
        相关资源
        最近更新 更多