2016-04-26 23 views
-2

私はアプリで画像処理を行っています。ライブビデオを撮影し、その上に画像を追加してオーバーレイとして使用します。残念ながら、これは、プログラムの他の部分が遅くなり、意図したとおりに動作しないようにするために大量のCPUを使用しています。基本的に、私は次のコードをCPUの代わりにGPUを使用したいと思っています。順番にiOSでGPUを使用して別の画像(ビデオフレーム)に1つの画像を重ねる

- (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;} 
+1

あなたはこのコードをプロファイリングしましたか? 'UIGraphicsBeginImageContext' /' UIGraphicsEndImageContext'の組み合わせは、その背後にあるメモリ配分のためにかなりのコストがかかります。すべてのコンポジションで新しいコンテキストを作成して破壊するだけでは、かなりうまくいくでしょう。 – Tommy

+0

問題はメモリではありません。実際にはかなり低いですが、イメージをビデオフレームにオーバーレイしてRTMP経由で送信すると、CPUが20%から95%にジャンプします。私はそれがビデオフレームが圧縮されているレートで混乱して95%のマークを取得するように、CPUを低く保つようにGPUで取得することを望んでいました。 – Charlie

+1

私はそれが相当の処理コストであると賭けています。メモリ割り当ては、同期とOS内部の非O(1)構造調整を意味します。 GPUへの切り替えが問題を解決するための非常に鈍い方法かもしれないことを示唆しているだけです。 '[UIImage imageNamed:]'がコストをかけているかを調べるためにプロファイルする必要があります - 'imageNamed:'はキャッシュの対象ですが、それは間違いなく速くなることを意味します。 – Tommy

答えて

1

最大のパフォーマンスの問題は、各フレームあなたがCIContextEAGLContextを作成することです。これは、processUsingCoreImageメソッドの外部で1回だけ実行する必要があります。また

あなたの代わりにあなたがこのようEaglLayerに直接レンダリングすることができ、処理ので、CPUをコアグラフィックス画像(createCGImage)を作成するので、CPU-GPUの往復を避けたい場合:

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

返信ありがとうございました。[self createPaddedGhostImageWithSize:CGSizeMake(1280,720)]がCPUスパイクの大きな原因であることが判明したので、画像を一度しか作成せず、その後多くの助けになりました。また、グローバル変数としてEAGLContextを再利用するように変更しました。CIContextでそれを試してみましょう。 OpenGLは行く方法のようだが、私の頭の上では、私はeagllayerを見てみましょう。 – Charlie

2

提案:

  1. は、あなたが実際には2枚の画像を合成する必要がありますか? AVCaptureVideoPreviewLayerUIImageViewが不十分ですか?次に、現在のゴースト変換を画像ビュー(またはそのレイヤー)に適用して、コンポジットに2つの画像を貼り合わせてGPUを使用させます。
  2. もしそうでなければ、最初のコールポートはCoreImageでなければなりません。GPUイメージ操作を比較的簡単なSwift/Objective-Cパッケージにまとめます。シンプルなコンポジションフィルターがありますので、2つのものをCIImageにして-imageByApplyingTransform:を使ってゴーストを調整するだけです。
  3. これらの両方に問題がある場合は、OpenGLソリューションを検討しています。具体的には、CVOpenGLESTextureCacheを使用してコアビデオフレームをGPUにプッシュすると、ゴーストはそこに永続的に存続します。あなたがまだしていない場合は、から始めて、GLKBaseEffectを調べて、GLSLを知る必要がないようにしてください。あなたがする必要があるのは、いくつかの頂点をパッケージ化し、描画呼び出しを行うことだけです。
+0

1。残念ながらそのシンプルではない、そのストリーミングビデオフレームので、私は上にUIImageViewを置くことはできません私は両方のオーバーレイを含む新しいフレームを必要とするだけでなく、ストリームだけでなく、ブロードキャストに表示されます。 2.私は昨晩コア・イメージに切り替えました(私はそれを表示するために上記のコードを更新します)。しかし、それはまだProfilerで0FPSを示しているGPU上にあるようではなく、High CPUも存在します。私はGLSLを知らないが、いつも挑戦のためにそれを見て、そこには何が必要な正しい方向にあるように見えますか? – Charlie

関連する問題