色空間の変換方法とユースケース
この記事は 株式会社ガラパゴス(有志) Advent Calendar 2025 の21日目の記事です。
前書き
こんにちは。@samechaaです。
前回記事のまとめに書いた通り、Swiftにおける色空間(ピクセルフォーマット)の変換方法やユースケースについて紹介したいと思います。
変換が必要になるタイミング
- カメラ映像のリアルタイム処理:AVFoundationの出力をCoreMLやARKitに渡す場合など
- 動画の入出力・圧縮:YCbCr形式の動画ファイルをデコードして処理する場合など
- フレームワーク間の連携:ARKitからMetalへ描画データを渡す場合など
- 高度な画像処理をする時
変換速度
前述のタイミングでの変換では、パフォーマンスを考慮した変換方法を検討する必要が出てきます。
例として、カメラ出力のフォーマット変換を考えます。
よく挙げられる変換方法として、AVCaptureVideoDataOutputの設定で出力データのPixelFormatをRGBで指定する方法があります。
var output = AVCaptureVideoDataOutput()
output.videoSettings = [kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA]
これは確かに楽ではあるのですが、TN3121: Selecting a pixel format for an AVCaptureVideoDataOutputに記載がある通り、推奨される方法ではありません。カメラのハードウェアは通常YCbCrでデータを出力するため、ここでRGBを指定すると暗黙的な変換が発生し、フレーム落ちやバッテリー消費の増加の原因となります。
効率的な変換方法
パフォーマンスを考慮する場合、主に以下の2つの変換方法を利用します。
- メタルシェーダを利用する方法
- vImageを利用する方法
メタルシェーダを利用する方法
メタルシェーダで変換する方法はDisplaying an AR Experience with Metalにコードを交えて詳しい記載があります。
この記載ではフラグメントシェーダ内で変換を行っています。変換部分のマジックナンバーは、前回記事で紹介したYCbCrをRGBに変換する式を行列式にした時の係数です。GPUの並列演算能力を活かせるため、低遅延で処理ができます。
vImageを利用する方法
vImageはAccelerateフレームワークに含まれる画像処理用のフレームワークです。Overviewに記載されている通り、ビデオのリアルタイム処理や画像の処理などに適しています。
Metalに比べてSwiftコードだけで完結できるので扱いやすいです。
ビデオをリアルタイムに変換する方法としてApplying vImage operations to video sample buffersにサンプルコードが記載されています。
まとめ
色空間の変換が必要になるタイミングとユースケースについて簡潔に記述しました。ユースケースについてはもっと詳細に書こうと思っていたのですが、あらためて調査してみるとAppleの公式ドキュメントが豊富なのでそちらを見れば事足りるということが判明しました。
まずは公式ドキュメントを参考にしつつ、より低レイヤーで自由度の高い制御が必要ならMetal、Swiftらしく型安全かつ高速に処理したいならvImageを選ぶのが良いかと思います。
Discussion