如何使用 CIFilter 在 Swift 中将 UIImage 转换为灰度?

Posted

技术标签:

【中文标题】如何使用 CIFilter 在 Swift 中将 UIImage 转换为灰度?【英文标题】:How can I convert an UIImage to grayscale in Swift using CIFilter? 【发布时间】:2017-08-18 02:10:01 【问题描述】:

到目前为止,我正在为 ios 应用程序构建扫描仪组件,结果图像被裁剪并处于正确的视角。 现在我需要将彩色图像转换为黑白“扫描”文档。

我尝试使用 - “CIPhotoEffectNoir”,但它的灰度更高,然后是完全黑白的。我希望获得 100% 黑色和 100% 白色的全对比度图像。

我怎样才能做到这一点? 谢谢

【问题讨论】:

查看这篇文章可能对***.com/questions/40178846/…有帮助 我觉得你需要解释一下灰度全黑和白的区别。 @Joe 基本上给了你 CIPhotoEffectNoir - 它适用于许多情况(并且是一个非常好的答案)。但是通过使用“扫描”,您是说您需要一个阈值“钳位”值来使该像素要么黑色或白色吗?它可以做到,但只能通过 (1) 编写的自定义 CI 内核 (2) 允许硬编码或参数化的“钳位”值。 【参考方案1】:

您可以使用 CIColorControls 并设置对比度键kCIInputContrastKey 来增加黑白对比度,如下所示:

Xcode 9 • Swift 4

extension String 
    static let colorControls = "CIColorControls"


extension UIImage 
    var coreImage: CIImage?  return CIImage(image: self) 


extension CIImage 
    var uiImage: UIImage?  return UIImage(ciImage: self) 
    func applying(contrast value: NSNumber) -> CIImage? 
        return applyingFilter(.colorControls, parameters: [kCIInputContrastKey: value])
    
    func renderedImage() -> UIImage? 
        guard let image = uiImage else  return nil 
        return UIGraphicsImageRenderer(size: image.size,
                                       format: image.imageRendererFormat).image  _ in
            image.draw(in: CGRect(origin: .zero, size: image.size))
        
    


let url = URL(string: "https://i.stack.imgur.com/Xs4RX.jpg")!
do 
    if let coreImage = UIImage(data: try Data(contentsOf: url))?.coreImage,
        let increasedContrast = coreImage.applying(contrast: 1.5) 
        imageView.image = increasedContrast.uiImage
        // if you need to convert your image to data (JPEG/PNG) you would need to render the ciimage using renderedImage method on CIImage   
    
 catch 
    print(error)


要将颜色转换为灰度,您可以将饱和度键kCIInputSaturationKey 设置为零:

extension CIImage 
    func applying(saturation value: NSNumber) -> CIImage? 
        return applyingFilter(.colorControls, parameters: [kCIInputSaturationKey: value])
    
    var grayscale: CIImage?  return applying(saturation: 0) 


let url = URL(string: "https://i.stack.imgur.com/Xs4RX.jpg")!
do 
    if let coreImage = UIImage(data: try Data(contentsOf: url))?.coreImage, 
        let grayscale = coreImage.grayscale 
        // use  grayscale image here
        imageView.image = grayscale.uiImage
    
 catch  
    print(error) 

【讨论】:

它太慢了.. 有没有其他方法可以让它变快?【参考方案2】:
    Desaturate 会将您的图像转换为灰度图像 增加对比度会将这些灰色推向极端,即黑色和白色。

你可以CIColorControls:

let ciImage = CIImage(image: image)!
let blackAndWhiteImage = ciImage.applyingFilter("CIColorControls", withInputParameters: ["inputSaturation": 0, "inputContrast": 5])

原文:

使用inputContrast = 1(默认):

inputContrast = 5:

【讨论】:

【参考方案3】:

在 Swift 5.1 中,我为 OSX 编写了一个扩展方法,它也可以与 NSImage 相互转换。它使用饱和度和输入对比度来转换图像。我已经为黑白抽象了一个函数。

extension NSImage 

    func blackAndWhite () -> NSImage?
    
        return applying(saturation: 0,inputContrast: 5,image: self)
    

    func applying(saturation value: NSNumber, inputContrast inputContrastValue: NSNumber, image:NSImage) -> NSImage? 

        let ciImage = CIImage(data: image.tiffRepresentation!)!
        let blackAndWhiteImage = ciImage.applyingFilter("CIColorControls", parameters: ["inputSaturation": value, "inputContrast": inputContrastValue])
        let rep: NSCIImageRep = NSCIImageRep(ciImage: blackAndWhiteImage)
        let nsImage: NSImage = NSImage(size: rep.size)
        nsImage.addRepresentation(rep)

        return nsImage
    



【讨论】:

这个问题被标记为 iOS UIImage 而不是 NSImage

以上是关于如何使用 CIFilter 在 Swift 中将 UIImage 转换为灰度?的主要内容,如果未能解决你的问题,请参考以下文章

Swift核心图像对没有CIFilter的图像应用锐化

如何在 Swift 5 和 iOS 13 中使用 CIFilter sunbeamsGenerator?

为啥我不能在我的 Swift iOS 应用程序中使用 CIFilter 将我的图像反转回原始图像

如何将 Vignette CIFilter 应用于 iOS 中的实时摄像机源?

在 CIFilter 内核中使用归一化采样器坐标

无法使用CIFilter从CIImage中提取UIImage