You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Metal片段着色器转Metal CoreImage内核:内置滤镜实现及采样器格式咨询

将Metal片段着色器转换为CoreImage内核的方案

一、用CoreImage内置滤镜实现需求

你的需求是基于BT.709权重(0.2126、0.7152、0.0722为BT.709亮度系数)计算亮度,再按阈值替换颜色,完全可以通过内置滤镜组合实现,无需自定义内核:

步骤拆解

  1. 生成亮度图
    使用CIColorMatrix滤镜,将RGB通道按BT.709权重转换为灰度值:
CIFilter *colorMatrix = [CIFilter filterWithName:@"CIColorMatrix"];
[colorMatrix setValue:inputImage forKey:kCIInputImageKey];
// 矩阵参数:[R通道系数, G通道系数, B通道系数, 0, 0,
//           R通道系数, G通道系数, B通道系数, 0, 0,
//           R通道系数, G通道系数, B通道系数, 0, 0,
//           0, 0, 0, 1, 0]
[colorMatrix setValue:[CIVector vectorWithValues:(CGFloat[]){0.2126, 0.7152, 0.0722, 0, 0,
                                                             0.2126, 0.7152, 0.0722, 0, 0,
                                                             0.2126, 0.7152, 0.0722, 0, 0,
                                                             0, 0, 0, 1, 0} count:20] forKey:@"inputMatrix"];
CIImage *luminanceImage = colorMatrix.outputImage;
  1. 创建阈值遮罩
    用CIColorThreshold分别生成高、低亮度区域的遮罩:
  • 高亮度遮罩(亮度≥0.95):
CIFilter *highThreshold = [CIFilter filterWithName:@"CIColorThreshold"];
[highThreshold setValue:luminanceImage forKey:kCIInputImageKey];
[highThreshold setValue:@0.95 forKey:@"inputThreshold"];
CIImage *highMask = highThreshold.outputImage;
  • 低亮度遮罩(亮度≤0.05):
CIFilter *lowThreshold = [CIFilter filterWithName:@"CIColorThreshold"];
[lowThreshold setValue:luminanceImage forKey:kCIInputImageKey];
[lowThreshold setValue:@0.05 forKey:@"inputThreshold"];
// 反转遮罩,保留阈值以下的区域
CIFilter *invertLow = [CIFilter filterWithName:@"CIColorInvert"];
[invertLow setValue:lowThreshold.outputImage forKey:kCIInputImageKey];
CIImage *lowMask = invertLow.outputImage;
  1. 合成颜色替换效果
    用CIBlendWithMask将红、蓝色分别合成到原图对应区域:
  • 生成纯色图并裁剪到原图尺寸:
CIImage *redImage = [CIImage imageWithColor:[CIColor colorWithRed:1 green:0 blue:0 alpha:1]];
redImage = [redImage imageByCroppingToRect:inputImage.extent];

CIImage *blueImage = [CIImage imageWithColor:[CIColor colorWithRed:0 green:0 blue:1 alpha:1]];
blueImage = [blueImage imageByCroppingToRect:inputImage.extent];
  • 先合成红色区域:
CIFilter *blendRed = [CIFilter filterWithName:@"CIBlendWithMask"];
[blendRed setValue:inputImage forKey:kCIInputImageKey];
[blendRed setValue:redImage forKey:@"inputBackgroundImage"];
[blendRed setValue:highMask forKey:@"inputMaskImage"];
CIImage *tempImage = blendRed.outputImage;
  • 再合成蓝色区域:
CIFilter *blendBlue = [CIFilter filterWithName:@"CIBlendWithMask"];
[blendBlue setValue:tempImage forKey:kCIInputImageKey];
[blendBlue setValue:blueImage forKey:@"inputBackgroundImage"];
[blendBlue setValue:lowMask forKey:@"inputMaskImage"];
CIImage *finalImage = blendBlue.outputImage;

如果要支持BT.2020色彩空间,只需把CIColorMatrix的权重换成BT.2020系数(0.2627, 0.6780, 0.0593)即可,其余步骤完全一致。

二、自定义CoreImage内核实现(若不用内置滤镜)

如果需要自定义内核,对应的Metal代码如下:

#include <CoreImage/CoreImage.h>

kernel vec4 thresholdKernel(sampler inputImage) {
    vec2 coord = samplerCoord(inputImage);
    vec3 rgb = sample(inputImage, coord).rgb;
    vec3 weights = vec3(0.2126, 0.7152, 0.0722);
    float intensity = dot(rgb, weights);

    if (intensity >= 0.95) {
        rgb = vec3(1.0, 0.0, 0.0);
    } else if (intensity <= 0.05) {
        rgb = vec3(0.0, 0.0, 1.0);
    }

    return vec4(rgb, 1.0);
}

对比原片段着色器,CoreImage内核语法更简洁:无需顶点输入,直接用sampler类型参数,通过samplerCoord获取纹理坐标、sample函数采样。

三、关于CoreImage采样器的像素格式问题

CoreImage采样器并非仅支持RGB类格式,它支持包括单通道灰度格式(如kCIFormatR8、kCIFormatR16Half等)在内的多种像素格式。处理灰度图时,可直接将灰度CIImage传入自定义内核,采样后读取r通道即为亮度值,示例代码:

kernel vec4 grayThresholdKernel(sampler grayImage) {
    vec2 coord = samplerCoord(grayImage);
    float intensity = sample(grayImage, coord).r;

    vec3 rgb;
    if (intensity >= 0.95) {
        rgb = vec3(1.0, 0.0, 0.0);
    } else if (intensity <= 0.05) {
        rgb = vec3(0.0, 0.0, 1.0);
    } else {
        rgb = vec3(intensity); // 保留原灰度
    }

    return vec4(rgb, 1.0);
}

注意:用内置滤镜生成的灰度图默认是RGB格式(三通道值相同),若要得到单通道灰度图,需在创建CIContext时指定输出格式,或用CIColorMatrix合并通道后转换格式。

内容的提问来源于stack exchange,提问作者Deepak Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 01:42:50