快速使用CIImage滤镜控制黑白着色

时间:2019-05-24 00:01:01

标签: swift filter nsimage ciimage

我的代码将彩色的NSImage转换为灰度。然后将灰度转换为纯黑白图像。有没有一种方法可以创建一个可以指定如何将灰色像素转换为黑色/白色的滤镜?例如 - 1.如果像素值> 100,则将其变为黑色。 2.否则将像素变成白色。

我可以使用哪些过滤器设置来实现这一目标?

使用CIKernel自定义过滤器进行了更新:

func applyCustomCIFilter( path: String )->NSImage{
    let url = URL(fileURLWithPath: path)
    let origImage = CIImage(contentsOf: url)!

    // Convert image into grayscale
    let grayImage = CIFilter(name: "CIPhotoEffectNoir", parameters: [kCIInputImageKey: origImage])?.outputImage
    print("convert into black and white")

    // custom filter to convert light gray to white and dark gray to black
    let replaceGrayKernel = CIColorKernel( source:
        "kernel vec4 replaceGrayWithBlackOrWhite(sampler grayImage) {" +
            "if( sample(grayImage, samplerCoord(grayImage)).rgb > 0.7  ){" +
            "return vec4(0.0,0.0,0.0,1.0);" +
            "}" +
            "else" +
            "{" +
            "return vec4(1.0,1.0,1.0,1.0);" +
            "}" +
        "}"
    )

    //Apply custom filter to grayscale image. 
    //ERROR: blackAndWhiteImage is nil causing runtime failure
    let blackAndWhiteImage = replaceGrayKernel?.apply(extent: (grayImage!.extent), arguments: [grayImage as Any])

    //Convert CIImage to NSImage
    let rep = NSCIImageRep(ciImage: blackAndWhiteImage!)
    let nsImage = NSImage(size: rep.size)
    nsImage.addRepresentation(rep)

    return nsImage;
}

1 个答案:

答案 0 :(得分:0)

您的内核代码有2个错误。这是正确的代码:

let kernel = CIColorKernel( source:
    "kernel vec4 replaceGrayWithBlackOrWhite(__sample s) {" +
        "if (s.r > 0.25 && s.g > 0.25 && s.b > 0.25) {" +
        "    return vec4(0.0,0.0,0.0,1.0);" +
        "} else {" +
        "    return vec4(1.0,1.0,1.0,1.0);" +
        "}" +
    "}"
)
  • sampler__ sample的变化是因为为一次处理一个像素而优化的CIColorKernel仅传递到该像素的内核中。因此,也无需调用sample(samplerCoord())CIWarpKernelCIKernel使用sampler,当您将RIO(感兴趣区域)发送到内核时,这些内核可以访问周围的像素……请考虑模糊效果。

  • 第二个更改是if语句。 if (s.rgb > 0.7)正在将vec3(或三个浮点数)与单个浮点数进行比较。一旦校正了这些值,我就不得不尝试使用值,并认为(a)使用AND({&&)代替或OR(||)以及(b)将阈值降低到0.25可以使值更接近黑白图像。随便玩这个,看看自己想要什么。

我已经创建了一个small Swift 5 project(使用硬编码图像),并且使用了该内核。

其中没有任何注释,它包含各种扩展名(以及GLKView的子类),因为我从生产项目中收集了一些东西。除了着眼于内核代码问题外,还需对代码提出警告-它包含多个强制解开符,对于“生产就绪”代码应删除。