Swift 개발
[swift] Chroma key filter
글른
2021. 4. 30. 14:53
Overview
- chroma key 효과는 greenscreening이나 bluescreening으로도 알려져 있는데, 투명하게 만들 색상을 정해서 target image에서 해당 색상 부분의 alpha value를 0으로 변경하고 background image와 합치는 것을 의미한다.
- 과정 (filter 두번 먹여주면 끝이다!!!!)
- Cube map 생성 : CIColorCube filter를 생성해서 투명하게 설정할 대상이 되는 색상을 결정한다
- CIColorFilter 적용 : source image의 모든 pixel에 대해서 CIColorCube filter를 적용한다
- source + background : CISourceOverCompositing filter를 사용해서 source와 background image를 합친다
Step1. Create a Cube Map
- Color cube란?
- RGB 색상에 투명도를 할당하는 3D color-loopup table이다
- 예를 들어 위의 사진처럼 input image에서 녹색을 제거하기 위해서, 녹색 부분에 대해 value를 0으로 설정하는 custom color cube를 생성하면 된다.
- HSC (hue-saturation-brightness) representation
- 특정한 색상의 범주를 정하기 위해서 HSV 표현법으로 모델링 한다.
- HSV는 hue(색상)을 각도로 나타내는데, screening color에 해당하는 영역에 대한 lookup table value를 0으로 설정하면 된다.
- 녹색에 해당하는 영역은 108도~144도로, greenscreening을 위해서는 color cube에서 이 범위에 투명도 값을 0으로 설정하면 된다.
func chromaKeyFilter(fromHue: CGFloat, toHue: CGFloat) -> CIFilter?
{
// 1. 3차원 Memory 할당해주기 (각 element는 RGBA로 구성됨)
let size = 64
var cubeRGB = [Float]()
// 2. RGB color combinatoin 만들기
for z in 0 ..< size {
let blue = CGFloat(z) / CGFloat(size-1)
for y in 0 ..< size {
let green = CGFloat(y) / CGFloat(size-1)
for x in 0 ..< size {
let red = CGFloat(x) / CGFloat(size-1)
// 3. RGB를 HSV로 변환하기. (getHue 함수를 활용)
let hue = getHue(red: red, green: green, blue: blue)
// green 영역에 해당하는 hue의 transparency 설정하기 (108~144)
let alpha: CGFloat = (hue >= fromHue && hue <= toHue) ? 0: 1
// 4. CIColorCube filter는 미리 alpah value와 곱해져 있어야함
// (그래서 transparency 포함한 lookup table)이라고 함)
cubeRGB.append(Float(red * alpha))
cubeRGB.append(Float(green * alpha))
cubeRGB.append(Float(blue * alpha))
cubeRGB.append(Float(alpha))
}
}
}
let data = Data(buffer: UnsafeBufferPointer(start: &cubeRGB, count: cubeRGB.count))
// 5. cube data로부터 Color image filter 생성하기
let colorCubeFilter = CIFilter(name: "CIColorCube", withInputParameters: ["inputCubeDimension": size, "inputCubeData": data])
return colorCubeFilter
}
// RGB representation -> HSV representation 을 위한 함수
func getHue(red: CGFloat, green: CGFloat, blue: CGFloat) -> CGFloat
{
let color = UIColor(red: red, green: green, blue: blue, alpha: 1)
var hue: CGFloat = 0
color.getHue(&hue, saturation: nil, brightness: nil, alpha: nil)
return hue
}
Step2. Remove Green from the Source Image
- source image에 step1에서 생성한 colorCubeFilter를 먹여서 모든 green pixel이 투명해진 output image를 얻는다.
- 이때 108도가 0.3에 해당하고 144도가 0.4에 해당한다고 한다. (왜인지는 잘 모르겠다)
let chromaCIFilter = self.chromaKeyFilter(fromHue: 0.3, toHue: 0.4)
chromaCIFilter?.setValue(foregroundCIImage, forKey: kCIInputImageKey)
let sourceCIImageWithoutBackground = chromaCIFilter?.outputImage
Step3. Composite over a Background Image
- step2의 결과로 얻은 output image에 CISourceOverCompositing filter를 먹여서 background image를 greenscreened output image와 합성한다.
let compositor = CIFilter(name:"CISourceOverCompositing")
compositor?.setValue(sourceCIImageWithoutBackground, forKey: kCIInputImageKey)
compositor?.setValue(backgroundCIImage, forKey: kCIInputBackgroundImageKey)
let compositedCIImage = compositor?.outputImage
참고 사이트 : developer.apple.com/documentation/coreimage/applying_a_chroma_key_effect
Apple Developer Documentation
developer.apple.com