【问题标题】:How to apply "filters" to AVCaptureVideoPreviewLayer如何将“过滤器”应用于 AVCaptureVideoPreviewLayer
【发布时间】:2011-07-06 15:00:55
【问题描述】:

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

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

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

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

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

【问题讨论】:

    标签: iphone avfoundation avcapturesession


    【解决方案1】:

    Apple 的示例 AVCamFilter 全部完成

    【讨论】:

      【解决方案2】:

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

      如果您只是对将 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 之外的不同过滤技术的示例。

      【讨论】:

      • 这个着色器是否还允许您更改创建的电影/视频,或仅更改预览层?
      【解决方案3】:

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

      我有一个示例应用程序here,我在其中从相机抓取帧并应用 OpenGL ES 2.0 着色器来实时处理视频以进行显示。在这个应用程序中(详细解释here),我使用基于颜色的过滤来跟踪相机视图中的对象,但其他人已经修改了这段代码来做一些整洁的视频处理效果。此应用程序中所有基于 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 的开源框架,它封装了这种自定义图像过滤。它还处理捕获视频并在过滤后将其显示到屏幕上,只需六行代码即可完成所有这些设置。有关该框架的更多信息,您可以阅读my more detailed announcement

      【讨论】:

      • @UFO - iOS 7 上的两通滤镜和静止图像存在一个已知错误,是的。他们处理实时摄像机输入和电影,但出于某种原因在该操作系统上使用静止图像生成黑色图像。我正在调查。
      • @BradLarson 有什么办法可以在您的代码中使用 cifilter(mono、tonal、noir 等)?
      • 此示例代码已过时,甚至无法在 xcode 8.2 上运行
      • @Crashalot - 需要更新什么?如果您指的是示例代码,那么更新它是读者的练习。基本概念仍然适用。
      • 感谢您的快速响应!只是想知道答案是否已过时或仍然相关——即,最高效的方式是 OpenGL ES,而 AVCaptureVideoPreviewLayer 提供的灵活性很小——因为答案已经超过 6 年了。谢谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-21
      • 2021-09-18
      • 1970-01-01
      • 2017-08-25
      • 2019-11-29
      • 2014-04-05
      • 1970-01-01
      相关资源
      最近更新 更多