iOS开发

您所在的位置:网站首页 一加图片识别功能 iOS开发

iOS开发

2024-07-13 10:32| 来源: 网络整理| 查看: 265

iOS开发-实现二维码扫一扫Scan及识别图片中二维码功能

在iOS开发中,会遇到扫一扫功能,扫一扫是使用摄像头扫码二维码或者条形码,获取对应二维码或条形码内容字符串。通过获得的字符串进行跳转或者打开某个页面开启下一步的业务逻辑。

https://blog.csdn.net/gloryFlow/article/details/132249830 https://img-blog.csdnimg.cn/b6b9b7416e7b45e9ab06c02083ac091f.jpeg#pic_center

一、使用前权限设置

扫一扫功能需要开启相机权限,需要在info.plist文件中添加NSCameraUsageDescription

例如:

NSCameraUsageDescription 开启相机权限,活动扫一扫更快捷 NSLocationAlwaysAndWhenInUseUsageDescription 开启定位权限 NSLocationAlwaysUsageDescription 开启定位权限 NSLocationWhenInUseUsageDescription 开启定位权限 NSMicrophoneUsageDescription 开启麦克风权限 NSPhotoLibraryAddUsageDescription 添加照片需要您的同意 NSPhotoLibraryUsageDescription 开启照片权限

这里还有其他权限,暂时扫一扫只需要NSCameraUsageDescription。

二、AVCaptureSession扫一扫功能 2.1 需要了解的几个类 AVCaptureSession

AVCaptureSession是iOS提供的一个管理和协调输入设备到输出设备之间数据流的对象。

AVCaptureDevice

AVCaptureDevice是指硬件设备。

AVCaptureDeviceInput

AVCaptureDeviceInput是用来从AVCaptureDevice对象捕获Input数据。

AVCaptureMetadataOutput

AVCaptureMetadataOutput是用来处理AVCaptureSession产生的定时元数据的捕获输出的。

AVCaptureVideoDataOutput

AVCaptureVideoDataOutput是用来处理视频数据输出的。

AVCaptureVideoPreviewLayer

AVCaptureVideoPreviewLayer是相机捕获的视频预览层,是用来展示视频的。

2.2 实现扫一扫功能

在熟悉几个类之后,我们可以初始化session了。 我们为AVCaptureSession添加功能实现所需要的input与output

/** 创建扫描器 */ - (void)loadScanView { AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil]; AVCaptureMetadataOutput *metadataOutput = [[AVCaptureMetadataOutput alloc] init]; [metadataOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()]; if (self.scanConfig.scannerArea == SDScannerAreaDefault) { metadataOutput.rectOfInterest = CGRectMake([self.scannerView scannerOriginX]/self.view.frame.size.height, [self.scannerView scannerOriginY]/self.view.frame.size.width, [self.scannerView scannerWidth]/self.view.frame.size.height, [self.scannerView scannerWidth]/self.view.frame.size.width); } AVCaptureVideoDataOutput *videoDataOutput = [[AVCaptureVideoDataOutput alloc] init]; [videoDataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()]; self.session = [[AVCaptureSession alloc]init]; [self.session setSessionPreset:AVCaptureSessionPresetHigh]; if ([self.session canAddInput:deviceInput]) { [self.session addInput:deviceInput]; } if ([self.session canAddOutput:metadataOutput]) { [self.session addOutput:metadataOutput]; } if ([self.session canAddOutput:videoDataOutput]) { [self.session addOutput:videoDataOutput]; } metadataOutputadataObjectTypes = [SDQrScanTool metadataObjectType:self.scanConfig.scannerType]; AVCaptureVideoPreviewLayer *videoPreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession:_session]; videoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; videoPreviewLayer.frame = self.view.layer.bounds; [self.videoPreView.layer insertSublayer:videoPreviewLayer atIndex:0]; [self.session startRunning]; }

AVCaptureMetadataOutput实现了方法,设置了delegate

[metadataOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];

实现AVCaptureMetadataOutputObjectsDelegate的代理方法

- (void)captureOutput:(AVCaptureOutput *)output didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection;

该方法每当输出捕获并发出新对象时,委托都会收到此消息,获得对应metadataObjectTypes。通过此方法,我们可以当扫描二维码时候获得对应的结果。

#pragma mark -- AVCaptureMetadataOutputObjectsDelegate - (void)captureOutput:(AVCaptureOutput *)output didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection { // 获取扫一扫结果 if (metadataObjects && metadataObjects.count > 0) { [self pauseScanning]; AVMetadataMachineReadableCodeObject *metadataObject = metadataObjects[0]; NSString *stringValue = metadataObject.stringValue; //AVMetadataMachineReadableCodeObject *obj = (AVMetadataMachineReadableCodeObject *)[self.lay transformedMetadataObjectForMetadataObject:metadataObjects.lastObject]; //[self changeVideoScale:metadataObject]; [self handleScanValue:stringValue]; } }

在AVCaptureVideoDataOutput实现了

[videoDataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];

这里实现了代理AVCaptureVideoDataOutputSampleBufferDelegate中方法

- (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection;

当捕获新的视频采样缓冲区时,将使用captureOutput:didOutputSampleBuffer:fromConnection:delegate方法将其提供给采样缓冲区代理。

在此方法中,可以观察亮度值,决定是否需要开启灯光。

#pragma mark -- AVCaptureVideoDataOutputSampleBufferDelegate /** 此方法会实时监听亮度值 */ - (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { CFDictionaryRef metadataDict = CMCopyDictionaryOfAttachments(NULL,sampleBuffer, kCMAttachmentMode_ShouldPropagate); NSDictionary *metadata = [[NSMutableDictionary alloc] initWithDictionary:(__bridge NSDictionary*)metadataDict]; CFRelease(metadataDict); NSDictionary *exifMetadata = [[metadata objectForKey:(NSString *)kCGImagePropertyExifDictionary] mutableCopy]; // 亮度值 float brightnessValue = [[exifMetadata objectForKey:(NSString *)kCGImagePropertyExifBrightnessValue] floatValue]; if (![self.scannerView flashlightOn]) { if (brightnessValue


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3