我想使用自定义的基于金属的卷积CIKernel
处理图像,并将结果与其他图像混合成一个构图。
但是在混合过程中,我观察到了奇怪的剪切行为:
为了说明这一点,我创建了一个简单的构图,如下所示:
let inputImage = CIImage(image: inputImage)
let filter = MyCustomFilter()
filter.setValue(inputImage, forKey: kCIInputImageKey)
let filteredImage = filter.outputImage!.transformed(by: .init(translationX: 360, y: 300))
let background = CIImage(color: .white).cropped(to: CGRect(origin: .zero, size: CGSize(width: 1500, height: 1000)))
let composedImage = filteredImage.composited(over: background)
当MyCustomFilter
不执行任何操作(return src.sample(src.coord())
)时,结果如下所示:

现在,如果我像这样在滤镜中执行实际的卷积(中间像素周围的采样像素)
float4 testKernel(sampler src, destination dest) {
return src.sample(src.transform(dest.coord() + float2(1,1)));
}
您可以看到,混合时图像上突然出现了一些钳位到扩展的行为,即使它的扩展仍然是inputImage
的扩展。
我观察到,苹果的卷积滤镜会返回较大的输出图像,该图像也包含一个取决于滤镜参数的光晕区域。因此,我进行了很多次尝试,发现如果我告诉内核将其渲染成更大的扩展并在之后进行裁剪,则混合将再次按预期进行:
let output = self.kernel.apply(extent: inputExtent.insetBy(dx: -1, dy: -1),
roiCallback: roiCallback,
arguments: [inputImage])
return output.cropped(to: inputExtent)
似乎混合滤镜以某种方式尝试对图像范围之外的像素进行采样,以确定如何填充空白。默认情况下,该 应该是透明的,但是即使我不更改结果范围,表面上看,仅卷积运算似乎也会增加一些钳到边缘的行为。
有人知道这是否是错误,和/或将自定义卷积过滤器与合成结合起来的最佳方法是什么?