條形d碼掃描之rectOfInterest

今天因爲需要寫一個掃描條形碼的功能,想着寫一個這樣的功能會很快,結果發現在代理

AVCaptureMetadataOutputObjectsDelegate處,怎麼也得不到回調。然後各種琢磨,終於在現在搞明白是什麼一個情況。先上修改前的代碼

- (void)prepareForScan{
    NSError *error;
    
    self.captureSession = [[AVCaptureSession alloc] init];
    self.captureSession.sessionPreset = AVCaptureSessionPresetHigh;
    
    /****************Device****************/
    self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    //更改這個設置的時候必須先鎖定設備,修改完後再解鎖,否則崩潰
    if ([self.device lockForConfiguration:NULL]) {
        if ([self.device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) {
            [self.device setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
        }
        [self.device unlockForConfiguration];
    }
    /****************Device****************/
    
    
    /****************AVCaptureDeviceInput****************/
    AVCaptureDeviceInput *input = [[AVCaptureDeviceInput alloc] initWithDevice:self.device error:&error];
    if (error) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"您的攝像頭打不開,請退出重試,或者前往“設置”,找到“快遞員”,打開攝像頭權限" delegate:nil cancelButtonTitle:@"確定" otherButtonTitles:nil, nil];
        [alert show];
        NSLog(@"error=%@",error);
    }
    if ([self.captureSession canAddInput:input]) {
        [self.captureSession addInput:input];
    }
    /****************AVCaptureDeviceInput****************/
    
    
    /****************AVCaptureVideoDataOutput****************/
    AVCaptureMetadataOutput *outPut = [[AVCaptureMetadataOutput alloc] init];
    [outPut setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    outPut.rectOfInterest = self.transparentRect;
    if ([self.captureSession canAddOutput:outPut]) {
        [self.captureSession addOutput:outPut];
    }

    NSMutableArray *availableTypes = [[outPut availableMetadataObjectTypes] mutableCopy];
    if ([availableTypes containsObject:AVMetadataObjectTypeQRCode]) {
        [availableTypes removeObject:AVMetadataObjectTypeQRCode];
    }
    outPut.metadataObjectTypes = availableTypes;
    /****************AVCaptureVideoDataOutput****************/
    
    
    /****************AVCaptureVideoPreviewLayer****************/
    AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];
    previewLayer.frame = self.view.bounds;
    previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    [self.view.layer insertSublayer:previewLayer atIndex:0];
    /****************AVCaptureVideoPreviewLayer****************/
}
細看真的是沒有什麼大問題 ,但是再查看各種資料後 發現在rectOfInterest處設置是有很大問題的。


先看官方介紹

/*!
 @property rectOfInterest
 @abstract
	Specifies a rectangle of interest for limiting the search area for visual metadata.
 
 @discussion
	The value of this property is a CGRect that determines the receiver's rectangle of interest for each frame of video.  
	The rectangle's origin is top left and is relative to the coordinate space of the device providing the metadata.  Specifying 
	a rectOfInterest may improve detection performance for certain types of metadata. The default value of this property is the 
	value CGRectMake(0, 0, 1, 1).  Metadata objects whose bounds do not intersect with the rectOfInterest will not be returned.
 */
@property(nonatomic) CGRect rectOfInterest NS_AVAILABLE_IOS(7_0);
這是設置一個興趣點  CGRect類型。但是賦值的過程中,得注意得這麼賦值
CGSize size = self.view.bounds.size;
CGRect cropRect = <span style="font-family: Arial, Helvetica, sans-serif;">self.transparentRect;</span>
captureOutput.rectOfInterest = CGRectMake(cropRect.origin.x/size.width,
                                         cropRect.origin.y/size.height,
                                         cropRect.size.width/size.width,
                                         cropRect.size.height/size.height);


在該文章中點擊打開鏈接
最後優化的代碼如下

CGSize size = self.view.bounds.size;
CGRect cropRect = CGRectMake(40, 100, 240, 240);
CGFloat p1 = size.height/size.width;
CGFloat p2 = 1920./1080.;  //使用了1080p的圖像輸出
if (p1 < p2) {
  CGFloat fixHeight = bounds.size.width * 1920. / 1080.;
  CGFloat fixPadding = (fixHeight - size.height)/2;
  captureOutput.rectOfInterest = CGRectMake((cropRect.origin.y + fixPadding)/fixHeight,
                                              cropRect.origin.x/size.width,
                                              cropRect.size.height/fixHeight,
                                              cropRect.size.width/size.width);
} else {
    CGFloat fixWidth = bounds.size.height * 1080. / 1920.;
    CGFloat fixPadding = (fixWidth - size.width)/2;
    captureOutput.rectOfInterest = CGRectMake(cropRect.origin.y/size.height,
                                              (cropRect.origin.x + fixPadding)/fixWidth,
                                              cropRect.size.height/size.height,
                                              cropRect.size.width/fixWidth);
}

經測試,完成預期的掃描加識別..

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章