用于图像统计的 Metal Core Image 内核

Metal Core Image kernels for Image statistics

提问人:Deepak Sharma 提问时间:11/10/2023 更新时间:11/11/2023 访问量:37

问:

我目前正在使用 Accelerate 和 Metal 着色器计算直方图、波形和矢量示波器。此代码适用于 8 位 SDR 像素缓冲区,它有效。我想使用 Core Image 重写它们,以便它们可以同时用于 10 位 HDR 和 SDR 缓冲区。

  1. Accelerate 非常适合 8 位图像的直方图。但是,它不支持 10 位 YCbCr 像素缓冲区。CoreImage 支持它,但目前尚不清楚如何从输出中获取原始直方图数据,以便使用 CoreGraphics 或 MTKView 显示它。用于显示直方图的内置直方图灵活性较低。除了 rgb 之外,我还想要亮度直方图。CIAreaHistogramCIHistogramDisplayFilter

  2. 我在 Metal 着色器中用于计算波形和矢量示波器等统计数据。似乎 Metal 核心映像内核不支持原子。有没有办法在 CoreImage 中做同样的事情?atomic_fetch_add_explicit

IOS 核心-镜像 CISoper 金属套件

评论


答:

2赞 Frank Rupprecht 11/10/2023 #1

对于直方图,我认为您有两种选择:

  1. 您可以编写自己的直方图可视化内核,类似于 Does。您可以向它传递 RGB 和亮度直方图,并根据自己的喜好对其进行可视化。CIHistogramDisplayFilter
  2. 您可以计算直方图(例如,使用 ),并将结果呈现到位图缓冲区中。然后,您可以从该缓冲区读取 bin 值,并将它们可视化为自定义 UI 组件,例如,使用 SwiftUI。在 Github 上的 CoreImageExtensions 库中,我们还提供了一些方便的 API,用于从 a 中读取值,这可能会简化此过程。CIAreaHistogramCIImage

关于原子:如果你已经为这些统计数据提供了一个有效的 Metal 实现,我建议你围绕它写一个。它正是为此目的而制作的:将自定义图像处理器包含在核心映像管道中。特别是使用 Metal 非常方便,因为您已经获得了 Metal 设备、纹理和命令缓冲区。CIImageProcessorKernel


一些细节:CIAreaHistogram

筛选器的输出是 1 像素高、宽度为 指定的图像。 指定直方图中要包含的条柱数。输出中的每个像素都包含落入相应条柱的像素百分比,由通道分隔。CIAreaHistograminputCountinputCount

例如,如果您设置为 2(即两个 bin),并且输出图像如下所示: ,这意味着所有红色值的 30% 落入第一个 bin,70% 落入第二个 bin;第一个箱中所有绿色值的 60%,第二个箱中 40 %;等等。inputCount[(0.3, 0.6, 0.2, 0.0), (0.7, 0.4, 0.8, 1.0)]

请注意,默认情况下,所有条柱中每个通道的值加起来为 1.0。但是,您可以使用参数更改该参数,以将所有值乘以因子。这是有道理的,尤其是当你有一个大 时,增加 不会因为每个 bin 可能非常小的值而损失精度。inputScaleinputCountinputScale

评论

0赞 Deepak Sharma 11/11/2023
输出的 bin 值,目前尚不清楚值的比例是多少。例如,在使用 API 时,我可以为每个颜色值获取整数频率计数。然后,我找到频率的最大值,并将每个频率值除以最大值,以将其归一化为 [0,1] 范围。目前尚不清楚如何对 Core Image 直方图输出执行相同的操作。CIAreaHistogramvImage
2赞 Frank Rupprecht 11/11/2023
我修改了我的答案,增加了一些细节。
0赞 Deepak Sharma 11/11/2023
因此,将这些数字乘以图像中的像素数将得到频率的绝对计数,对吗?
0赞 Deepak Sharma 11/11/2023
另外,如果 CIImage 中嵌入的像素缓冲区的输入像素格式是 YCbCr,我相信核心图像会在执行直方图内核之前将像素格式转换为 RGBA。这将获取 RGBA 的直方图,但 Luma 直方图呢? 如果我们以 .r8 像素格式(对于 8 位图像)将 Y 纹理作为输入传递,则可以计算亮度直方图。Core Image 似乎对此别无选择。MPSImageHistogram
0赞 Frank Rupprecht 11/13/2023
是的,直方图中的数字表示每个条柱的百分比值(如果为 1)。当您乘以像素数时,您应该得到绝对值(这里要注意浮点精度,因为 iOS 上的 CI 仅使用 16 位半浮点数)。inputScale