平滑Chroma Key的边缘 - CoreImage

9
我正在使用以下代码从图像中去除绿色背景。但是,图像的边缘有绿色色调,并且一些像素已经损坏。我该如何使其更加平滑并让图像剪切完美?
 func chromaKeyFilter(fromHue: CGFloat, toHue: CGFloat) -> CIFilter?
    {
        // 1
        let size = 64
        var cubeRGB = [Float]()

        // 2
        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
                    let hue = getHue(red: red, green: green, blue: blue)
                    let alpha: CGFloat = (hue >= fromHue && hue <= toHue) ? 0: 1

                    // 4
                    cubeRGB.append(Float(red * alpha))
                    cubeRGB.append(Float(green * alpha))
                    cubeRGB.append(Float(blue * alpha))
                    cubeRGB.append(Float(alpha))
                }
            }
        }



  @IBAction func clicked(_ sender: Any) {
          let a = URL(fileURLWithPath:"green.png")
          let b = URL(fileURLWithPath:"back.jpg")

        let image1 = CIImage(contentsOf: a)
        let image2 = CIImage(contentsOf: b)





        let chromaCIFilter = self.chromaKeyFilter(fromHue: 0.3, toHue: 0.4)
        chromaCIFilter?.setValue(image1, forKey: kCIInputImageKey)
        let sourceCIImageWithoutBackground = chromaCIFilter?.outputImage

        /*let compositor = CIFilter(name:"CISourceOverCompositing")
        compositor?.setValue(sourceCIImageWithoutBackground, forKey: kCIInputImageKey)
        compositor?.setValue(image2, forKey: kCIInputBackgroundImageKey)
        let compositedCIImage = compositor?.outputImage*/

        var rep: NSCIImageRep = NSCIImageRep(ciImage: sourceCIImageWithoutBackground!)
        var nsImage: NSImage = NSImage(size: rep.size)
        nsImage.addRepresentation(rep)

        let url = URL(fileURLWithPath:"file.png")

        nsImage.pngWrite(to: url)
        super.viewDidLoad()
    }

输入:

enter image description here

输出:

enter image description here

更新1:

enter image description here

更新2:

enter image description here

更新3:

enter image description here


你为什么注释掉那段代码?我看到这是苹果示例中的默认代码,https://developer.apple.com/documentation/coreimage/applying_a_chroma_key_effect,如果它能正常工作,那么是什么原因让你改变了他们的示例呢? - impression7vx
据我所知,这段代码替换了背景图像。但我只需要删除背景。苹果的示例代码不适用于macOS,我使用了CIImage,而OSX示例使用UIImage。 - techno
哦,我明白了。我只是好奇而已。 - impression7vx
嘿@techno,你解决了你的问题吗?我正在尝试修改苹果文档中的默认示例应用,但我在删除颜色时遇到了一些问题。您是否可以好心查看我的问题?非常感谢,伙计。https://dev59.com/Q3sQtIcB2Jgan1znErVp - Jason Krowl
2个回答

8
专业的色度键合工具通常包括所谓的溢色抑制器。溢色抑制器会查找包含少量色度键颜色的像素,并将颜色向相反方向移动。因此,绿色像素将向品红色移动。这减少了您经常在键控镜头周围看到的绿色边缘。
您称之为损坏的像素只是其中一些级别带有色度颜色并被您的键控函数捕获的像素。与选择硬0或1不同,您可以考虑一个基于像素颜色返回0到1值的函数。例如,您可以找到当前像素色调与fromHuetoHue的角度距离,然后可能执行以下操作:
// Get the distance from the edges of the range, and convert to be between 0 and 1
var distance: CGFloat
if (fromHue <= hue) && (hue <= toHue) {
    distance = min(abs(hue - fromHue), abs(hue - toHue)) / ((toHue - fromHue) / 2.0)
} else {
    distance = 0.0
}
distance = 1.0 - distance
let alpha = sin(.pi * distance - .pi / 2.0) * 0.5 + 0.5

那将使你在范围边缘和范围中心之间得到平滑的变化。(请注意,我没有处理色调在360°处包裹的事实。这是你需要处理的。) 衰减的图像如下所示:

A sine function scaled and offset so that it smoothly goes from 0 to 1 over the range 0 to 1

另外一件你可以做的事情是限制关键像素只影响饱和度高于某个阈值和值高于某个阈值的像素。对于非常暗或不饱和的颜色,你可能不想将其关键掉。例如,我认为这将有助于解决你在模型夹克上看到的问题。

看起来很复杂...我只是Swift的初学者...我该如何在我的代码中实现它? - techno
我认为他告诉了你,在你的 let hue = ... 之后添加他的代码。 - impression7vx
@user1118321,你的代码产生了错误的结果。请查看更新。 - techno
这同样无法解决我所提到的核心问题。请查看更新。 - techno
不完全与这个问题相关。但我遇到了默认的示例实现的问题,你能否请好心检查一下我的问题@user1118321?https://dev59.com/Q3sQtIcB2Jgan1znErVp - Jason Krowl
显示剩余5条评论

3
我的(实时)键控器的工作原理是这样的(使用用户1118321描述的增强功能),并且使用其分析器,我很快就注意到这很可能不是真正的绿屏图像。这是许多伪造图像之一,其中绿屏似乎已被饱和的单色绿色所取代。虽然这看起来很好,但它会引入伪影,其中键入的主体(带有最初使用的绿色边缘)与单色绿色相遇。 通过查看直方图,您可以看到只使用了一个绿色。真正的绿屏总是有(不)可见的绿色阴影。我能够获得不错的键控,但必须手动调整某些设置。使用NLE,您可能可以获得更好的结果,但它们也会更加复杂。 因此,要解决您的问题,您的代码现在可能已经起作用(更新#3),您只需要使用适当的真实绿屏图像。 输入图像描述

嗯...但是像PhotoKey8这样的应用程序在我测试的图像上运行正常。 - techno
如果你的代码不需要快速运行,那么你要么必须购买技术(好的技术都是有专利的),要么就要投入几年时间。这是一项非常迷人的技术,所以请享受它! - Mike Versteeg
@Summit 我使用了两个工具:一个在YUV领域工作,另一个在RGB领域工作,它们相互补充。这个想法是抑制前景中的关键颜色以及遮罩边缘。真正的技巧是自动化处理,使其能够适用于大多数图像,并且在我需要实时视频的情况下,让它变得更快。互联网上有足够的公共信息(如研究论文)可供学习这项美妙的技术。 - Mike Versteeg
@Summit 如果你的抑制器不起作用,那么可能是你的键控器工作不正常?很抱歉,我不能与你分享我的代码,它是我商业产品的一部分。 - Mike Versteeg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接