2014-10-29 49 views
2

我正在嘗試爲我目前正在使用的應用設計條形碼掃描器。我希望掃描儀預覽可以填充設備的整個屏幕,並提供一個更小的框架以指向條形碼。所有的工作是如何我想要的,但我無法得到感興趣的框架工作。Xcode AVCapturesession掃描特定幀中的條形碼(rectOfInterest不起作用)

下面是條形碼掃描器的執行情況:

#import "GEScannerViewController.h" 
@import AVFoundation; 

@interface GEScannerViewController() <AVCaptureMetadataOutputObjectsDelegate> { 
    AVCaptureSession *_session; 
    AVCaptureDevice *_device; 
    AVCaptureDeviceInput *_input; 
    AVCaptureMetadataOutput *_output; 
    AVCaptureVideoPreviewLayer *_prevLayer; 

    UIView *_greyView; 
    UIView *_highlightView; 
    UIView *_scopeView; 
    UILabel *_label; 
} 
@end 

@implementation GEScannerViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    _label = [[UILabel alloc] init]; 
    _label.frame = CGRectMake(0, self.view.bounds.size.height - 40, self.view.bounds.size.width, 40); 
    _label.autoresizingMask = UIViewAutoresizingFlexibleTopMargin; 
    _label.backgroundColor = [UIColor colorWithWhite:0.15 alpha:0.65]; 
    _label.textColor = [UIColor whiteColor]; 
    _label.textAlignment = NSTextAlignmentCenter; 
    _label.text = @"(none)"; 
    [self.view addSubview:_label]; 

    NSError *error = nil; 

    _session = [[AVCaptureSession alloc] init]; 
    _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 

    [_device lockForConfiguration:&error]; 

    if (error) { 
     NSLog(@"Error: %@", error); 
    } 

    _device.focusPointOfInterest = CGPointMake(self.view.frame.size.width/2, (self.view.frame.size.height/2) - 80); 

    _input = [AVCaptureDeviceInput deviceInputWithDevice:_device error:&error]; 
    if (_input) { 
     [_session addInput:_input]; 
    } else { 
     NSLog(@"Error: %@", error); 
    } 

    _output = [[AVCaptureMetadataOutput alloc] init]; 
    [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()]; 
    _output.rectOfInterest = CGRectMake((self.view.frame.size.width/2) - 160, (self.view.frame.size.height/2) - 160, 320, 160); 
    [_session addOutput:_output]; 

    _output.metadataObjectTypes = [_output availableMetadataObjectTypes]; 

    _prevLayer = [AVCaptureVideoPreviewLayer layerWithSession:_session]; 
    _prevLayer.frame = self.view.bounds; 
    _prevLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; 
    [self.view.layer addSublayer:_prevLayer]; 

    _greyView = [[UIView alloc] initWithFrame:self.view.frame]; 
    _greyView.bounds = self.view.bounds; 
    _greyView.backgroundColor = [UIColor colorWithWhite:0.15 alpha:0.65]; 
    [self.view.layer addSublayer:_greyView.layer]; 

    _scopeView = [[UIView alloc] initWithFrame:CGRectMake((self.view.frame.size.width/2) - 160, (self.view.frame.size.height/2) - 160, 320, 160)]; 
    _scopeView.backgroundColor = [UIColor clearColor]; 
    _scopeView.layer.borderColor = [UIColor greenColor].CGColor; 
    _scopeView.layer.borderWidth = 1; 
    _scopeView.clipsToBounds = YES; 
    [self.view addSubview:_scopeView]; 

    _highlightView = [[UIView alloc] init]; 
    _highlightView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleBottomMargin; 
    _highlightView.layer.borderColor = [UIColor greenColor].CGColor; 
    _highlightView.layer.borderWidth = 3; 
    [_scopeView addSubview:_highlightView]; 

    [_session startRunning]; 

    [self.view bringSubviewToFront:_highlightView]; 
    [self.view bringSubviewToFront:_label]; 
} 

我使用_output.rectOfInterest指定框架是一樣的_scopeView的框架。不幸的是,這是行不通的。如果我這樣做,條碼不再被識別。

回答

7

只要我得到它,這是絕對清楚:

的AVCaptureMetadataOutput由像素定義的,因此在輸出顯示器的座標映射到這一點,我不得不使用metadataOutputRectOfInterestForRect:

From AVCaptureOutput.h: 


/*! 
@method metadataOutputRectOfInterestForRect: 
@abstract 
Converts a rectangle in the receiver's coordinate space to a rectangle of interest in the coordinate space of an AVCaptureMetadataOutput 
whose capture device is providing input to the receiver. 

@param rectInOutputCoordinates 
A CGRect in the receiver's coordinates. 

@result 
A CGRect in the coordinate space of the metadata output whose capture device is providing input to the receiver. 

@discussion 
AVCaptureMetadataOutput rectOfInterest is expressed as a CGRect where {0,0} represents the top left of the picture area, 
and {1,1} represents the bottom right on an unrotated picture. This convenience method converts a rectangle in 
the coordinate space of the receiver to a rectangle of interest in the coordinate space of an AVCaptureMetadataOutput 
whose AVCaptureDevice is providing input to the receiver. The conversion takes orientation, mirroring, and scaling into 
consideration. See -transformedMetadataObjectForMetadataObject:connection: for a full discussion of how orientation and mirroring 
are applied to sample buffers passing through the output. 
*/ 

- (CGRect)metadataOutputRectOfInterestForRect:(CGRect)rectInOutputCoordinates NS_AVAILABLE_IOS(7_0); 

使用此設置rectOfInterest後,它的工作。

+0

「接收器」代表什麼? – JonSlowCN 2015-07-29 07:49:33

+0

那麼你如何實現只掃描屏幕中心? – 2016-11-24 17:47:47