Как преобразовать UIImage в оттенки серого в Swift с помощью CIFilter?

Я создаю компонент сканера для приложения iOS, пока у меня есть изображение результата, обрезанное и в правильной перспективе. Теперь мне нужно превратить цветное изображение в черно-белый «отсканированный» документ.

Я пытался использовать - "CIPhotoEffectNoir", но он больше в оттенках серого, чем полностью черно-белый. Я хочу получить полностью контрастное изображение со 100% черным и 100% белым цветом.

Как я могу этого добиться? Спасибо


person shannoga    schedule 25.03.2017    source источник
comment
Проверьте этот пост, может помочь stackoverflow.com/questions/40178846/   -  person Joe    schedule 25.03.2017
comment
Я думаю, вам нужно объяснить разницу между оттенками серого и полностью черным и белым. @Joe в основном дал вам CIPhotoEffectNoir, который работает во многих случаях (и это очень хороший ответ). Но, используя Scanned, вы говорите, что вам нужно пороговое значение фиксации, которое говорит, что этот пиксель должен быть либо черным, либо белым? Это можно сделать, но только с (1) написанным пользовательским ядром CI, которое (2) допускает либо жестко запрограммированное, либо параметризованное значение фиксации.   -  person dfd    schedule 25.03.2017


Ответы (3)


Вы можете использовать CIColorControls и установить Contrast Key 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) 
}
person Leo Dabus    schedule 25.03.2017
comment
это слишком медленно .. есть ли другой способ сделать это быстро? - person EI Captain v2.0; 03.04.2018

  1. Desaturate преобразует ваше изображение в оттенки серого.
  2. Увеличение контраста вытолкнет эти серые оттенки в крайности, то есть в черный и белый.

Вы можете CIColorControls:

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

Оригинал:

Оригинал

С inputContrast = 1 (по умолчанию):

inputContrast = 1

С inputContrast = 5:

inputContrast = 5

person Code Different    schedule 25.03.2017

В 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
    }

}

person RichIntellect    schedule 09.10.2019
comment
Этот вопрос помечен как iOS UIImage, а не NSImage - person Leo Dabus; 26.10.2019