2

我想使用基于金属的自定义卷积处理图像,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()))时,结果如下所示:<a href="https://i.stack.imgur.com/SLGkq.jpg" rel="nofollow noreferrer">在此处输入图像描述

现在,如果我像这样在过滤器中执行实际卷积(中间像素周围的样本像素)

float4 testKernel(sampler src, destination dest) {
    return src.sample(src.transform(dest.coord() + float2(1,1)));
}

结果突然变成了这样: 在此处输入图像描述</p>

正如您所看到的,在混合时突然向图像添加了一些clamp-to-extend 行为,即使它的extend 仍然是inputImage.

我观察到 Apple 的卷积过滤器返回一个更大的输出图像,其中还包含一个光环区域,具体取决于过滤器参数。所以我玩了很多,发现如果我告诉内核渲染到更大的范围并在之后裁剪它,混合再次按预期工作:

let output = self.kernel.apply(extent: inputExtent.insetBy(dx: -1, dy: -1),
                          roiCallback: roiCallback,
                            arguments: [inputImage])
return output.cropped(to: inputExtent)

似乎混合滤镜以某种方式尝试对图像范围之外的像素进行采样,以确定如何填充空白空间。默认情况下这应该是透明的,但似乎单独的卷积操作会增加一些钳位到边缘的行为,即使我没有更改结果范围。

有谁知道这是否是一个错误和/或将自定义卷积过滤器与组合相结合的最佳方法是什么?

4

0 回答 0