上一节,我们已经实现了二维码的扫描,这一节,我们利用元数据的bounds和corners实现一个可视化的扫描效果。
bounds定义了包含二维码图像的矩形,corners定义了二维码图像的实际坐标:
当摄像头和二维码图片完全对齐时,bounds和corners就是相同的。但是通常来说,几乎不可能让摄像头和二维码完全对齐。
打开ViewController.m,添加以下实例变量,用于存放所有检测到得二维码,以二维码的内容为索引。
NSMutableDictionary *_barcodes;在viewDidLoad方法中初始化这个字典:
_barcodes = [NSMutableDictionary new];定义一个Barcode类,用于存放已识别的二维码的元数据。
@interface Barcode : NSObject @property (nonatomic, strong) AVMetadataMachineReadableCodeObject *metadataObject; @property (nonatomic, strong) UIBezierPath *cornersPath; @property (nonatomic, strong) UIBezierPath *boundingBoxPath; @end @implementation Barcode @end添加processMetadataObject :
- (Barcode *)processMetadataObject:(AVMetadataMachineReadableCodeObject *)code
{
// 1
Barcode *barcode = _barcodes[code.stringValue];
// 2
if (!barcode)
{
barcode = [Barcode new];
_barcodes[code.stringValue] = barcode;
}
// 3
barcode.metadataObject = code;
// Create the path joining code's corners
// 4
CGMutablePathRef cornersPath = CGPathCreateMutable();
// 5
CGPoint point;
CGPointMakeWithDictionaryRepresentation((CFDictionaryRef)code.corners[0], &point);
// 6
CGPathMoveToPoint(cornersPath, nil, point.x, point.y);
// 7
for (int i = 1; i < code.corners.count; i++) {
CGPointMakeWithDictionaryRepresentation((CFDictionaryRef)code.corners[i], &point);
CGPathAddLineToPoint(cornersPath, nil, point.x, point.y);
}
// 8
CGPathCloseSubpath(cornersPath);
// 9
barcode.cornersPath =[UIBezierPath bezierPathWithCGPath:cornersPath];
CGPathRelease(cornersPath);
// Create the path for the code's bounding box
// 10
barcode.boundingBoxPath = [UIBezierPath bezierPathWithRect:code.bounds];
// 11
return barcode;
}
修改captureOutput:didOutputMetadataObjects:fromConnection方法:
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
// 1
NSMutableSet *foundBarcodes = [NSMutableSet new];
[metadataObjects enumerateObjectsUsingBlock: ^(AVMetadataObject *obj, NSUInteger idx, BOOL *stop) {
NSLog(@"Metadata: %@", obj);
// 2
if ([obj isKindOfClass:[AVMetadataMachineReadableCodeObject class]])
{
// 3
AVMetadataMachineReadableCodeObject *code = (AVMetadataMachineReadableCodeObject*)
[_previewLayer transformedMetadataObjectForMetadataObject:obj];
// 4
Barcode *barcode = [self processMetadataObject:code];
[foundBarcodes addObject:barcode];
}
}];
dispatch_sync(dispatch_get_main_queue(), ^{
// Remove all old layers
// 5
NSArray *allSublayers = [_previewView.layer.sublayers copy];
[allSublayers enumerateObjectsUsingBlock: ^(CALayer *layer, NSUInteger idx, BOOL *stop) { if (layer != _previewLayer) {
[layer removeFromSuperlayer];
}
}];
// Add new layers
// 6
[foundBarcodes enumerateObjectsUsingBlock: ^(Barcode *barcode, BOOL *stop) {
CAShapeLayer *boundingBoxLayer = [CAShapeLayer new]; boundingBoxLayer.path = barcode.boundingBoxPath.CGPath; boundingBoxLayer.lineWidth = 2.0f; boundingBoxLayer.strokeColor =
[UIColor greenColor].CGColor; boundingBoxLayer.fillColor =
[UIColor colorWithRed:0.0f green:1.0f blue:0.0f
alpha:0.5f].CGColor; [_previewView.layer addSublayer:boundingBoxLayer];
CAShapeLayer *cornersPathLayer = [CAShapeLayer new]; cornersPathLayer.path = barcode.cornersPath.CGPath; cornersPathLayer.lineWidth = 2.0f; cornersPathLayer.strokeColor =
[UIColor blueColor].CGColor; cornersPathLayer.fillColor =
[UIColor colorWithRed:0.0f green:0.0f blue:1.0f
alpha:0.5f].CGColor; [_previewView.layer addSublayer:cornersPathLayer];
}];
});
}
编译运行,效果如下:
下一节,我们将为程序添加语音合成功能,自动朗读二维码的内容。
转载请注明出处:http://blog.csdn.net/yamingwu/article/details/44518051
iOS AV Foundation 二维码扫描 03 为扫描到的二维码添加可视化效果
原文:http://blog.csdn.net/yamingwu/article/details/44518051