首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >混淆CIContext,OpenGL和金属(SWIFT)。CIContext默认使用CPU或GPU吗?

混淆CIContext,OpenGL和金属(SWIFT)。CIContext默认使用CPU或GPU吗?
EN

Stack Overflow用户
提问于 2018-08-19 23:27:06
回答 2查看 4K关注 0票数 3

因此,我正在制作一个应用程序,其中一些主要功能围绕着将CIFilters应用于图像。

代码语言:javascript
复制
let context = CIContext()
let context = CIContext(eaglContext: EAGLContext(api: .openGLES3)!)
let context = CIContext(mtlDevice: MTLCreateSystemDefaultDevice()!)

所有这些给了我大约相同的CPU使用率(70%)在我的CameraViewController,在那里我应用过滤器的帧和更新的图像视图。所有这些似乎都是一样的,这让我觉得我错过了一些重要的信息。

例如,使用AVFoundation,我从相机中获取每一帧,应用过滤器并使用新图像更新图像视图。

代码语言:javascript
复制
let context = CIContext()

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
    connection.videoOrientation = orientation
    connection.isVideoMirrored = !cameraModeIsBack
    let videoOutput = AVCaptureVideoDataOutput()
    videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue.main)

    let sharpenFilter = CIFilter(name: "CISharpenLuminance")
    let saturationFilter = CIFilter(name: "CIColorControls")
    let contrastFilter = CIFilter(name: "CIColorControls")
    let pixellateFilter = CIFilter(name: "CIPixellate")

    let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
    var cameraImage = CIImage(cvImageBuffer: pixelBuffer!)

    saturationFilter?.setValue(cameraImage, forKey: kCIInputImageKey)
    saturationFilter?.setValue(saturationValue, forKey: "inputSaturation")
    var cgImage = context.createCGImage((saturationFilter?.outputImage!)!, from: cameraImage.extent)!
    cameraImage = CIImage(cgImage: cgImage)

    sharpenFilter?.setValue(cameraImage, forKey: kCIInputImageKey)
    sharpenFilter?.setValue(sharpnessValue, forKey: kCIInputSharpnessKey)
    cgImage = context.createCGImage((sharpenFilter?.outputImage!)!, from: (cameraImage.extent))!
    cameraImage = CIImage(cgImage: cgImage)

    contrastFilter?.setValue(cameraImage, forKey: "inputImage")
    contrastFilter?.setValue(contrastValue, forKey: "inputContrast")
    cgImage = context.createCGImage((contrastFilter?.outputImage!)!, from: (cameraImage.extent))!
    cameraImage = CIImage(cgImage: cgImage)

    pixellateFilter?.setValue(cameraImage, forKey: kCIInputImageKey)
    pixellateFilter?.setValue(pixelateValue, forKey: kCIInputScaleKey)
    cgImage = context.createCGImage((pixellateFilter?.outputImage!)!, from: (cameraImage.extent))!
    applyChanges(image: cgImage)

}

另一个例子是如何将更改应用于普通图像(所有这些都使用滑块)。

代码语言:javascript
复制
   func imagePixelate(sliderValue: CGFloat){
    let cgImg = image?.cgImage
    let ciImg = CIImage(cgImage: cgImg!)
    let pixellateFilter = CIFilter(name: "CIPixellate")
    pixellateFilter?.setValue(ciImg, forKey: kCIInputImageKey)
    pixellateFilter?.setValue(sliderValue, forKey: kCIInputScaleKey)
    let outputCIImg = pixellateFilter?.outputImage!
    let outputCGImg = context.createCGImage(outputCIImg!, from: (outputCIImg?.extent)!)
    let outputUIImg = UIImage(cgImage:outputCGImg!, scale:(originalImage?.scale)!, orientation: originalOrientation!)
    imageSource[0] = ImageSource(image: outputUIImg)
    slideshow.setImageInputs(imageSource)
    currentFilteredImage = outputUIImg
}

几乎是这样:

  1. 从CgImg创建UiImg
  2. 从CiImg创建CgImg
  3. 使用上下文应用筛选器并将其转换回UiImg
  4. 用新的UiImg更新任何视图

这在我的iPhone X上运行得很好,在我的iPhone 6上也非常好。由于我的应用程序已经相当完整,所以我希望尽可能地优化它。我看过很多关于使用OpenGL和Metal来做事情的文档,但似乎无法弄清楚如何开始。

我一直以为我是在CPU上运行这些进程,但是用OpenGL和Metal创建上下文并没有提供任何改进。我需要使用MetalKit视图还是GLKit视图(似乎完全不推荐eaglContext)?我怎么把这个翻译完?苹果的文件似乎毫无新意。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-08-19 23:57:22

我开始对此发表评论,但我认为,自从WWDC'18‘以来,这是一个最好的答案。我会编辑更多的专家,而不是我的评论,并愿意删除整个答案,如果这是正确的事情。

你是在正确的轨道-利用GPU时,你可以,这是一个很好的适合。CoreImage和Metal,虽然“通常”使用GPU的“低级”技术,但如果需要的话,可以使用CPU。CoreGraphics?它使用CPU呈现事物。

图像。UIImageCGImage是实际的图像。然而,CIImage却不是,最好的思考方法是一个图像的“配方”。

我通常--现在,我将解释一下--在使用过滤器时坚持使用CoreImage、CIFilters、CIImages和GLKViews。对GLKView使用CIImage意味着使用OpenGL和单个CIContextEAGLContext。它提供的性能几乎与使用MetalKitMTKViews一样好。

至于使用UIKit (它是UIImageUIImageView ),我只在需要时才这样做--保存/共享/上传,什么的。坚持到那个时候。

……

从这里开始变得复杂起来。

金属是苹果专有的API。因为他们拥有硬件--包括CPU和GPU --他们为他们优化了硬件。它的“管道”与OpenGL略有不同。没什么大不了的,只是不一样。

直到WWDC'18,使用GLKit,包括GLKView,都很好。但是所有的东西OpenGL都被破坏了,苹果公司正在把东西转移到金属上。虽然性能(目前)并不是很好,但最好还是使用MTKView、Metal和CIContext` `。

请看答案:马特给了这里一个很好的使用MTKViews的方法。

票数 3
EN

Stack Overflow用户

发布于 2018-08-20 03:08:15

一些独立的观点:

  • 分析一下你的应用程序,找出它花在哪里的CPU时间。
  • 如果图形工作实际上不是很难-也就是说,如果您的应用程序没有GPU绑定-优化GPU工作可能无助于整体性能。
  • 尽量避免在CPU和GPU之间来回移动数据。不要一直为每个过滤器输出创建CGImage。核心图像的一个主要特征是链式过滤器能力不对每个图像进行渲染,然后一次渲染所有的效果。此外,正如dfd在他的回答中所说,如果您直接呈现到屏幕上,而不是创建一个UIImage在图像视图中显示,那就更好了。
  • 避免重复工作。不要每次都重新创建CIFilter对象。如果参数没有改变,不要每次都重新配置它们。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51922595

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档