Contents

toupper/warhol

Warhol is a lightweight Swift wrapper around Apple's Vision framework for face detection on iOS. It detects face features from camera or image input, converts those positions into your coordinate space, and lets you draw or place images directly on top.

Features

  • Face detection from camera input
  • Face detection from UIImageView
  • Face feature conversion into view coordinates
  • Overlay drawing and image placement on top of landmarks

Requirements

  • iOS 12.0+
  • Swift 5.9+

Installation

Swift Package Manager

.package(url: "https://github.com/toupper/Warhol.git", from: "0.2.1")

CocoaPods

platform :ios, '12.0'
use_frameworks!

target 'MyApp' do
  pod 'Warhol', '~> 0.2'
end

Carthage

github "toupper/Warhol" ~> 0.2

Usage

From camera, draw on top

import Warhol

let cameraViewController = CameraFaceDetectionViewController()
let faceView = FaceView()
faceView.backgroundColor = .clear
cameraViewController.cameraFrontView = faceView
present(cameraViewController, animated: true)

Create a custom view conforming to CameraFrontView and draw using the incoming FaceViewModel:

import Warhol

final class FaceView: UIView, CameraFrontView {
  var viewModel: FaceViewModel?

  override func draw(_ rect: CGRect) {
    guard let context = UIGraphicsGetCurrentContext(),
          let viewModel else {
      return
    }

    context.saveGState()
    defer { context.restoreGState() }

    context.addRect(viewModel.boundingBox)
  }
}

From camera, place images on landmarks

<p align="center"> <img src="FaceLayout.jpg" width="375" alt="Face layout" /> </p>

let cameraViewController = CameraFaceDetectionViewController()

let leftEye = ImageLayout(image: UIImage(named: "leftEye")!, sizeRatio: SizeRatio(width: 1, height: 4))
let rightEye = ImageLayout(image: UIImage(named: "rightEye")!, sizeRatio: SizeRatio(width: 1, height: 4))
let nose = ImageLayout(image: UIImage(named: "nose")!)

let faceLayout = FaceLayout(
  landmarkLayouts: [
    .leftEye: leftEye,
    .rightEye: rightEye,
    .nose: nose,
  ]
)

cameraViewController.faceLayout = faceLayout
present(cameraViewController, animated: true)

You can also implement CameraFaceDetectionDelegate if you want landmark updates without drawing.

From image

Draw directly into the existing image view:

import Warhol

imageView.image = UIImage(named: "Face")
drawLandmarks(in: imageView, draw: { viewModel, context in
  // draw with CGContext
}, error: { error in
  print(error)
})

Generate a new image instead of mutating the existing one:

imageView.image = UIImage(named: "Face")
drawLandmarksInNewImage(from: imageView, draw: { viewModel, context in
  // draw with CGContext
}, completion: { newImage in
  self.newImageView.image = newImage
}, error: { error in
  print(error)
})

License

Warhol is released under the MIT license. See LICENSE for details.

Package Metadata

Repository: toupper/warhol

Default branch: master

README: README.md