首页 电脑 电脑学堂 查看内容

静态图片和视频捕捉

2016-9-20 11:35 1085 0

摘要: 通过输入(inputs)和输出(outputs)对象来对采集设备(比如摄像头或麦克风)进行管理. 使用AVCaptureSession对象协调inputs和outputs之间的数据.AVCaptureDevice代表输入设备, 比如摄像头和麦克风AVCaptureInput的子类用 ...

通过输入(inputs)和输出(outputs)对象来对采集设备(比如摄像头或麦克风)进行管理. 使用 AVCaptureSession 对象协调inputs和outputs之间的数据.

使用CALayer的子类 AVCaptureVideoPreviewLayer , 可以展示摄像头采集的画面预览.

对于一个session, 可以配置多个inputs和outputs, 如图所示:

对于大部分的应用而言, 这已经足够了. 但是有些情况下, 会涉及到如何表示一个inputs的多个端口(ports), 以及这些ports如何连接到outputs.

Capture session中使用 AVCaptureConnection 表示inputs和outputs之间的连接. 一个Inputs包含一个或多个input ports( AVCaptureInputPort ). Outputs可以从一个或多个来源接收数据, 比如 AVCaptureMovieFileOutput 可以同时接收视频和音频数据.

如下图所示, 当在session中添加一个input或output时, session会为所有可匹配的inputs和outputs之前生成connections( AVCaptureConnection ).

可以使用一个connection来开启或关闭一个input或output数据流. 也可以使用connection监控一个audio频道的码率平均值和峰值.

注意: 媒体捕捉不支持模拟器,也不能同时使用iOS设备上的前置摄像头和后置摄像头进行捕捉

使用Capture Session协调数据流

数据采集管理的核心是 AVCaptureSession . 在session中添加采集设备并对output进行配置之后, 可以向session发送 startRunning 消息开始采集, 发送 stopRunning消息停止采集.

AVCaptureSession *session = [[AVCaptureSession alloc] init];
// Add inputs and outputs.
[session startRunning];

配置Capture Session

使用session的 sessionPreset 属性指定图片质量和分辨率:

  • AVCaptureSessionPresetHigh: 高分辨率, 最终效果根据设备不同有所差异
  • AVCaptureSessionPresetMedium: 中等分辨率, 适合Wi-Fi分享. 最终效果根据设备不同有所差异
  • AVCaptureSessionPresetLow: 低分辨率, 适合3G分享, 最终效果根据设备不同有所差异
  • AVCaptureSessionPreset640x480: 640x480, VGA
  • AVCaptureSessionPreset1280x720: 1280x720, 720p HD
  • AVCaptureSessionPresetPhoto: 全屏照片, 不能用来作为输出视频

在设置一个preset之前, 需要判断设备是否支持该preset值:

if ([session canSetSessionPreset:AVCaptureSessionPreset1280x720]) {
    session.sessionPreset = AVCaptureSessionPreset1280x720;
}
else {
    // Handle the failure.
}

如果需要设置一个更高分辨率的preset, 或者在session运行时修改一些配置, 需要在beginConfiguration 和 commitConfiguration 之间完成修改. beginConfiguration和 commitConfiguration 方法确保所有的修改被整体应用, 减少对预览状态的影响. 在调用 beginConfiguration 之后, 可以添加或移除一个output, 修改 sessionPreset 属性, 或者单独配置input和output的属性. 只有调用了 commitConfiguration 方法, 改变才会生效.

[session beginConfiguration];
// Remove an existing capture device.
// Add a new capture device.
// Reset the preset.
[session commitConfiguration];

监测Capture Session的状态

可以使用通知(NSNotification)监测session的状态, 并且所有的通知都在主线程中发送. 注册监听 AVCaptureSessionRuntimeError 通知可以捕捉运行时发生的错误. 也可以使用session的 running 属性判断当前的运行状态, interrupted 属性则可以判断当前是否中断. 此外, running 和 interrupted 属性都可以通过KVO进行监听.

使用AVCaptureDevice表示输入设备

AVCaptureDevice 是对实际的物理捕捉设备的抽象, 物体捕捉设备向 AVCaptureSession 提供数据. 每个 AVCaptureDevice 对象代表一个实际的输入设备, 例如前摄像头或后摄像头, 或麦克风.

