【问题标题】:Alpha blending for frame averaging in Core Image核心图像中帧平均的 Alpha 混合
【发布时间】:2021-12-21 07:57:42
【问题描述】:

在我的应用程序中,我试图实现一种运动模糊功能,它将来自视频输出的不同帧(平均它们)堆叠成单个图像。我试图获得的效果在这里得到了很好的解释:https://photographylife.com/image-averaging-technique

我尝试使用自定义 CIKernel 对每个颜色通道执行平均操作,如下所示:

float4 makeAverage(sample_t currentStack, sample_t newImage, float stackCount) {
          
          float4 cstack = unpremultiply(currentStack);
          float4 nim = unpremultiply(newImage);
          float4 avg = ((cstack * stackCount) + nim) / (stackCount + 1.0);
          
          return premultiply(avg);
          
      }

您可以在此处找到有关完整代码的更多详细信息:Problems with frame averaging with Core Image

它可以工作,但过了一会儿,图像中开始出现奇怪的补丁,暗示颜色通道正在剪切。

有没有一种方法可以在核心图像中使用 alpha 混合来实现相同的结果?也许,不是在颜色通道上进行堆叠操作,我可以堆叠具有递减 alpha 值的后续图像吗?

如果是这样,执行此操作的程序/算法是什么?

【问题讨论】:

    标签: swift avfoundation core-image


    【解决方案1】:

    您可以通过 CIColorMatrix 和 CISourceOverCompositing 的组合以更简单的方式完成与您正在做的相同的事情,只需使用像这样的 CIMix 过滤器

        func makeCompositeImage(stackImage: CIImage, newImage: CIImage?, count: Double) -> CIImage {
            let opacity = 1.0 / count
            return newImage?
                .applyingFilter("CIMix", parameters: [
                    kCIInputBackgroundImageKey: stackImage,
                    kCIInputAmountKey: opacity
                ]) ?? stackImage
        }
    

    请查看我刚刚发布的这个应用程序:https://apps.apple.com/us/app/filter-magic/id1594986951。它可以让你玩弄每一个过滤器。

    【讨论】:

    • 恭喜您的应用!我刚刚下载了它,它看起来很棒!一个很好的工具来探索核心图像过滤器,绝对需要!感谢您提供有关 CIMix 过滤器的提示!
    • @Salvo89 谢谢!让我很高兴您发现我的应用程序很有用。对此进行了大量的研究和实验。很高兴与社区分享。享受吧!
    【解决方案2】:

    经过一番尝试,我找到了解决方案。基本上,这里是如何达到预期的效果:

    我使用 CIColorMatrix 滤镜降低每个连续帧的不透明度。函数代码如下:

    func setOpacity (image : CIImage, alpha : Double) ->CIImage {
    
    guard let overlayFilter: CIFilter = CIFilter(name: "CIColorMatrix") else { fatalError() }
    let overlayRgba: [CGFloat] = [0, 0, 0, alpha]
    let alphaVector: CIVector = CIVector(values: overlayRgba, count: 4)
    overlayFilter.setValue(image, forKey: kCIInputImageKey)
    overlayFilter.setValue(alphaVector, forKey: "inputAVector")
    
    return overlayFilter.outputImage!
    

    }

    每帧到达时,alpha 值计算为 1/count。然后,我使用 CISourceOverCompositing 过滤器执行 alpha 混合:

    func makeCompositeImage(stackImage: CIImage?, newImage: CIImage?, count: Double) -> CIImage {
        
        let bgImage = stackImage
        
        let opacity = 1.0 / count
        
        let newImageFiltered = setOpacity(image: newImage!, alpha: opacity)
        // Filter part
        let currentFilter = CIFilter(name: "CISourceOverCompositing")
        currentFilter?.setValue(newImageFiltered, forKey: kCIInputImageKey)
        currentFilter?.setValue(bgImage, forKey: kCIInputBackgroundImageKey)
        guard let outputImage = currentFilter?.outputImage else { return bgImage!}
        
        return outputImage
    }
    

    该方法按预期工作,我可以模拟连续帧的运动模糊。但是,最初的问题仍然存在,一段时间后,图像中开始出现明显的色带和色块,从而破坏了最终结果。

    不过,我希望上面的代码对某些人有用。

    【讨论】:

    • “但是,最初的问题仍然存在,一段时间后,图像中开始出现明显的色带和色块,破坏了最终结果。”那为什么这是一个问题的答案呢?
    • 因为问题专门针对如何在 Core Image 中进行帧平均的 alpha 混合。正如我在这里所写:“有没有一种方法可以在核心图像中使用 alpha 混合来实现相同的结果?”在这里:“如果是这样,那么做它的程序/算法是什么?”并在标题中。该代码允许您进行 alpha 混合以实现运动模糊,所以我认为它对某人有用。
    猜你喜欢
    • 2013-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-20
    • 2012-04-05
    • 1970-01-01
    • 1970-01-01
    • 2015-01-08
    相关资源
    最近更新 更多