Core Imageを使用したiOSでの顔検出

Core Imageは、Cocoa Touchに組み込まれている強力なAPIです。 これはiOS SDKの重要な部分です。 しかし、彼女はしばしば見落とされています。 この記事では、顔検出の可能性と、iOSアプリケーションでこのテクノロジーを使用する方法を検討します!







このチュートリアルでは何をしますか?



iOSの顔認識は、5回目のリリース(2011年頃)からかなり前に登場しましたが、この機能はしばしば見落とされていました。 顔検出APIを使用すると、開発者は顔を認識するだけでなく、笑顔の存在、人が目をまばたきするかどうかなど、特定のプロパティを確認することもできます。



まず、写真内の顔を認識し、それを特別なフレームで囲む​​アプリケーションを作成することにより、Core Imageフレームワークを使用した顔検出の技術を研究します。 2番目の例では、ユーザーが写真を撮り、顔が存在するかどうかを検出し、ユーザーの顔の座標を取得できるアプリケーションを作成することにより、より詳細な使用方法を検討します。 したがって、iOSでの顔認識と、見過ごされがちな強力なAPIを使用する原則について、できる限り学習します。 さあ、行こう!



プロジェクトのセットアップ



こちらのリンクからスタータープロジェクトをダウンロードし、Xcodeで開きます。 ご覧のとおり、IBOutletをImageViewに接続した非常にシンプルなコントローラー。







Core Imageを使用して顔検出を開始するには、Core Imageライブラリをインポートする必要があります。 ViewController.swiftファイルを参照し、上部に次のコードを貼り付けます。



import CoreImage
      
      





コア画像を使用した顔検出



スタータープロジェクトでは、IBOutletとしてコードに接続されたImageViewがあります。 次に、顔認識のためのコードを実装する必要があります。 次のコードをプロジェクトに貼り付けて、より詳細に検討します。



 func detect() { guard let personciImage = CIImage(image: personPic.image!) else { return } let accuracy = [CIDetectorAccuracy: CIDetectorAccuracyHigh] let faceDetector = CIDetector(ofType: CIDetectorTypeFace, context: nil, options: accuracy) let faces = faceDetector.featuresInImage(personciImage) for face in faces as! [CIFaceFeature] { print("Found bounds are \(face.bounds)") let faceBox = UIView(frame: face.bounds) faceBox.layer.borderWidth = 3 faceBox.layer.borderColor = UIColor.redColor().CGColor faceBox.backgroundColor = UIColor.clearColor() personPic.addSubview(faceBox) if face.hasLeftEyePosition { print("Left eye bounds are \(face.leftEyePosition)") } if face.hasRightEyePosition { print("Right eye bounds are \(face.rightEyePosition)") } } }
      
      





ここで何が起こっているのか:





viewDidLoadでdetect()メソッドを呼び出します。 そのため、次のコード行をメソッドに貼り付けます。



 detect()
      
      





アプリケーションを起動します。 次のようなものが表示されます。







xCodeコンソールには、検出された顔の座標が表示されます。



 Found bounds are (177.0, 415.0, 380.0, 380.0)
      
      





現在の例では考慮しなかったいくつかのニュアンスがあります。









次に、detect()メソッドを次のコードに置き換えます。



 func detect() { guard let personciImage = CIImage(image: personPic.image!) else { return } let accuracy = [CIDetectorAccuracy: CIDetectorAccuracyHigh] let faceDetector = CIDetector(ofType: CIDetectorTypeFace, context: nil, options: accuracy) let faces = faceDetector.featuresInImage(personciImage) //    let ciImageSize = personciImage.extent.size var transform = CGAffineTransformMakeScale(1, -1) transform = CGAffineTransformTranslate(transform, 0, -ciImageSize.height) for face in faces as! [CIFaceFeature] { print("Found bounds are \(face.bounds)") //     faceBox var faceViewBounds = CGRectApplyAffineTransform(face.bounds, transform) let viewSize = personPic.bounds.size let scale = min(viewSize.width / ciImageSize.width, viewSize.height / ciImageSize.height) let offsetX = (viewSize.width - ciImageSize.width * scale) / 2 let offsetY = (viewSize.height - ciImageSize.height * scale) / 2 faceViewBounds = CGRectApplyAffineTransform(faceViewBounds, CGAffineTransformMakeScale(scale, scale)) faceViewBounds.origin.x += offsetX faceViewBounds.origin.y += offsetY let faceBox = UIView(frame: faceViewBounds) faceBox.layer.borderWidth = 3 faceBox.layer.borderColor = UIColor.redColor().CGColor faceBox.backgroundColor = UIColor.clearColor() personPic.addSubview(faceBox) if face.hasLeftEyePosition { print("Left eye bounds are \(face.leftEyePosition)") } if face.hasRightEyePosition { print("Right eye bounds are \(face.rightEyePosition)") } } }
      
      





上記のコード変更はコメントで強調表示されます。









顔認識を使用したカメラアプリケーションの作成



写真を撮るカメラアプリケーションがあると想像してみましょう。 写真がキャプチャされるとすぐに、顔認識機能を開始して、写真に顔があるかどうかを判断します。 人がいる場合、この写真をいくつかのタグなどで分類できます。 これを行うには、UIImagePickerクラスと統合し、写真の撮影後に顔認識コードを実行する必要があります。

スタータープロジェクトでは、CameraViewControllerクラスを既に作成しました。 コードを更新してカメラ機能を実装します。



 class CameraViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate { @IBOutlet var imageView: UIImageView! let imagePicker = UIImagePickerController() override func viewDidLoad() { super.viewDidLoad() imagePicker.delegate = self } @IBAction func takePhoto(sender: AnyObject) { if !UIImagePickerController.isSourceTypeAvailable(.Camera) { return } imagePicker.allowsEditing = false imagePicker.sourceType = .Camera presentViewController(imagePicker, animated: true, completion: nil) } func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) { if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage { imageView.contentMode = .ScaleAspectFit imageView.image = pickedImage } dismissViewControllerAnimated(true, completion: nil) self.detect() } func imagePickerControllerDidCancel(picker: UIImagePickerController) { dismissViewControllerAnimated(true, completion: nil) } }
      
      





