提问人:Deepak Sharma 提问时间:11/7/2023 最后编辑:Deepak Sharma 更新时间:11/7/2023 访问量:47
Metal Core Image Sampler 像素格式
Metal Core Image Sampler pixel format
问:
我有这个 Metal 代码,我想将其转换为 Metal CoreImage 内核。
fragment half4 fragmentShaderThreshold ( MappedVertex in [[ stage_in ]],
texture2d<half, access::sample> inputTexture [[ texture(0) ]]
)
{
constexpr sampler s(s_address::clamp_to_edge, t_address::clamp_to_edge, min_filter::linear, mag_filter::linear);
half3 rgb = inputTexture.sample(s, in.textureCoordinate).rgb;
half3 weights = half3(0.2126, 0.7152, 0.0722);
float intensity = dot(rgb, weights);
if (intensity >= 0.95) {
rgb = half3(1.0, 0.0, 0.0);
} else if (intensity <= 0.05) {
rgb = half3(0.0, 0.0, 1.0);
}
return half4(rgb, 1.h);
}
要在 Metal Core Image 内核中做同样的事情,我认为这是可以使用内置过滤器完成的事情。因为内置滤镜可以在各种色彩空间(例如 BT.2020)中工作。请评论如何使用内置过滤器实现这一点。
如果无法使用内置滤镜,我正在考虑将图像转换为灰度并在 Metal Core Image 内核中读取强度(灰度值)。看起来 Metal Core Image 采样器仅支持基于 RGB 的像素格式(与 Metal 不同,Metal 的纹理可以具有像素格式,例如 r8)。这是对的吗?
答:
不幸的是,没有简单的内置过滤器可以将图像转换为灰度。 确实如此,但它在引擎盖下使用了一个颜色立方体/查找表,并且没有记录它是如何定义的。CIPhotoEffectNoir
你可以用它来做内核的第一部分:CIColorMatrix
let colorMatrixFilter = CIFilter.colorMatrix()
let lumaCoefficients = CIVector(x: 0.2126, y: 0.7152, z: 0.0722, w: 0.0)
colorMatrixFilter.rVector = lumaCoefficients
colorMatrixFilter.bVector = lumaCoefficients
colorMatrixFilter.gVector = lumaCoefficients
您可以进一步调整亮度系数以匹配您正在使用的色彩空间,尽管 Core Image 默认将所有内容转换为扩展的线性 sRGB,因此这些应该是正确的。
对于强度阈值,您可能可以使用一些巧妙的组合 和 ,但老实说,我会为此编写一个简单的自定义颜色内核。它在运行时也应该更快。CIColorThreshold
CIBlendWithMask
是的,Core Image 始终适用于 4 通道纹理。在仅生成单通道输出的自定义内核中,通常在所有 3 个颜色通道中写入相同的值。或者,您也可以指定一个单通道,例如在初始化内核时使用 ,但 CI 会在将其作为输入传递给下一个过滤器之前将其转回 4 通道映像(除非该处理器明确使用单通道输入,但这种情况很少见)。outputPixelFormat
.Rh
init(functionName: String, fromMetalLibraryData: Data, outputPixelFormat: CIFormat)
评论
workingColorSpace
CIColorMatrix
image.matchedFromWorkingSpace(to: bt2020ColorSpace)
(0.2126, 0.7152, 0.0722)
评论