Почему сканирование штрих-кодов с помощью нового API iOS 7 происходит очень медленно?

В настоящее время я пытаюсь использовать новейшие API-интерфейсы iOS 7 для сканирования штрих-кодов кода 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;
}

person KingPolygon    schedule 11.02.2014    source источник
comment
Вы профилировали время, чтобы узнать, какие строки кода замедляют ваше приложение?   -  person Larme    schedule 11.02.2014
comment
Я действительно испытал прямо противоположные результаты.   -  person nhgrif    schedule 28.03.2014
comment
@KingPolygon удачи в повышении производительности обнаружения штрих-кода. Я испытываю аналогичные результаты и озадачен.   -  person Abhineet Prasad    schedule 23.05.2015
comment
Родной сканер штрих-кода Apple для iOS — это мусор: medium.com/arthurs-coding-tips/   -  person Hashem Aboonajmi    schedule 01.06.2015


Ответы (4)


У меня была аналогичная проблема с AVCaptureSession, захват был очень медленным, и иногда для его завершения требовалось много времени.

Не знаю, подходит ли мое решение для вас, но определенно может быть полезно для кого-то еще, кто ищет эту проблему, как я.

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

С помощью этого кода вы настраиваете камеру на предустановку высокого качества.

Надеюсь, это поможет кому-то.

person MajinDageta    schedule 09.09.2015
comment
Почему? AVCaptureSessionPresetPhoto имеет гораздо лучшее разрешение - person Vyachaslav Gerchicov; 23.11.2016

Попробуйте немного увеличить масштаб... videoDevice.videoZoomFactor = 2.0;

person MichaelG    schedule 07.10.2015

Во многом это связано с качеством изображения (фокус, блики, освещение и т. д.). В действительно хороших условиях сканирование должно происходить почти мгновенно.

person Senseful    schedule 07.03.2014

Я предложил вам поставить NSLog в функцию делегата captureOutput:

Вы увидите, что он вызывается много раз только для однократного сканирования штрих-кода. Инициализация NSDateFormatter — очень дорогая операция на Почему выделение или инициализация NSDateFormatter считается дорогим ?.

Я бы посоветовал вам создать NSDateFormatter вне функции делегата и повторно использовать ее вместо того, чтобы создавать ее каждый раз при вызове функции. Это должно сделать ваше приложение более отзывчивым.

person Laurent Rivard    schedule 07.10.2014