この関数の最初の数行は、UIImagePickerデリゲートを設定します。 didFinishPickingMediaWithInfoメソッド(これはUIImagePickerデリゲートメソッドです)で、imageViewのメソッドで受け取った画像を設定します。 次に、ピッカーのdismissを呼び出して、検出関数を呼び出します。



検出機能はまだ実装されていません。 次のコードを貼り付けて、よく見てください。



 func detect() { let imageOptions = NSDictionary(object: NSNumber(int: 5) as NSNumber, forKey: CIDetectorImageOrientation as NSString) let personciImage = CIImage(CGImage: imageView.image!.CGImage!) let accuracy = [CIDetectorAccuracy: CIDetectorAccuracyHigh] let faceDetector = CIDetector(ofType: CIDetectorTypeFace, context: nil, options: accuracy) let faces = faceDetector.featuresInImage(personciImage, options: imageOptions as? [String : AnyObject]) if let face = faces.first as? CIFaceFeature { print("found bounds are \(face.bounds)") let alert = UIAlertController(title: "Say Cheese!", message: "We detected a face!", preferredStyle: UIAlertControllerStyle.Alert) alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil)) self.presentViewController(alert, animated: true, completion: nil) if face.hasSmile { print("face is smiling"); } if face.hasLeftEyePosition { print("Left eye bounds are \(face.leftEyePosition)") } if face.hasRightEyePosition { print("Right eye bounds are \(face.rightEyePosition)") } } else { let alert = UIAlertController(title: "No Face!", message: "No face was detected", preferredStyle: UIAlertControllerStyle.Alert) alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil)) self.presentViewController(alert, animated: true, completion: nil) } }
      
      





detect()関数は、以前の実装と非常によく似ています。 ただし、今回は、キャプチャした画像で使用します。 顔が検出されると、「顔を検出しました!」という警告メッセージが表示されます。そうでない場合は、「顔がありません!」というメッセージが表示されます。 アプリケーションを起動し、作業をテストします。







CIFaceFeatureには、既に説明したいくつかのプロパティとメソッドがあります。 たとえば、発見を実行したい場合、人が笑顔になった場合、ブール値を返す.hasSmileを呼び出すことができます。 実験では、.hasLeftEyePositionを呼び出して、左目が存在するかどうかを確認します(そうすることを期待しましょう)。



hasMouthPositionを呼び出して、口が存在するかどうかを確認することもできます。 口が存在する場合、以下に示すように、mouthPositionプロパティを使用して座標にアクセスできます。



 if (face.hasMouthPosition) { print("mouth detected") }
      
      





ご覧のとおり、顔の特徴の検出はCore Imageを使用すると非常に簡単です。 口、笑顔、目の位置を検出するだけでなく、左目に対してleftEyeClosedを、右目に対してrightEyeClosedを呼び出すことで、目が開いているか閉じているかを確認することもできます。



そして結論として



この記事では、APIを使用した顔検出機能、Core Image APIのコアイメージ、およびカメラアプリケーションでそれらを使用する方法について説明しました。 メインのUIImagePickerを使用して、写真を撮影し、画像に存在する顔を検出します。



ご覧のとおり、コアイメージCore Imageを使用した顔検出は、多くのアプリケーションとともに強力なAPIです! このチュートリアルが、このあまり知られていないiOS用APIの有用で有益なガイドであることが、この記事でわかることを願っています!



»最終的な最終プロジェクトはこちらからダウンロードできます。



All Articles