-4

I'm currently struggling to reproduce scan appearance on an image

As discovered throw many days of work - CIFilter CIEdgeWork - is the best (but not good enough for my need) option.

original image

current result

expected image

Proof that CIColorControls isn't good option

Would be greatfull for any help.

  • Why don't you simply increase the image contrast? – Leo Dabus Apr 14 '20 at 20:00
  • You mean reduce? It's reduce also text's contrast – Artem Zinkov Apr 14 '20 at 21:06
  • https://stackoverflow.com/a/43011878/2303865 – Leo Dabus Apr 14 '20 at 21:08
  • Just get your image coreImage grayscale using the extension from the link above – Leo Dabus Apr 14 '20 at 21:15
  • Already worked with CIColorControl. Not good enough – Artem Zinkov Apr 14 '20 at 21:40
  • it is 10x better than what you have posted check my post below – Leo Dabus Apr 14 '20 at 21:46
  • I've already checked it before answering. Added result of CIColorControls usage if you don't believe me – Artem Zinkov Apr 15 '20 at 13:03
  • Why do you expect the gray around technology to became white? If you need BW image it is obvious that gray will become black. If you need to simply convert from color to grayscale and then to bitmap I can edit my post otherwise you will have to dig into color control https://www.dropbox.com/s/b93l79349cwj7av/bw%20image.jpg?dl=1 – Leo Dabus Apr 15 '20 at 17:11
  • If you don't understand I will explain. Your rectangle at the top left when converted to grayscale it has many levels of grayscale ranging from 0 at the top left part to 0.475. Post of it at around 0.4. The text "Technology" it is almost black. Note that your drawing when converted to grayscale it is not black it is grayscale at the same gray level from the rectangle around 0.4. You can't expect the code to distinguish from the rectangle's gray to your drawing's gray. – Leo Dabus Apr 15 '20 at 20:00
  • Yes, i understand this, but expected result was achieved at some point. And i wonder how can i achieve same result – Artem Zinkov Apr 16 '20 at 07:49

2 Answers2

0

It would be easier to accomplish what you want removing the image saturation and increasing its brightness and contrast. You would need to play with those values to fine tune the result to your needs:

extension String {
    static let colorControls = "CIColorControls"
}

extension UIImage {
    var coreImage: CIImage? { CIImage(image: self) }
}

extension CIImage {

    var image: UIImage? { UIImage(ciImage: self) }

    func applying(brightness: Float, contrast: Float, saturation: Float) -> CIImage? {
        applyingFilter(.colorControls,
                       parameters: [kCIInputBrightnessKey: brightness,
                                    kCIInputContrastKey: contrast,
                                    kCIInputSaturationKey: saturation])
    }

    func renderedImage() -> UIImage? {
        guard let image = image else { return nil }
        return UIGraphicsImageRenderer(size: image.size,
                                       format: image.imageRendererFormat).image { _ in
            image.draw(in: CGRect(origin: .zero, size: image.size))
        }
    }
}

Playground testing

let image = UIImage(data: try! Data(contentsOf: URL(string: "https://i.stack.imgur.com/KEZE6.jpg")!))!
if let coreImage = image.coreImage,
    let filteredImage = coreImage.applying(brightness: 0.25, contrast: 1.75, saturation: 0) {
    // use your filtered core image here
    // filteredImage
    // or get an UIImage from it
    // filteredImage.image
    // if you need to convert it to JPEG or PNG you would need to render your core image 
    // filteredImage.renderedImage()

}

enter image description here

Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
0

For those who struggle after me, the answer is CIFilter CIConvolution7X7

You want to input this values in vector which goes to your filter for key kCIInputWeightsKey

    /**
     A = 12
     B = 16
     C = 12
     D = 4
     E = 4
     F = 1
     */

    // Matrix for pixel color priority
    let weightsArr: [CGFloat] = [
        A, A, B, B, B, A, A,
        A, B, C, C, C, B, A,
        B, C, D, E, D, C, B,
        B, C, E, F, E, C, B,
        B, C, D, E, D, C, B,
        A, B, C, C, C, B, A,
        A, A, B, B, B, A, A
    ]

    let inputWeights: CIVector = CIVector(values: weightsArr,
                                          count: weightsArr.count)

enter image description here