31

我的应用程序目前正在使用 AVFoundation 从 iPhone 的后置摄像头获取原始摄像头数据,并将其实时显示在 AVCaptureVideoPreviewLayer 上。

我的目标是有条件地将简单的图像过滤器应用于预览层。图像没有保存,所以我不需要捕获输出。例如,我想切换一个设置,将进入预览层的视频转换为黑白。

我在这里发现了一个问题,它似乎通过在缓冲区中捕获单个视频帧,应用所需的转换,然后将每个帧显示为 UIImage 来完成类似的事情。出于几个原因,这对我的项目来说似乎有点过头了,我想避免这可能导致的任何性能问题。

这是实现我的目标的唯一方法吗?

正如我所提到的,我不想捕捉任何 AVCaptureSession 的视频,只是预览它。

4

3 回答 3

66

可能最有效的处理方式是使用 OpenGL ES 过滤和显示这些视频帧。除了在与另一个视图或图层重叠时调整其不透明度之外,您将无法直接使用 AVCaptureVideoPreviewLayer 做很多事情。

我在这里有一个示例应用程序,我从相机中抓取帧并应用 OpenGL ES 2.0 着色器来实时处理视频以进行显示。在这个应用程序中(这里有详细解释),我使用基于颜色的过滤来跟踪相机视图中的对象,但其他人已经修改了这个代码来做一些简洁的视频处理效果。此应用程序中所有基于 GPU 的过滤器在我的 iPhone 4 上以 60 FPS 的速度显示在屏幕上。

唯一支持视频但没有支持 OpenGL ES 2.0 的 GPU 的 iOS 设备是 iPhone 3G。如果您还需要以该设备为目标,您可以获取视频捕获和生成 OpenGL ES 纹理的基本代码,然后使用 Apple 的GLImageProcessing示例应用程序中的过滤器代码。该应用程序是围绕 OpenGL ES 1.1 构建的,所有 iOS 设备都支持它。

但是,我强烈建议为此使用 OpenGL ES 2.0,因为与使用固定功能的 OpenGL ES 1.1 管道相比,您可以使用着色器实现更多种类的效果。

(编辑:2/13/2012)作为对上述内容的更新,我现在创建了一个名为GPUImage的开源框架,它封装了这种自定义图像过滤。它还处理捕获视频并在过滤后将其显示到屏幕上,只需六行代码即可完成所有这些设置。有关该框架的更多信息,您可以阅读我更详细的公告

于 2011-03-01T18:43:01.503 回答
3

我建议查看 ios 开发库中的Rosy Writer示例。Brad Larson 的GPUImage 库非常棒,但对于这个问题似乎有点矫枉过正。

如果您只是对将 OpenGL 着色器(又名过滤器)添加到AVCaptureVideoPreviewLayer工作流感兴趣,那么您可以将捕获会话的输出发送到 OpenGL 视图进行渲染。

AVCaptureVideoDataOutput *videoOut = [[AVCaptureVideoDataOutput alloc] init];
videoOut.videoSettings = @{ (id)kCVPixelBufferPixelFormatTypeKey : @(_renderer.inputPixelFormat) };
[videoOut setSampleBufferDelegate:self queue:_videoDataOutputQueue];

然后在captureOutput:委托中将样本缓冲区发送到 OpenGL Renderer

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
    CVPixelBufferRef sourcePixelBuffer = CMSampleBufferGetImageBuffer( sampleBuffer );
    _renderer copyRenderedPixelBuffer:sourcePixelBuffer];
}

在 OpenGL 渲染器中附加sourcePixelBuffer到纹理,您可以在 OpenGL 着色器中对其进行过滤。着色器是在每像素基础上运行的程序。Rosy Writer 示例还展示了使用除 OpenGL 之外的不同过滤技术的示例。

于 2015-10-19T19:06:31.893 回答
1

Apple 的示例AVCamFilter完成了所有工作

在此处输入图像描述

于 2020-03-12T08:29:50.100 回答