iOS:AVCaptureSession 通过摄像头获取某一帧的画面

1.配置plist

2.上代码

//
//  ViewController.m
//  newface
//
//  Created by xc on 2018/8/27.
//  Copyright © 2018年 xc. All rights reserved.
//

#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
@interface ViewController ()<AVCaptureVideoDataOutputSampleBufferDelegate>
@property (nonatomic) AVCaptureDeviceDiscoverySession *videoDeviceDiscoverySession;
@property (nonatomic,strong) UIImageView *imgview;
@end

int g_width = 0;
int g_height = 0;
int g_pitch = 0;
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self setupAVCapture];
}


- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
       fromConnection:(AVCaptureConnection *)connection
{
    //通过抽样缓存数据创建一个UIImage对象
    unsigned char* pBGRA = NULL;
    UIImage* image = [self imageFromSampleBuffer:sampleBuffer:&pBGRA];//最开始一帧图像很暗,后面就正常了
    dispatch_async(dispatch_get_main_queue(), ^{
        // 回到主线程 image为捕捉到的画面,直接使用就OK了
        self.imgview.image = image;
        
    });
}

/**
 *  相机初始化方法
 */
- (void)setupAVCapture
{
    
    _imgview = [[UIImageView alloc]init];
    _imgview.frame =CGRectMake(0, 400, 100, 100);
    [self.view addSubview:_imgview];
    
    NSError *error = nil;
    
    // 1 创建session
    AVCaptureSession *session = [AVCaptureSession new];
    // 2 设置session显示分辨率
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
        [session setSessionPreset:AVCaptureSessionPreset640x480];
    else
        [session setSessionPreset:AVCaptureSessionPresetPhoto];
    
 
    // 3 获取摄像头device,并且默认使用的后置摄像头,并且将摄像头加入到captureSession中
    AVCaptureDevice* device = [AVCaptureDevice defaultDeviceWithDeviceType:AVCaptureDeviceTypeBuiltInWideAngleCamera mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionFront];
    AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
    //    isUsingFrontFacingCamera = NO;
    if ([session canAddInput:deviceInput]){
        [session addInput:deviceInput];
    }
    // 4 创建预览output,设置预览videosetting,然后设置预览delegate使用的回调线程,将该预览output加入到session
    AVCaptureVideoDataOutput* videoOutput = [[AVCaptureVideoDataOutput alloc] init];
    videoOutput.alwaysDiscardsLateVideoFrames = YES;
    videoOutput.videoSettings = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey];//设置像素格式
    if ([session canAddOutput:videoOutput])
        [session addOutput:videoOutput];
    //    5 显示捕捉画面
    dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL);
    [videoOutput setSampleBufferDelegate:self queue:queue];
    AVCaptureVideoPreviewLayer* preLayer = [AVCaptureVideoPreviewLayer layerWithSession: session];//相机拍摄预览图层
    preLayer.frame = CGRectMake(0, 0, 400,400);
    preLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    [self.view.layer addSublayer:preLayer];
    
    // 6 启动session,output开始接受samplebuffer回调
    [session startRunning];
    if (error) {
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:@"Failed with error %d", (int)[error code]]
                                                            message:[error localizedDescription]
                                                           delegate:nil
                                                  cancelButtonTitle:@"Dismiss"
                                                  otherButtonTitles:nil];
        [alertView show];
        
    }
}

// 通过抽样缓存数据创建一个UIImage对象
- (UIImage *) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer:(unsigned char**) pBGRA
{
    // 为媒体数据设置一个CMSampleBuffer的Core Video图像缓存对象
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    // 锁定pixel buffer的基地址
    CVPixelBufferLockBaseAddress(imageBuffer, 0);
    
    // 得到pixel buffer的基地址
    void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
    
    // 得到pixel buffer的行字节数
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
    // 得到pixel buffer的宽和高
    size_t width = CVPixelBufferGetWidth(imageBuffer);
    size_t height = CVPixelBufferGetHeight(imageBuffer);
    g_width = width;
    g_height = height;
    g_pitch = bytesPerRow;
    //return (unsigned char*)baseAddress;
    *pBGRA = (unsigned char*)malloc(g_pitch*g_height);
    memcpy(*pBGRA, baseAddress, g_pitch*g_height);
    // 创建一个依赖于设备的RGB颜色空间
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    
    // 用抽样缓存的数据创建一个位图格式的图形上下文(graphics context)对象
    CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8,
                                                 bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
    //   unsigned char* pBGRA = CGBitmapContextGetData(context);
    //   return pBGRA;
    
    
    
    // 根据这个位图context中的像素数据创建一个Quartz image对象
    CGImageRef quartzImage = CGBitmapContextCreateImage(context);
    // 解锁pixel buffer
    CVPixelBufferUnlockBaseAddress(imageBuffer,0);
    
    // 释放context和颜色空间
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    
    // 用Quartz image创建一个UIImage对象image
    UIImage *image = [UIImage imageWithCGImage:quartzImage];
    
    // 释放Quartz image对象
    CGImageRelease(quartzImage);
    
    return (image);
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end

over,有用到请点赞谢谢

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏PPV课数据科学社区

【学习】七天搞定SAS(四):数据输出

弄清楚了基本的PROC之后,开始研究SAS的输出...毕竟有了数据处理的结果之后,还要有一个比较舒服的输出格式才可以嘛。 SAS的结果发送系统:ODS SAS里...

3768
来自专栏Alice

绘图quartz之加水印

实现在图片上加一个水印  并存在document的路径下  同时在手机相册中也存一份 //首先开启imageContext找到图片     UIGraphics...

2116
来自专栏帘卷西风的专栏

MFC若干小问题解决方案(1)

1、新建一个子类CMFCPropertyGridCtrlEX继承CMFCPropertyGridCtrl

922
来自专栏iOS开发攻城狮的集散地

iOS后台音频播放及锁屏歌词

2386
来自专栏菩提树下的杨过

ExtJs学习笔记(7)_获取GridPanel选中行的详细信息

这一节,我们将学习如何获取Grid当前选中行的信息 1.xml数据源内容: <?xml version="1.0" encoding="UTF-8"?> <D...

22110
来自专栏数据小魔方

leaflet在线地图进阶宝典之——高级辅助特性

本文跟大家分享leaflet在线地图的高级附加属性,这些属性通常来讲仅仅作为我们数据额可视化项目的修饰元素,而并不会影响数据元素。 但是有了这些辅助修饰元素,往...

3424
来自专栏iOS122-移动混合开发研究院

Pop–实现任意iOS对象的任意属性的动态变化

简介 Pop 是一个可扩展的动画引擎,可用于实现任意iOS对象的任意属性的动态变化,支持一般动画,弹性动画和渐变动画三种类型. 最新示例: 点击下载 注...

1997
来自专栏青玉伏案

iOS开发之微信聊天工具栏的封装

之前山寨了一个新浪微博(iOS开发之山寨版新浪微博小结),这几天就山寨个微信吧。之前已经把微信的视图结构简单的拖了一下(iOS开发之微信山寨版),今天就开始给微...

2688
来自专栏一“技”之长

iOS开发封装一个可以响应超链接的label——基于RCLabel的交互扩展

        iOS系统是一个十分注重用户体验的系统,在iOS系统中,用户交互的方案也十分多,然而要在label中的某部分字体中添加交互行为确实不容易的,如果...

911
来自专栏BY的专栏

iOS将单个控制器设为横屏、页面横屏

3425

扫码关注云+社区

领取腾讯云代金券