こんにちは、のっくんです。
今日はSwiftで画像の顔検出をやっていこうと思います。
SwiftにはVisionフレームワークが用意されています。
iOS11(2017年9月リリース)で導入されたフレームワークですが、ざっとみただけでも以下のような機能があります。
- Object Tracking、物体追跡
- Face and Body Detection、顔、体検出
- Animal Detection、動物検出
- Machine-Learning Image Analysis、マシンラーニングの画像解析
参考:https://developer.apple.com/documentation/vision
スゴイですね。こんな高機能な物が用意されているなんて。
さすがはApple。
デベロッパーとしてはとても嬉しいですね。
早速使っていこうと思います。
画像を用意する
まずは顔の写った画像を用意します。
ネットで人が写っている画像を検索して撮影、Xcodeに取り込みます。

Assetsの中にドラッグAndドロップで取り込んで適当な名前をつけます。
imageviewに表示する
画像をimageviewに表示させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. guard let image = UIImage(named: "sample1") else { return } let imageView = UIImageView(image: image) imageView.contentMode = .scaleAspectFit let scaledHeight = view.frame.width / image.size.width * image.size.height imageView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: scaledHeight) imageView.backgroundColor = .blue view.addSubview(imageView) |
ImageViewの高さと横幅を設定しています。
ImageViewの横幅はViewの横幅にします。
ImageViewの高さは「Viewの横幅/画像の横幅」で割合を求めて、その割合を画像の高さと掛け算して求めます。
顔検出をしたら四角形を表示する
続けて以下のコードを追加して顔検出をした後に顔に四角形を表示してみます。
クロージャに以下の処理を追加しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
let request = VNDetectFaceRectanglesRequest{ (req, err) in if let err = err{ print("Failed to detect:", err) return } req.results?.forEach({ (res) in guard let faceObservation = res as? VNFaceObservation else { return } print(faceObservation.boundingBox) let x = self.view.frame.width * faceObservation.boundingBox.origin.x let height = scaledHeight * faceObservation.boundingBox.height let y = scaledHeight * (1 - faceObservation.boundingBox.origin.y) - height let width = self.view.frame.width * faceObservation.boundingBox.width let redView = UIView() redView.backgroundColor = .red redView.frame = CGRect(x: x, y: y, width: width, height: height) redView.alpha = 0.4 self.view.addSubview(redView) }) } |
VNDetectFaceRectanglesRequests
をすると、顔の場所(boundingBox、x座標、y座標、高さ、横幅)が返って来ます。
しかし、VNDetectFaceRectanglesRequests
で顔検出をしているのは元の画像(UIImage)に対してなので、iPhone上の座標とは異なります。
iPhone上の座標に四角形を表示させるために、x、y、高さ、横幅を再計算しています。
ハンドラーを実行する
以上で顔検出時に実行するクロージャ内の処理が出来上がったので、あとは実行するのみです。
VNImageRequestHandler
の引数にcgImageを渡して実行します。
1 2 3 4 5 6 7 8 9 |
guard let cgImage = image.cgImage else { return } let handler = VNImageRequestHandler(cgImage: cgImage, options: [:]) do{ try handler.perform([request]) }catch let reqErr{ print("Failed to perform request", reqErr) } |
実行結果
良い感じにできていますね。
参考