Core Image 中用于帧平均的 Alpha 混合
Alpha blending for frame averaging in Core Image
在我的应用程序中,我试图实现一种运动模糊功能,该功能可将来自视频输出的不同帧(对其进行平均)堆叠到单个图像中。我试图获得的效果在这里得到了很好的解释: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 值的后续图像吗?
如果是这样,procedure/algorithm 会怎么做?
经过一番尝试,我找到了解决办法。基本上,这是达到预期效果的方法:
我使用 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/计数。然后,我使用 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
}
该方法按预期工作,我可以模拟连续帧的运动模糊。然而,最初的问题仍然存在,一段时间后,图像中开始出现明显的色带和色块,破坏了最终结果。
不过,我希望上面的代码对某些人有用。
您可以通过像这样使用 CIMix 过滤器以更简单的方式组合 CIColorMatrix 和 CISourceOverCompositing 来完成与您正在做的相同的事情
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。它可以让你玩弄每一个过滤器。
在我的应用程序中,我试图实现一种运动模糊功能,该功能可将来自视频输出的不同帧(对其进行平均)堆叠到单个图像中。我试图获得的效果在这里得到了很好的解释: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 值的后续图像吗?
如果是这样,procedure/algorithm 会怎么做?
经过一番尝试,我找到了解决办法。基本上,这是达到预期效果的方法:
我使用 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/计数。然后,我使用 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
}
该方法按预期工作,我可以模拟连续帧的运动模糊。然而,最初的问题仍然存在,一段时间后,图像中开始出现明显的色带和色块,破坏了最终结果。
不过,我希望上面的代码对某些人有用。
您可以通过像这样使用 CIMix 过滤器以更简单的方式组合 CIColorMatrix 和 CISourceOverCompositing 来完成与您正在做的相同的事情
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。它可以让你玩弄每一个过滤器。