目標(biāo):識別二維碼,并且在視頻流中,在已識別的二維碼周邊加上邊框。
#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
@interface ViewController ()<AVCaptureMetadataOutputObjectsDelegate>
@property (nonatomic, strong) AVCaptureSession *session;
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *preview;
@property (nonatomic, strong) CALayer *drawLayer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
// session
_session = [[AVCaptureSession alloc] init];
// input
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCaptureDeviceInput *input = [[AVCaptureDeviceInput alloc] initWithDevice:device error:nil];
// output
AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
// addInput, addOutput
if ([_session canAddInput:input]) {
[_session addInput:input];
}
if ([_session canAddOutput:output]) {
[_session addOutput:output];
}
output.metadataObjectTypes = output.availableMetadataObjectTypes;
[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
_preview = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_session];
_preview.frame = self.view.bounds;
_drawLayer = [CALayer layer];
_drawLayer.frame = self.view.bounds;
}
- (IBAction)testButton1:(id)sender {
if (_session.isRunning) {
[_preview removeFromSuperlayer];
[_drawLayer removeFromSuperlayer];
[_session stopRunning];
} else {
[self.view.layer insertSublayer:_drawLayer atIndex:0];
[self.view.layer insertSublayer:_preview atIndex:0];
[_session startRunning];
}
}
- (void)captureOutput:(AVCaptureOutput *)output didOutputMetadataObjects:(NSArray<__kindof AVMetadataObject *> *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
NSArray *layers = _drawLayer.sublayers.copy;
for (CALayer *layer in layers) {
[layer removeFromSuperlayer];
}
for (AVMetadataObject *obj in metadataObjects) {
if ([obj isKindOfClass:AVMetadataMachineReadableCodeObject.class]) {
//將0-1間小數(shù)表示的坐標(biāo)系轉(zhuǎn)換為常用的坐標(biāo)系
AVMetadataMachineReadableCodeObject *temp = (AVMetadataMachineReadableCodeObject*)[_preview transformedMetadataObjectForMetadataObject:obj];
[self addBorderOnOjbect:(AVMetadataMachineReadableCodeObject *)temp];
}
}
}
//添加一個(gè)中間是透明的,周邊是有顏色的layer
- (void)addBorderOnOjbect:(AVMetadataMachineReadableCodeObject *)obj {
CAShapeLayer *layer = [CAShapeLayer layer];
layer.lineWidth = 4;
layer.strokeColor = UIColor.greenColor.CGColor;
layer.fillColor = UIColor.clearColor.CGColor;
layer.path = [self boderPathWithObject:obj].CGPath;
[_drawLayer addSublayer:layer];
}
//獲取邊框的path
- (UIBezierPath *)boderPathWithObject:(AVMetadataMachineReadableCodeObject *)obj {
UIBezierPath *path = [UIBezierPath bezierPath];
NSArray *corners = obj.corners;
CGPoint point = CGPointZero; int index = 0;
//將corner里0-1小數(shù)表示的坐標(biāo)點(diǎn)轉(zhuǎn)換為常用的坐標(biāo)點(diǎn)。
CGPointMakeWithDictionaryRepresentation((CFDictionaryRef)corners[index++], &point);
[path moveToPoint:point];
while (index < corners.count) {
CGPointMakeWithDictionaryRepresentation((CFDictionaryRef)corners[index++], &point);
[path addLineToPoint:point];
}
[path closePath];
return path;
}
@end
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。