背景との境界のカクカクを滑らかにします。iOSで使えるフィルターで実現できます。
機械学習のセマンティックセグメンテーションは、出力サイズが512,512程度なので、拡大してマスク画像として用いると、オブジェクトのエッジ境界がカクカクしてしまいます。
中央値フィルターという平滑化フィルターを用いることで、境界を滑らかにできます。
中央値フィルターとは?:ピクセル値を、その周りのピクセル値の中央値に変えるフィルターだそうです。
iOSではMPSImageMedianフィルターが使えます。
#使い方
このフィルターを、拡大後のマスク画像に適用すると、エッジがスムースになります。
引数の「kernelDiameter」は、中央値をとる対象の周囲のピクセルの直径で3以上の奇数を指定する必要があります。
func edgeSmoothing(cgImage image:CGImage) -> CGImage {
let commandBuffer = self.commandQueue!.makeCommandBuffer()!
let median = MPSImageMedian(device: self.device as! MTLDevice, kernelDiameter: 15)
// kernelDiameter:中央値をとる対象の周囲のピクセルの直径
let textureLoader = MTKTextureLoader(device: self.device as! MTLDevice)
let options: [MTKTextureLoader.Option : Any]? = nil
let srcTex = try! textureLoader.newTexture(cgImage: image, options: options)
let desc = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: srcTex.pixelFormat,
width: srcTex.width,
height: srcTex.height,
mipmapped: false)
desc.pixelFormat = .rgba8Unorm
desc.usage = [.shaderRead, .shaderWrite]
let medTex = self.device!.makeTexture(descriptor: desc)!
median.encode(commandBuffer: commandBuffer, sourceTexture: srcTex, destinationTexture: medTex)
#if os(macOS)
let blitCommandEncoder = commandBuffer.makeBlitCommandEncoder()!
blitCommandEncoder.synchronize(resource: medTex)
blitCommandEncoder.endEncoding()
#endif
commandBuffer.commit()
commandBuffer.waitUntilCompleted()
let colorSpace = CGColorSpaceCreateDeviceRGB()
let bitmapInfo = CGImageAlphaInfo.noneSkipLast.rawValue
let bytesPerRow = lapTex.width * 4
let bitmapContext = CGContext(data: nil,
width: medTex.width,
height: medTex.height,
bitsPerComponent: 8,
bytesPerRow: bytesPerRow,
space: colorSpace,
bitmapInfo: bitmapInfo)!
medTex.getBytes(bitmapContext.data!,
bytesPerRow: bytesPerRow,
from: MTLRegionMake2D(0, 0, medTex.width, medTex.height),
mipmapLevel: 0)
return bitmapContext.makeImage()
}
🐣
お仕事のご相談こちらまで
rockyshikoku@gmail.com
Core MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。