6

I'm using CoreImage Framework for detecting Business Card. When I detect a rectangle (CIDetectorTypeRectangle) I draw an overlay using this method:

    func drawOverlay(image: CIImage, topLeft: CGPoint, topRight: CGPoint, bottomLeft: CGPoint, bottomRight: CGPoint) -> CIImage {

    var overlay = CIImage(color: CIColor(red: 0, green: 0, blue: 1.0, alpha: 0.3))
    overlay = overlay.imageByCroppingToRect(image.extent())
    overlay = overlay.imageByApplyingFilter("CIPerspectiveTransformWithExtent",
      withInputParameters: [
        "inputExtent": CIVector(CGRect: image.extent()),
        "inputTopLeft": CIVector(CGPoint: topLeft),
        "inputTopRight": CIVector(CGPoint: topRight),
        "inputBottomLeft": CIVector(CGPoint: bottomLeft),
        "inputBottomRight": CIVector(CGPoint: bottomRight)
      ])
    return overlay.imageByCompositingOverImage(image)
  }

Now I need to take automatically a picture of the selected area and save it. Does anyone know how to do it? Thanks!

Michael Dautermann
  • 88,797
  • 17
  • 166
  • 215
Ale
  • 2,282
  • 5
  • 38
  • 67
  • 1
    Use CGImageCreateWithImageInRect to crop it to the exact portion that you want – Sandeep Oct 23 '14 at 11:27
  • Thanks for question! Now I know how to crop CIImage in Swift. Google rejected to help so did Apple's site. I tried to use filters when you can easily call the method imageByCroppingToRect :) – alexsalo Dec 19 '14 at 19:46

1 Answers1

1

I have found the solution!

func cropBusinessCardForPoints(image: CIImage, topLeft: CGPoint, topRight: CGPoint, bottomLeft: CGPoint, bottomRight: CGPoint) -> CIImage {

        var businessCard: CIImage
        businessCard = image.imageByApplyingFilter("CIPerspectiveTransformWithExtent",
            withInputParameters: [
                "inputExtent": CIVector(CGRect: image.extent()),
                "inputTopLeft": CIVector(CGPoint: topLeft),
                "inputTopRight": CIVector(CGPoint: topRight),
                "inputBottomLeft": CIVector(CGPoint: bottomLeft),
                "inputBottomRight": CIVector(CGPoint: bottomRight)
            ])
        businessCard = image.imageByCroppingToRect(businessCard.extent())

        return businessCard
    }

Usage:

//Variables
    var context: CIContext!
    var orientation: UIImageOrientation = UIImageOrientation.Right



override func viewDidLoad() {
        super.viewDidLoad()

        //Initialize the CIContext
        context = CIContext(options:nil)

        ...
}

When a rectangle is detected:

//...

let businessCardImage = cropBusinessCardForPoints(image, topLeft: feature.topLeft, topRight: feature.topRight, bottomLeft: feature.bottomLeft, bottomRight: feature.bottomRight)

//Convert CIImage to CGImage
let cgimg = context.createCGImage(businessCardImage, fromRect: businessCardImage.extent())

//Convert CGImage to UIImage
let newImage = UIImage(CGImage: cgimg, scale:1, orientation: orientation)
Ale
  • 2,282
  • 5
  • 38
  • 67
  • 1
    Not sure if you're doing this, but if you want Core Image to straighten out the image as well, you can use the CIPerspectiveCorrection filter. Works great. – Matt Long Jun 04 '15 at 05:55
  • @Ale What is feature in your solution? – Alok Nair Nov 05 '15 at 10:39
  • But this crops to rectangle. Any idea how to crop to feature points ? @AlokNair feature is the detected object from CIDetector. – Amr Hossam May 30 '16 at 13:53