使用 AVCaptureDevice 类的 devices 和 devicesWithMediaType: 方法可以获取当前可用的捕捉设备. 而且可以获取捕捉设备的设备特性(参见 Device Capture Settings ). 当前的可用设备的状态可能会发生改变, 当前使用的输入设备可能会变为不可用状态(如果设备被另外一个应用使用), 也可能会有新的设备变为可用状态(被其他应用释放). 注册接收 AVCaptureDeviceWasConnectedNotification 和 AVCaptureDeviceWasDisconnectedNotification 通知可以得知可用设备列表的变化.

设备特性

可以获取一个设备的设备特性. 也可以通过 hasMediaType: 方法判断设备是否支持特定媒体类型的捕捉, 通过 supportsAVCaptureSessionPreset: 判断设备是否支持特定的分辨率. 当要提供一个可用的捕捉设备列表给用户进行选择时, 获取展示出设备的位置以及名称(比如前摄像头或后摄像头)拥有更好的用户体验.

下图展示了前摄像头( AVCaptureDevicePositionFront )和后摄像头( AVCaptureDevicePositionBack ):

下面的代码遍历了所有的可用设备并打印其名称, 如果是视频设备, 则打印其位置:

NSArray *devices = [AVCaptureDevice devices];

for (AVCaptureDevice *device in devices) {

    NSLog(@"Device name: %@", [device localizedName]);

    if ([device hasMediaType:AVMediaTypeVideo]) {

        if ([device position] == AVCaptureDevicePositionBack) {
            NSLog(@"Device position : back");
        }
        else {
            NSLog(@"Device position : front");
        }
    }
}

此外, 还可以获取设备的model ID以及unique ID.

捕捉设置

不同的设备之间存在性能差异, 比如一些设备支持特殊的对焦或闪光灯模式, 某些设备还支持兴趣点对焦.

下面的代码示例了如何找出一个支持手电筒模式和特定preset的设备:

NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
NSMutableArray *torchDevices = [[NSMutableArray alloc] init];

