在iOS上使用GPU在另一个图像(视频帧)上覆盖一个图像

时间:2016-04-26 17:01:55

标签: ios opengl opengl-es

我在我的应用中处理一些图像处理。拍摄实时视频并在其上添加图像以将其用作叠加层。不幸的是,这需要大量的CPU来执行,这会导致程序的其他部分变慢并且不能按预期工作。基本上我想让以下代码使用GPU而不是CPU。

- (UIImage *)processUsingCoreImage:(CVPixelBufferRef)input {

    CIImage *inputCIImage = [CIImage imageWithCVPixelBuffer:input];


// Use Core Graphics for this
UIImage * ghostImage = [self createPaddedGhostImageWithSize:CGSizeMake(1280, 720)];//[UIImage imageNamed:@"myImage"];
CIImage * ghostCIImage = [[CIImage alloc] initWithImage:ghostImage];

CIFilter * blendFilter = [CIFilter filterWithName:@"CISourceAtopCompositing"];
[blendFilter setValue:ghostCIImage forKeyPath:@"inputImage"];
[blendFilter setValue:inputCIImage forKeyPath:@"inputBackgroundImage"];

CIImage * blendOutput = [blendFilter outputImage];

EAGLContext *myEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
NSDictionary *contextOptions = @{ kCIContextWorkingColorSpace : [NSNull null] ,[NSNumber numberWithBool:NO]:kCIContextUseSoftwareRenderer};
CIContext *context = [CIContext contextWithEAGLContext:myEAGLContext options:contextOptions];

CGImageRef outputCGImage = [context createCGImage:blendOutput fromRect:[blendOutput extent]];
UIImage * outputImage = [UIImage imageWithCGImage:outputCGImage];
CGImageRelease(outputCGImage);

return outputImage;}

2 个答案:

答案 0 :(得分:2)

建议顺序:

  1. 你真的需要合成两张图片吗?最高AVCaptureVideoPreviewLayer UIImageView是否不足?然后,您只需将当前的重影变换应用于图像视图(或其图层),然后让合成器将两者粘合在一起,为此它将使用GPU。
  2. 如果没有,那么第一个调用端口应该是CoreImage - 它将GPU图像操作包装成一个相对简单的Swift / Objective-C包。有一个简单的合成过滤器,所以你需要做的就是将这两件事变成CIImage并使用-imageByApplyingTransform:来调整重影。
  3. 两者都失败了,那么你正在寻找一个OpenGL解决方案。您特别希望使用CVOpenGLESTextureCache将核心视频帧推送到GPU,并且幽灵将永久地存在于那里。从GLCameraRipple sample开始,然后查看GLKBaseEffect以避免需要了解GLSL(如果您还没有)。您需要做的就是打包一些顶点并进行绘图调用。

答案 1 :(得分:1)

最大的性能问题是您创建的每个框架 EAGLContext CIContext 。这只需要在processUsingCoreImage方法之外完成一次。

此外,如果你想避免CPU-GPU往返,而不是创建一个核心图形图像(createCGImage),这样Cpu处理就可以直接在EaglLayer中渲染,如下所示:

[context drawImage:blendOutput inRect: fromRect: ];
[myEaglContext presentRenderBuffer:G:_RENDERBUFFER];