web-dev-qa-db-ja.com

AVCaptureVideoPreviewLayerに「フィルター」を適用する方法

私のアプリは現在、AVFoundationを使用して、iPhoneの背面カメラから生のカメラデータを取得し、リアルタイムでAVCaptureVideoPreviewLayerに表示しています。

私の目標は、簡単な画像フィルターを条件付きでプレビューレイヤーに適用することです。画像は保存されないため、出力をキャプチャする必要はありません。たとえば、プレビューレイヤーに入るビデオを白黒に変換する設定を切り替えたいと思います。

私は質問を見つけました here 個別のビデオフレームをバッファーにキャプチャし、必要な変換を適用し、各フレームをUIImageとして表示することで、同様のことを達成しているようです。いくつかの理由で、これは私のプロジェクトにとってやり過ぎのように思われ、これが引き起こす可能性のあるパフォーマンスの問題を回避したいと思います。

これが私の目標を達成する唯一の方法ですか?

前述のように、AVCaptureSessionのビデオをキャプチャするのではなく、プレビューするだけです。

30
eschurter

おそらくこれを処理する最もパフォーマンスの高い方法は、これらのビデオフレームのフィルタリングと表示にOpenGL ESを使用することでしょう。 AVCaptureVideoPreviewLayerを直接使用して、別のビューまたはレイヤーでオーバーレイされたときに不透明度を調整することを除いて、多くを行うことはできません。

サンプルアプリケーションがあります こちら ここで、カメラからフレームを取得し、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 というオープンソースフレームワークを作成しました。また、ビデオをキャプチャし、フィルタリング後に画面に表示することもできるので、これらすべてを設定するのに必要なコードはわずか6行です。フレームワークの詳細については、 私の詳細なお知らせ を参照してください。

66
Brad Larson

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レンダラーに送信します

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

OpenGLレンダラーでsourcePixelBufferをテクスチャにアタッチすると、OpenGLシェーダー内でフィルター処理できます。シェーダーは、ピクセルごとのベースで実行されるプログラムです。 Rosy Writerの例は、OpenGL以外のさまざまなフィルタリング技術の使用例も示しています。

3
izzy

Appleの例 AVCamFilter はそれをすべて行います

enter image description here

0
Nick Kovalsky