for (AVCaptureDevice *device in devices) {
    [if ([device hasTorch] &&
         [device supportsAVCaptureSessionPreset:AVCaptureSessionPreset640x480]) {
        [torchDevices addObject:device];
    }
}

如果找到了多个符合要求的设备, 你可能需要让用户选择其中的某一个设备, 这时可以使用 localizedName 属性获取设备的描述信息.

可以用类似的方式实现各种不同的捕捉设置. 框架预定义了一些常量用来代表特定的捕捉模式, 你可以使用这些常量以便于判断设备是否支持特定的模式. 在大部分情况下, 可以通过属性监听获取设备特性的变化状态. 任何情况下, 在改变设备的捕捉设置之前, 都应该先锁定设备, 详见下节 设备的配置 .

兴趣点对焦模式和兴趣点曝光模式是互斥的, 正如对焦模式和曝光模式也是互斥的一样

对焦模式

有三种对焦模式:

  • AVCaptureFocusModeLocked : 固定焦点
  • AVCaptureFocusModeAutoFocus : 自动对焦然后锁定焦点
  • AVCaptureFocusModeContinuousAutoFocus : 连续自动对焦

使用 isFocusModeSupported: 方法判断设备是否支持给定的对焦模式, 然后设置属性 focusMode 改变对焦模式.

此外, 一些设备还支持兴趣点对焦模式. 通过方法 focusPointOfInterestSupported判断是否支持该模式, 然后使用属性 focusPointOfInterest 设置焦点. 无论设备是横屏(Home键靠右)或竖屏模式, CGPoint{0,0}代表设备左上角, CGPoint{1,1}代表设备右下角.

属性 adjustingFocus 可以用来判断当前设备是否正在对焦中. 可以使用KVO监听该属性获取对焦开始与结束的通知.

设置对焦模式的示例代码如下:

if ([currentDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) {
    CGPoint autofocusPoint = CGPointMake(0.5f, 0.5f);
    [currentDevice setFocusPointOfInterest:autofocusPoint];
    [currentDevice setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
}

曝光模式

有两种曝光模式:

  • AVCaptureExposureModeContinuousAutoExposure : 自动调整曝光等级
  • AVCaptureExposureModeLocked : 固定曝光等级

使用 isExposureModeSupported: 方法判断设备是否支持给定的曝光模式, 然后设置属性 exposureMode 改变曝光模式.

此外, 一些设备还支持兴趣点曝光模式. 通过方法 exposurePointOfInterestSupported 判断是否支持该模式, 然后使用属性 exposurePointOfInterest 设置曝光点. 无论设备是横屏(Home键靠右)或竖屏模式, CGPoint{0,0}代表设备左上角, CGPoint{1,1}代表设备右下角.

属性 adjustingExposure 可以用来判断当前设备是否正在改变曝光设置中. 可以使用KVO监听该属性获取开始设置曝光模式与结束设置曝光模式的通知.

设置曝光模式的示例代码如下:

if ([currentDevice isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]) {
    CGPoint exposurePoint = CGPointMake(0.5f, 0.5f);
    [currentDevice setExposurePointOfInterest:exposurePoint];
    [currentDevice setExposureMode:AVCaptureExposureModeContinuousAutoExposure];
}

闪光模式

有三种闪光模式:

  • AVCaptureFlashModeOff : 关闭
  • AVCaptureFlashModeOn : 打开
  • AVCaptureFlashModeAuto : 根据环境亮度自动开启或关闭

使用方法 hasFlash 判断一个设备是否有闪光灯. 使用方法 isFlashModeSupported: 判断是否支持某个闪光模式, 使用属性 flashMode 设置闪光灯模式.

手电筒模式

手电筒模式下, 闪光灯会一直处于开启状态, 用于视频捕捉. 有三种手电筒模式:

  • AVCaptureTorchModeOff : 关闭
  • AVCaptureTorchModeOn : 打开
  • AVCaptureTorchModeAuto : 根据需要自动开启或关闭

使用方法 hasTorch 判断一个设备是否有闪光灯. 使用方法 isTorchModeSupported: 判断是否支持某个手电筒模式, 使用属性 torchMode 设置手电筒模式.

对于一个有手电筒的设备, 手电筒只有在设备与一个运行中的 capture session进行了关联后才可以设置为开启.

视频稳定性

依赖于某些特殊的硬件设备, 视频会有更好设置达到电影级别的稳定性. 但并不支持所有的视频格式和分辨率.

开启电影级别的视频稳定性特性在捕捉视频时可能会增加延迟. 使用属性 videoStabilizationEnabled 可以判断当前是否使用了视频稳定性特性. 属性 enablesVideoStabilizationWhenAvailable 可以在设备支持的情况下自动开启视频稳定性特性, 该属性默认为关闭状态.

白平衡

有两种白平衡模式:

  • AVCaptureWhiteBalanceModeLocked : 固定参数的白平衡
  • AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance : 由相机自动调整白平衡参数

使用方法 isWhiteBalanceModeSupported: 判断设备是否支持给定的白平衡模式, 然后通过属性 whiteBalanceMode 设置白平衡模式.

使用属性 adjustingWhiteBalance 判断当前是否正在修改白平衡模式. 可以使用KVO监听该属性获取开始设置白平衡模式与结束设置白平衡模式的通知.

设置设备方向

可以在 AVCaptureConnection 上指定期望的设备方向, 用来设置输出时 AVCaptureOutput ( AVCaptureMovieFileOutput , AVCaptureStillImageOutput 和 AVCaptureVideoDataOutput )的设备方向.

使用属性 AVCaptureConnectionsupportsVideoOrientation 判断设备是否支持修改视频方向, 使用属性 videoOrientation 指定一个方向. 下面的代码将 AVCaptureConnection 的方向设置为 AVCaptureVideoOrientationLandscapeLeft :

AVCaptureConnection *captureConnection = <#A capture connection#>;
if ([captureConnection isVideoOrientationSupported])
{
    AVCaptureVideoOrientation orientation = AVCaptureVideoOrientationLandscapeLeft;
    [captureConnection setVideoOrientation:orientation];
}

设备配置

要修改设备的捕捉属性, 首先需要使用方法 lockForConfiguration: 锁定设备, 这样可以避免与其他应用的设置产生冲突.

if ([device isFocusModeSupported:AVCaptureFocusModeLocked]) {
    NSError *error = nil;
    if ([device lockForConfiguration:&error]) {
        device.focusMode = AVCaptureFocusModeLocked;
        [device unlockForConfiguration];
    }
    else {
        // Respond to the failure as appropriate.

    }

切换设备

某些场景下可能需要允许用户切换输入设备, 比如前后摄像头. 为了避免卡顿, 可以重新配置正在运行的session, 但是嵌套使用  声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除


路过
1

雷人

握手

鲜花

鸡蛋

刚表态过的朋友 (1 人)

  • 雷人

    匿名

最新评论

返回顶部