我有这个金属代码,我想翻译成金属核心图像内核。
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,纹理可以有像素格式,如r8)。这是正确的吗?
1条答案
按热度按时间rjee0c151#
不幸的是,没有简单的内置过滤器将图像转换为灰度。
CIPhotoEffectNoir
可以做到这一点,但它在幕后使用了颜色立方体/查找表,并且没有记录它是如何定义的。你可以使用
CIColorMatrix
来完成内核的第一部分:字符串
您可以进一步调整亮度系数以匹配您正在使用的颜色空间,尽管默认情况下Core Image将所有内容转换为扩展线性sRGB,因此这些应该是正确的。
对于强度阈值,你可能会使用
CIColorThreshold
和CIBlendWithMask
的巧妙组合,但老实说,我会为此编写一个简单的自定义颜色内核。它在运行时也应该更快。是的,Core Image始终支持4通道纹理。在仅生成单通道输出的自定义内核中,您通常在所有3个颜色通道中写入相同的值。或者,您也可以在使用
init(functionName: String, fromMetalLibraryData: Data, outputPixelFormat: CIFormat)
初始化内核时指定单通道outputPixelFormat
,例如.Rh
,但CI会在将其作为输入传递给下一个过滤器之前将其重新混合为4通道图像(除非这是一个显式处理单通道输入的处理器,但这很少见)。