画像をグレースケールへ変換する(Metal編)
May 3, 2017 · iosmetalswift3
RGBのMTLTextureをグレースケールのMTLTextureに変換する方法
UIImageを変換する方法はこちらを参照
Metal上でこういった画像処理をしたい場合は、MetalPerformanceShadersを利用する。
今回のような色空間の変更だけでなく、各種フィルタ処理なども高速に処理できる(どれくらい高速かは未確認)
ただし、iOS10(iOS_GPUFamily2_v3)以降でしか使えない
使い方
色空間の変更にはMPSImageConversionを利用する
色空間の定義はこちらのAccessing System-Defined Color Spacesを参照
変換元と変換後の色空間を定義する
sRGBからグレースケールの場合は以下のとおりlet srcColorSpace = CGColorSpace(name: CGColorSpace.sRGB)! let dstColorSpace = CGColorSpace(name: CGColorSpace.linearGray)! let conversionInfo = CGColorConversionInfo(src: srcColorSpace, dst: dstColorSpace)フィルタ(カーネル)を生成する
let device = MTLCreateSystemDefaultDevice()! let conversion = MPSImageConversion(device: device, srcAlpha: .alphaIsOne, destAlpha: .alphaIsOne, backgroundColor: nil, conversionInfo: conversionInfo)αは特に関係ないのでデフォルトの1に、背景色も指定しないので
nilにしておく実行する
let commandQueue = device.makeCommandQueue() let commandBuffer = commandQueue.makeCommandBuffer() conversion.encode(commandBuffer: commandBuffer, sourceTexture: colorTexture, destinationTexture: grayTexture) // 必要に応じて他のMetalの処理 commandBuffer.commit()これで
grayTextureにグレースケール化された画像が入る
小ネタ
色空間の調べ方
変換先の色空間はともかく、変換元の色空間がなんなのか判らない場合、
UIImage(CGImage)であれば以下で取得できる
let image: UIImage = ...
let colorSpace = image.cgImage!.colorSpace
ちなみにnilになる場合は、マスク画像が入っているらしい
MPSImageの場合
MPSをCNNで使っている場合などで、MTLTextureではなくMPSImageがソースの場合は、
conversion.encode(commandBuffer: commandBuffer,
sourceTexture: colorImage.texture,
destinationTexture: grayImage.texture)
というように指定する
なお、この場合は、必ずMPSImageのチャンネル数を合わせないと実行時にエラーとなるので注意
(RGBなら3、グレースケールなら1)
開発環境
- Xcode 8.3
- iOS 10.3.1
- iPhone 7+
