ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [swift] Chroma key filter
    Swift 개발 2021. 4. 30. 14:53

    Overview

    • chroma key 효과는 greenscreening이나 bluescreening으로도 알려져 있는데, 투명하게 만들 색상을 정해서 target image에서 해당 색상 부분의 alpha value를 0으로 변경하고 background image와 합치는 것을 의미한다.

    • 과정 (filter 두번 먹여주면 끝이다!!!!)
      1. Cube map 생성 : CIColorCube filter를 생성해서 투명하게 설정할 대상이 되는 색상을 결정한다
      2. CIColorFilter 적용 : source image의 모든 pixel에 대해서 CIColorCube filter를 적용한다
      3. 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

     

    댓글

Written by Geulleun