iOS AVFoundation 自动捕获拍照

需求分析

自定义一个相机,要支持手动拍照,以及自动捕获作业拍照。

实现方法

创建相机

    self.session = [[AVCaptureSession alloc] init];
    AVCaptureDeviceInput* input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
    self.session.sessionPreset = AVCaptureSessionPresetPhoto;
    [self.session addInput:input];
    
    AVCaptureVideoDataOutput *dataOutput = [[AVCaptureVideoDataOutput alloc] init];
    [dataOutput setAlwaysDiscardsLateVideoFrames:YES];
    [dataOutput setVideoSettings:@{(id)kCVPixelBufferPixelFormatTypeKey:@(kCVPixelFormatType_32BGRA)}];
    [dataOutput setSampleBufferDelegate:self queue:_captureQueue];
    [self.session addOutput:dataOutput];
    
    self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
    CGFloat kWidth = kFullScreenWidth;
    CGFloat kHeight = kMiddleViewHeight;
    NSDictionary * outputSettings = @{AVVideoWidthKey : @(kWidth),
    AVVideoHeightKey: @(kHeight),
    AVVideoCodecKey : AVVideoCodecJPEG,AVVideoScalingModeKey:AVVideoScalingModeResizeAspectFill};
    [self.stillImageOutput setOutputSettings:outputSettings];
    
    AVCaptureConnection *connection = [dataOutput.connections firstObject];
    [connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
    if ([self.session canAddInput:self.videoInput]) {
        [self.session addInput:self.videoInput];
    }
    
    if ([self.session canAddOutput:self.stillImageOutput]) {
        [self.session addOutput:self.stillImageOutput];
    }
    self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];
    self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    self.previewLayer.frame = CGRectMake(0,kTopViewHeight,kFullScreenWidth,kMiddleViewHeight);
    self.previewLayer.contentsScale = [UIScreen mainScreen].scale;
    self.previewLayer.backgroundColor = [[UIColor blackColor]CGColor];
    self.cameraContentView.layer.masksToBounds = YES;
    [self.cameraContentView.layer addSublayer:self.previewLayer];

手动拍照

    [self.stillImageOutput captureStillImageAsynchronouslyFromConnection:conntion completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
        if (imageDataSampleBuffer == nil) {
            return ;
        }
        NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
        UIImage *oringImage = [UIImage imageWithData:imageData];
        // 裁剪成4:3的比例
        self->_photopImage = [self clipImageWithRectangle:oringImage];
        [self doPhoto];
        self->_takePhotoButton.enabled = YES;
    }];

自动拍照

#pragma mark - AVCaptureVideoDataOutputSampleBufferDelegate

