CIFilter 卷积将 CIImage 维度倾斜到无穷大

CIFilter convolution skews CIImage dimensions into infinity

将卷积核应用于输入图像应该会产生具有完全相同尺寸的输出图像。然而,当在 CIImage 上使用具有非零偏差的 CIFilter.convolution3x3 时,检查输出会发现宽度、高度和原点坐标已倾斜到无穷大,特别是 CGFloat.greatestFiniteMagnitude。我试过这个过滤器的 5x5 和 7x7 版本,我试过设置不同的权重和偏差,结论是一样的——如果偏差不是零,输出图像的大小和原点坐标似乎被破坏了。

此过滤器的文档是 here

这是一些代码...

// create the filter
let convolutionFilter = CIFilter.convolution3X3()
convolutionFilter.bias = 1 // any non zero bias will do

// I'll skip setting convolutionFilter.weights because the filter's default weights (an identity matrix) should be fine

// make your CIImage input
let input = CIImage(...) // I'm making mine from data I got from the camera

// lets print the size and position so we can compare it with the output
print(input.extent.width, input.extent.height, input.extent.origin) // -> 960.0 540.0 (0.0, 0.0)

// pass the input through the filter
convolutionFilter.inputImage = input
guard let output = convolutionFilter.outputImage else {
    print("the filter failed for some reason")
}

// the output image now contains the instructions necessary to perform the convolution,
// but no processing has actually occurred; even so, the extent property will have
// been updated if a change in size or position was described

// examine the output's size (it's just another CIImage - virtual, not real)
print(output.extent.width, output.extent.height, output.extent.origin) // -> 1.7976931348623157e+308 1.7976931348623157e+308 (-8.988465674311579e+307, -8.988465674311579e+307)

注意 1.7976931348623157e+308CGFloat.greatestFiniteMagnitude

这不应该发生。我可以提供的唯一其他信息是我 运行 这段代码在 iOS 13.5 上,我正在过滤的 CIImages 是从 CMSampleBuffers 抓取的 CVPixelBuffers 实例化的,这些 CVPixelBuffers 由设备的相机供稿。过滤前宽高都是960x540

虽然它似乎没有在任何地方记录,但这似乎是 @matt 建议的正常行为,尽管我不知道为什么 bias 是决定因素。总的来说,我怀疑这与 CIFilter 的卷积在处理边缘像素时必须在 外部 图像的初始边界之外进行操作有关;内核与边缘和它外面的未定义区域重叠,被视为虚拟 RGBA(0,0,0,0) 像素的无限 space。

在范围变为无穷大后,原始图像像素本身仍在其原始原点和width/height,因此您可以毫无问题地将它们渲染到具有相同原点和width/height;您用于此渲染的 CIContext 将忽略目标像素缓冲区边界之外的那些“虚拟”像素。

请记住,由于与相邻的虚拟 RGBA(0,0,0,0) 像素相互作用,您的卷积可能会在图像边缘产生意想不到的效果,让您认为渲染已经消失错误或错位的事情。通常,如果您在应用卷积之前使用 CIImage 的 clampedToExtent() 方法,则可以避免此类问题。