OpenCVのHighGUIは手軽だが、本格的なツールを作ろうとすると不都合な点が沢山でてくる。ツールはやはり、ネイティブアプリ(Cocoa)のUIで作りたい。諸々の都合からSwiftのことは一旦置いておいて、まずはObjective-Cを使ってCocoaアプリからOpenCVの機能を使う方法についてまとめておく。
OpenCVのインストール
インストールについては、過去の記事を参照。/usr/local/Cellar/opencv以下にヘッダファイルとライブラリがインストールされ、サンプルプログラムが正常に動作しているのが前提。
プロジェクトの作成
Cocoa Applicationテンプレートを使う。Document-based Application、Use Core Dataは話がややこしくなるので、今回はオフ。他の設定は自由。
MainMenu.xib上にボタンを設置、アクションを設定する。ターゲットがAppDelegateなのは本来はあまり好ましくないが、今回は実験なのであしからず。
- (IBAction)selectImage:(id)sender { NSOpenPanel *openPanel = [NSOpenPanel openPanel]; openPanel.allowedFileTypes = @[@"jpg", @"png"]; [openPanel beginWithCompletionHandler:^(NSInteger result) { if (result == NSFileHandlingPanelOKButton) { NSString *selectedFilePath = openPanel.URL.path; NSLog(@"Selected image: %@", selectedFilePath); } }]; }
OpenCVを組み込む前に、NSOpenPanelを使って、画像ファイル(jpg or png)を選択する部分まで作って動作確認する。
OpenCVのヘッダの読み込みとリンク
結論からいうと、HighGUIを使う場合と同じ。詳細はその記事を参照。
- Build SettingsのHeader Search Pathsに「/usr/local/Cellar/opencv (recursive)」を追加するとOpenCVのヘッダーを読み込めるようになる。
- Build PhasesのLink Binary With Librariesに、使いたいOpenCVのライブラリを追加する。
CocoaからOpenCVの機能を使う実験
NSOpenPanelで指定した画像ファイルをcvLoadImageで読み込む実験をしてみる。IplImageあるいはcv::MatをCocoaの画面上に表示させるのは少し面倒なので、読み込んだ画像のサイズをログに出すことで、正しく読み込めたか確認する。
#import "SYAppDelegate.h" #include <cv.h> #include <highgui.h> @implementation SYAppDelegate ... - (IBAction)selectImage:(id)sender { NSOpenPanel *openPanel = [NSOpenPanel openPanel]; openPanel.allowedFileTypes = @[@"jpg", @"png"]; [openPanel beginWithCompletionHandler:^(NSInteger result) { if (result == NSFileHandlingPanelOKButton) { NSString *selectedFilePath = openPanel.URL.path; const char * filePath = [selectedFilePath cStringUsingEncoding:NSUTF8StringEncoding]; IplImage *image = cvLoadImage(filePath, CV_LOAD_IMAGE_COLOR); if (image != NULL) { NSLog(@"Image size: %d x %d", image->width, image->height); cvReleaseImage(&image); } else { NSLog(@"Failed to load image. %s\n%s", filePath, cvErrorStr(cvGetErrStatus())); } } }]; } @end
動作には、libopencv_coreとlibopencv_highguiが必要。読み込んだ画像のサイズ(縦横のピクセル数)が表示されれば成功。
まとめ/今後
Cocoa Applicationテンプレートでプロジェクトを作り、Command Line Toolsと同じ要領でヘッダ検索パスとライブラリのリンクの設定をすれば、CocoaからOpenCVを使える。
ただし、OpenCVのデータ構造(IplImageやcv::Mat)をCocoaのUI上に表示するには、NSImageへの変換を書かなければいけない。
また、OpenCV 2系ではインターフェイスはC++になっているので、2系のインターフェイスを使う場合はObjective-C++でアプリを書いてく必要あり。
本当は、SwiftからOpenCVを使いたい。しかし、インターフェイスがC++になっている関係で、SwiftからOpenCVを直接使うことはできない。Objective-C++でOpenCVのラッパークラスを用意して、Swift – Objective-C++のブリッジを使ってアクセスしなければいけないので、結構道のりは長い。