-(void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{
    if (self.forceStop) return;
    if (_isStopped || _isCapturing || !CMSampleBufferIsValid(sampleBuffer)) return;
    
    CVPixelBufferRef pixelBuffer = (CVPixelBufferRef)CMSampleBufferGetImageBuffer(sampleBuffer);
    CIImage *image = [CIImage imageWithCVPixelBuffer:pixelBuffer];

    image = [self filteredImageUsingContrastFilterOnImage:image];
    if (self.isBorderDetectionEnabled) // 可以自动捕获拍照
    {
        if (_borderDetectFrame)
        {
            // CIRectangleFeature
            _borderDetectLastRectangleFeature = [self biggestRectangleInRectangles:[[self highAccuracyRectangleDetector] featuresInImage:image]];
            _borderDetectFrame = NO;
        }
        
        if (_borderDetectLastRectangleFeature)
        {
            _imageDedectionConfidence += 0.5;
            image = [self drawHighlightOverlayForPoints:image topLeft:_borderDetectLastRectangleFeature.topLeft topRight:_borderDetectLastRectangleFeature.topRight bottomLeft:_borderDetectLastRectangleFeature.bottomLeft bottomRight:_borderDetectLastRectangleFeature.bottomRight];
            //SSLog(@"%f----",_imageDedectionConfidence);
            
            if (self.isBorderDetectionEnabled && rectangleDetectionConfidenceHighEnough(_imageDedectionConfidence) ) {
                //SSLog(@"当前线程---%@",[NSThread currentThread]);
                dispatch_async(dispatch_get_main_queue(), ^{
                    self->_takePhotoButton.enabled = NO;
                    [self captureImageWithCompletionHander];
                });
            }else{
                dispatch_async(dispatch_get_main_queue(), ^{
                    self->_takePhotoButton.enabled = YES;
                });
            }
        }else{
            _imageDedectionConfidence = 0.0f;
        }
    }
    
    if (self.context && _coreImageContext){
        if(_context != [EAGLContext currentContext]){
            [EAGLContext setCurrentContext:_context];
        }
        [_glkView bindDrawable];
        [_coreImageContext drawImage:image inRect:self.cachedBounds fromRect:[self cropRectForPreviewImage:image]];
        [_glkView display];
        if(_intrinsicContentSize.width != image.extent.size.width) {
            self.intrinsicContentSize = image.extent.size;
            dispatch_async(dispatch_get_main_queue(), ^{
                [self.cameraContentView invalidateIntrinsicContentSize];
            });
        }
        image = nil;
    }
}

AutomaticCaptureCamera Demo

参考文章

AVFoundation篇 - 苏沫离

AVFoundation - Seacen_Liu

人脸框检测 - 会飞的大马猴

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 什么是 AVFoundationAVFoundation是苹果公司提供的一个多媒体处理框架,它能够处理音频、视频、文本和图像等媒体类型,还能够实现录制、编辑、播放等多种操作。 2. AVFoundation的优点是什么? AVFoundation有以下几个优点: - 它可以在多个平台上使用,包括iOS、macOS和tvOS等。 - 它提供了灵活的API,可以对多种媒体类型进行处理。 - 它支持硬件加速,能够提高处理速度和性能。 - 它支持多种格式的媒体文件,包括MP3、AAC、H.264和MPEG-4等。 3. 如何使用AVFoundation实现音频录制? 在使用AVFoundation实现音频录制时,需要执行以下步骤: - 创建一个AVAudioSession对象,用于管理音频会话。 - 创建一个AVAudioRecorder对象,用于录制音频。 - 配置录音参数,例如音频格式、采样率、通道数、音频质量等。 - 调用AVAudioRecorder的record方法开始录音。 - 调用AVAudioRecorder的stop方法停止录音。 4. AVFoundation中的AVPlayerLayer是什么? AVPlayerLayer是一个CALayer子类,用于在iOS和macOS应用程序中显示视频内容。它可以显示一个AVPlayer对象的输出,并且支持全屏播放、画中画、视频内容缩放等功能。 5. 如何使用AVFoundation实现视频播放? 在使用AVFoundation实现视频播放时,需要执行以下步骤: - 创建一个AVPlayer对象,用于播放视频。 - 创建一个AVPlayerLayer对象,用于显示视频内容。 - 将AVPlayerLayer对象添加到视图层次结构中。 - 创建一个AVPlayerItem对象,用于管理视频资源。 - 调用AVPlayer的replaceCurrentItemWithPlayerItem方法将AVPlayerItem与AVPlayer关联。 - 调用AVPlayer的play方法开始播放视频。 6. 如何在AVFoundation中实现视频编辑? 在AVFoundation中实现视频编辑通常需要使用AVAsset、AVAssetTrack、AVComposition、AVMutableComposition等类。以下是实现视频编辑的大致步骤: - 创建一个AVAsset对象,用于表示视频资源。 - 创建一个AVMutableComposition对象,用于管理视频资源。 - 使用AVAssetTrack获取视频的音频和视频轨道。 - 使用AVMutableCompositionTrack将音频和视频轨道添加到AVMutableComposition中。 - 使用AVAssetExportSession导出编辑后的视频。 7. AVFoundation中的AVCaptureSession是什么? AVCaptureSession是用于管理视频和音频输入的会话对象。它可以管理多个输入设备(例如摄像头、麦克风等)并且可以将它们合并到单个输出中。使用AVCaptureSession可以方便地实现视频录制、视频流传输、实时视频分析等功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值