iOS 自定义相机:基础知识储备

2021-07-05 21:10:04 浏览数 (2)

  • 1.1模拟拍照动作
  • 1.2 能否切换前置后置
  • 1.3 从输出的元数据中捕捉人脸
  • 1.4 捕获每一帧图像: AVCaptureVideoDataOutputSampleBufferDelegate
  • 1.5 点击屏幕对焦:聚焦
  • 1.6 身份证和人头像的宽高比
  • 1.7 调整屏幕亮度
  • 1.8 获取iPhone设备摄像头所感知的环境光强度
  • 1.9 手电筒
  • 2.1 扫描线
    • 2.1.1 采用动画组进行实现
    • 2.1.2 定时调用setNeedsDisplay定时redrawn,来实现实现水平扫描线
  • 2.2 iOS13适配【present 半屏问题】

引言

在这里插入图片描述

I、常用基础功能

1.1模拟拍照动作

代码语言:javascript复制
            //振动,颤动,摆动
            AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);//            // 播放一下“拍照”的声音,模拟拍照            AudioServicesPlaySystemSound(1108);

1.2 能否切换前置后置

代码语言:javascript复制
// 
- (BOOL)canSwitchCameras {
    return [[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] count] > 1;
    
}

1.3 从输出的元数据中捕捉人脸

实现输出流的代理AVCaptureMetadataOutputObjectsDelegate

代码语言:javascript复制
        _metadataOutput = [[AVCaptureMetadataOutput alloc]init];
        
        [_metadataOutput setMetadataObjectsDelegate:self queue:self.queue];
                [self.videoDataOutput setSampleBufferDelegate:nil queue:self.queue];


代码语言:javascript复制
// 检测人脸是为了获得“人脸区域”,做“人脸区域”与“身份证人像框”的区域对比,当前者在后者范围内的时候,才能截取到完整的身份证图像
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
    if (metadataObjects.count) {
        AVMetadataMachineReadableCodeObject *metadataObject = metadataObjects.firstObject;
        
        AVMetadataObject *transformedMetadataObject = [self.previewLayer transformedMetadataObjectForMetadataObject:metadataObject];
        CGRect faceRegion = transformedMetadataObject.bounds;
        
        if (metadataObject.type == AVMetadataObjectTypeFace) {
            NSLog(@"是否包含头像:%d, facePathRect: %@, faceRegion: %@",CGRectContainsRect(self.faceDetectionFrame, faceRegion),NSStringFromCGRect(self.faceDetectionFrame),NSStringFromCGRect(faceRegion));
            
            if (CGRectContainsRect(self.faceDetectionFrame, faceRegion)) {// 只有当人脸区域的确在小框内时,才再去做捕获此时的这一帧图像
                // 为videoDataOutput设置代理,程序就会自动调用下面的代理方法,捕获每一帧图像
                if (!self.videoDataOutput.sampleBufferDelegate) {
                    [self.videoDataOutput setSampleBufferDelegate:self queue:self.queue];
                }
            }
        }
    }
}

1.4 捕获每一帧图像: AVCaptureVideoDataOutputSampleBufferDelegate

设置代理

代码语言:javascript复制
        _videoDataOutput = [[AVCaptureVideoDataOutput alloc] init];

                    [self.videoDataOutput setSampleBufferDelegate:self queue:self.queue];

从输出的数据流捕捉单一的图像帧

代码语言:javascript复制

#pragma mark - AVCaptureVideoDataOutputSampleBufferDelegate
#pragma mark 从输出的数据流捕捉单一的图像帧
// AVCaptureVideoDataOutput获取实时图像,这个代理方法的回调频率很快,几乎与手机屏幕的刷新频率一样快
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
    if ([self.outPutSetting isEqualToNumber:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange]] || [self.outPutSetting isEqualToNumber:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange]]) {
        CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
        
        if ([captureOutput isEqual:self.videoDataOutput]) {
            // 身份证信息识别  (void)iDCardRecognit:(CVImageBufferRef)imageBuffer WithstopRunningBlcok:(void(^)(id make)) stopRunningBlcok finishBlock:(k_finishBlock)finishBlock;
            __weak __typeof__(self) weakSelf = self;

            [KNScanCardManage iDCardRecognit:imageBuffer  WithstopRunningBlcok:^(id  _Nonnull sender) {
                
                            if ([weakSelf.session isRunning]) {
                                [weakSelf.session stopRunning];
                            }

            } finishBlock:weakSelf.finishBlock];//imageBuffer
            
            
            
            
            
            
            // 身份证信息识别完毕后,就将videoDataOutput的代理去掉,防止频繁调用AVCaptureVideoDataOutputSampleBufferDelegate方法而引起的“混乱”
            if (self.videoDataOutput.sampleBufferDelegate) {
                [self.videoDataOutput setSampleBufferDelegate:nil queue:self.queue];
            }
        }
    } else {
        NSLog(@"输出格式不支持");
    }
}

1.5 点击屏幕对焦:聚焦

监听点击事件

代码语言:javascript复制
    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(focusGesture:)];
    [self.view addGestureRecognizer:tapGesture];

点击屏幕对焦

0 人点赞