0

Im using the following code to detect a face from an image.

let userDirectory = FileManager.default.homeDirectoryForCurrentUser
let desktopDirectory = userDirectory.appendingPathComponent("Desktop")
let pictureUrl = desktopDirectory.appendingPathComponent("test").appendingPathExtension("jpg")

let image = CIImage(contentsOf: pictureUrl)   
let faceDetector = CIDetector(ofType: CIDetectorTypeFace, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])
let faces = faceDetector?.features(in: image!) as! [CIFaceFeature]
print("Number of faces: \(faces.count)")

How can I detect a face and save it to an NSImage?

techno
  • 6,100
  • 16
  • 86
  • 192
  • So, `CIFeature` has a `bounds` property, which defines the bounding rectangle of what was found. So the question becomes "how do you copy a portion of an image"? To which [this question](https://stackoverflow.com/questions/31254435/how-to-select-a-portion-of-an-image-crop-and-save-it-using-swift) might shed some light (personally I like the top voted answer) and then you could have a look at [How to save a UIImage to a file using UIImagePNGRepresentation](https://www.hackingwithswift.com/example-code/media/how-to-save-a-uiimage-to-a-file-using-uiimagepngrepresentation) – MadProgrammer Sep 14 '17 at 04:43
  • OSX has no UIwhatever. He also needs to convert from NSImage to CIImage and back to NSImage – Leo Dabus Sep 14 '17 at 04:57

1 Answers1

5

Xcode 9 • Swift 4

extension NSImage {
    var ciImage: CIImage? {
        guard let data = tiffRepresentation else { return nil }
        return CIImage(data: data)
    }
    var faces: [NSImage] {
        guard let ciImage = ciImage else { return [] }
        return (CIDetector(ofType: CIDetectorTypeFace, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])?
            .features(in: ciImage) as? [CIFaceFeature])?
            .map {
                let ciimage = ciImage.cropped(to: $0.bounds)  // Swift 3 use cropping(to:)
                let imageRep = NSCIImageRep(ciImage: ciimage)
                let nsImage = NSImage(size: imageRep.size)
                nsImage.addRepresentation(imageRep)
            return nsImage
        }  ?? []
    }
}

Testing

let image = NSImage(contentsOf: URL(string: "https://i.stack.imgur.com/Xs4RX.jpg")!)!
let faces = image.faces

enter image description here

Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
  • Thanks for your answer.. How can I adjust the size of the Crop window? i.e.: Get the detected face rectangle , increase the size of the rectangle and crop that portion.. Does changing `$0.bounds` with a custom rectangle help.. Please advice. – techno Sep 16 '17 at 17:35
  • @techno the answer is at the iOS question which I linked when I closed your other question. You can use `bounds.insetBy(dx: -10, dy: -10)` – Leo Dabus Sep 16 '17 at 17:36
  • 1
    Thanks a lot... :) – techno Sep 16 '17 at 17:44
  • Using `cropping.to` and `bounds.insetBy` produces incorrect results when drawing a text over detected bitmap. – techno Oct 20 '17 at 16:49
  • @techno this has nothing to do with that code. Sorry buddy but I don’t have time for that question now. – Leo Dabus Oct 20 '17 at 16:51
  • Try redrawing your image after applying the inset. this is iOS but should be really similar for macOS https://stackoverflow.com/questions/42098390/swift-png-image-being-saved-with-incorrect-orientation/42098812#42098812 – Leo Dabus Oct 20 '17 at 16:52
  • Thanks for replying even when you are Busy.Sorry,I have been pestering you because I have been stuck with this piece of code for few days.Tried everything to sort out the issue, but nothing works and no one is able to help.Should I redraw the NSImage.. can you point me to some resource .. – techno Oct 20 '17 at 16:58
  • @techno I haven’t coded for macOS for more than 2 years. Try googling it. It is easier than searching with SO search field – Leo Dabus Oct 20 '17 at 17:01
  • I have found this answer by you https://stackoverflow.com/a/42098812/848968 But this applies for `ios`.. – techno Oct 20 '17 at 17:03
  • @techno kkkk this is my own that I posted above. use it as a reference to translate to macOS – Leo Dabus Oct 20 '17 at 17:04
  • okay.. thanks ...I think I should redraw the nsimage after this `let imageRep = NSCIImageRep(ciImage: ciimage) let nsImage = NSImage(size: imageRep.size) nsImage.addRepresentation(imageRep)` .. – techno Oct 20 '17 at 17:07
  • Tried Redrawing - `nsImage.lockFocus() nsImage.draw(in: NSRect(origin: NSZeroPoint, size: nsImage.size)) nsImage.unlockFocus() ` It does not fix the issue... it seems the the whole image is shifted.. – techno Oct 20 '17 at 17:34
  • Original Image https://imgur.com/a/b5ni7 ... Saved Image after Face Detection and Drawing Text https://imgur.com/a/P86je .. Text is Drawn using this code https://stackoverflow.com/a/46844728/848968 ... Please take a look if your time permits...Thanks – techno Oct 20 '17 at 17:37