皆さん
今回はOpenCVの利用で耳を検証する方法をご紹介させていただきます。内容は下記となりますので、ご参考しましょう!
1. OpenCVについて
まずはOpenCV(Open Source Computer Vision Library)については簡単に説明します。OpenCVとはインテルが開発・公開したオープンソースのコンピュータビジョン向けライブラリ(Wikipedia)
2. 「Haar Cascade」の方法でオブジェクトを検出する。
オブジェクト検出はいくつ方法がありますが、今回は「Haar Cascade」という方法を利用します。ただ、「Haar Cascade」については、知識がかなり多いですが、簡単に説明させていただきます。
その方法は、オブジェクトの画像から特徴量を抽出して、それぞれの特徴量は単一の数値であり、黒の矩形の位置の画素の輝度の合計から白の矩形の位置の画素の輝度の合計を差し引いたものです。そのあとは一杯の画像からトレーニングして、結果XMLファイルを作成します。
詳しくはこのリンクをご参考ください。
※このブログ内容の限り、結果XMLファイルの作成方法を話しないです。利用方法のみ紹介します。
3. OpenCVをSwiftのプロジェクトに組み込む
- まずはOpenCVページからiOSのOpenCVライブラリをダウンロードして、プロジェクトにインポートします。
- もともとSwiftがOpenVCライブラリーのFunctionを直接にコールできないので、「Bridging header」を作成する必要があります。ソースコードで「OpenCVWrapper.h」と「OpenCVWrapper.mm」を作成します。
#import <Foundation/Foundation.h> @interface OpenCVWrapper : NSObject //Get OpenCV version +(NSString *) openCVVersionString; @end
#import "opencv2/opencv.hpp" #import "OpenCVWrapper.h" +(NSString *) openCVVersionString { return [NSString stringWithFormat:@"OpenCV Version %s", CV_VERSION]; } @end
- SwiftのソースコードでWrapperのFunctionをコールできるようになりました。
@IBOutlet weak var openCVVersionLbl: UILabel! override func viewDidLoad() { super.viewDidLoad() openCVVersionLbl.text = OpenCVWrapper.openCVVersionString() }
4. 「Haar Cascade」のXML結果ファイルで耳検出機能を実装します。
左耳と右耳の特徴が違いますので、2ファイルが必要です。”haarcascade_rightear.xml”と”haarcascade_leftear.xml”になります。そのファイルを読んで、耳の画像から耳を検出します。
var detector:OpenCVWrapper! @IBAction func detectEar(_ sender: Any) { detector.setXML("haarcascade_leftear.xml") imageView.image = UIImage(named: "leftear.jpg") if (detector.isActive()) { let arr = NSMutableArray() detector.detect(imageView.image,founds: arr) print(arr.count) UIGraphicsBeginImageContext(imageView.image!.size); imageView.image!.draw(in: CGRect(x: 0,y: 0,width: imageView.image!.size.width,height: imageView.image!.size.height)) let context: CGContext = UIGraphicsGetCurrentContext()! context.setStrokeColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0) context.setLineWidth(5.0); for i in 0..<(arr.count/4) { let x:Int = arr[i * 4 + 0] as! NSNumber as Int let y:Int = arr[i * 4 + 1] as! NSNumber as Int let w:Int = arr[i * 4 + 2] as! NSNumber as Int let h:Int = arr[i * 4 + 3] as! NSNumber as Int print("\(i): \(x) \(y) \(w) \(h)") context.addRect(CGRect(x: CGFloat(x),y: CGFloat(y),width: CGFloat(w),height: CGFloat(h))); } context.strokePath() let img = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() imageView.image = img; } }
結果はこんな感じになりますね。