Metalでカメラからの動画入力をリアルタイム処理する

1 Star2 Stars3 Stars4 Stars5 Stars (まだ評価されていません)
Loading...

Metalのパフォーマンスがわかりやすく活きる例としては、動画のリアルタイム処理です。動画撮影中に30fpsなり60fpsなりで渡されてくるカメラからの入力をMetalで画像処理し、Metalで描画する、ということをやります。

カメラからの入力を取得する

カメラからの入力をリアルタイムに受け取るようにする実装は、何も新しいことはないのでここでは省略します。AVFoundationのAVCaptureSessionを用いるおなじみのものです。iOS-10-Samplerにもそういう実装があるので必要に応じてご参照ください。

関連:

AVCaptureVideoDataOutputSampleBufferDelegate プロトコルの captureOutput:didOutputSampleBuffer:fromConnection: メソッドで、カメラからの入力がCMSampleBuffer として渡されてきます。

func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!)

ここから CMSampleBufferGetImageBuffer() を用いて、 CVImageBuffer (CVPixelBuffer)を取り出します。

let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)

ここまではiOSデバイスでカメラ入力に対して何かやりたいときには必ず通る、おなじみの手順かと思います。

CVImageBuffer -> MTLTexture

ここからが本番で、Metalで処理するために、 CVImageBuffer (CVPixelBuffer) からMTLTextureを生成します。

1.CVMetalTextureCacheを生成

まず、CVMetalTextureCacheを用意しておきます。

(Swift)

var textureCache : CVMetalTextureCache?

CVMetalTextureCacheCreate(kCFAllocatorDefault, nil, device, nil, &textureCache)

(ObjC)

CVMetalTextureCacheRef textureCache;

CVMetalTextureCacheCreate(kCFAllocatorDefault,
nil,
device,
nil,
&textureCache);

deviceMTLDevice

CVMetalTextureCacheは、CVMetalTexture型のテクスチャを生成・管理するためのクラスです。以下リファレンスより引用。

A CoreVideo Metal texture cache creates and manages CVMetalTexture textures. You use a CVMetalTextureCache object to directly read from or write to GPU-based CoreVideo image buffers in rendering or GPU compute tasks that use the Metal framework.

テクスチャをつくるたびに生成しなおす必要はありません。

2. CVImageBuffer -> CVMetalTexture

ここからは、カメラからの入力(CMSampleBuffer)を得るたびに行う処理です。

CVMetalTextureCacheを用いて、 CVImageBuffer から、 CVMetalTexture を生成します。

swift

let width = CVPixelBufferGetWidth(imageBuffer)
let height = CVPixelBufferGetHeight(imageBuffer)
var imageTexture: CVMetalTexture?
let result = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault, textureCache, imageBuffer, nil, pixelFormat, width, height, 0, &imageTexture)

objc

CVMetalTextureRef imageTexture;
CVReturn result = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
textureCache,
imageBuffer,
nil,
MTLPixelFormatBGRA8Unorm,
width, height, 0,
&imageTexture);

成功すれば、戻り値は kCVReturnSuccess となります。

ちなみに、CVMetalTextureとはどういうものかというと、「Metalで利用するためのtexture-basedなイメージバッファ」とのことです。

A texture-based image buffer that supplies source image data for use with the Metal framework.

3. CVMetalTexture -> MTLTexture

イメージバッファから、MTLTexture を取り出します。

swift

let texture = CVMetalTextureGetTexture(imageTexture)

objc

id<MTLTexture> texture = CVMetalTextureGetTexture(imageTexture);
CFRelease(imageTexture);

Objective-Cの場合は明示的にCVMetalTextureを解放する必要がある点に注意。

MTLTexture -> Metalで処理

Metalのシェーダで何かしらの処理を行う話は以下の記事に、

また、Metal Performance Shadersでリサイズやブラー処理を行う話はこちらに、

MTLTextureに対して(Metalでシームレスに)Core Imageで画像処理を行う話は下記記事に書きました。

MTLTexture -> MTKViewで表示(描画)

MTLTextureをMTKViewで描画する方法については、下記記事にまとめました。

出来上がり

(AnimatedGIFを載せる予定)

今後の展望

このへんの知見は、Metal Performance ShadersでのCNNを使う際にも活きてくる予定です。

近日中に記事を書く予定です。


1 Star2 Stars3 Stars4 Stars5 Stars (まだ評価されていません)
Loading...
      この投稿は審査処理中  | 元のサイトへ