iPhoneでopencvを動かす

iPhoneでopencvを動かしたいと言う事で、調べてみると色々と情報が出てくるんですが、それでもハマったのでメモ書きです。先日作成したヒストグラム表示サンプルをiPhoneのシミュレータと実機で動かしてみました。

iphoneでopenCV
iphoneでopenCV

参考ページ
iPhoneでOpenCVを使う方法

手順
基本的には参考ページ様様で書かれている通りなのですが、行う手順は以下のようになります。

  1. iPhone用のライブラリを作成
  2. Xcodeに外部ライブラリの設定
  3. プログラム作成

1. iPhone用のライブラリを作成
シミュレータ用(x86)と実機用(arm)にそれぞれライブラリをコンパイルします。参考ページの「OpenCVのライブラリをソースからビルドする」の節の手順を行って下さい。面倒な場合は先ほどのページでダウンロードできるサンプルの中からコピーしても良いと思います。

2. Xcodeに外部ライブラリの設定
Xcodeでの開発に慣れてないという事もあり、ここが一番ハマりました。単純に何処で設定すれば解らなかっただけなのですけども。

設定はシミュレータ用ビルド時と、実機用ビルド時で分けて設定します。問題の設定箇所は⌥⌘Eで表示されるEdit Active Target画面にある以下の2箇所です。

  • (i) Linkig: Other Linker Flag
    ここに1で作成したライブラリファイルへのパスを追加します。例えば実機用の設定は以下のようになります。-lstdc++が無いと動きませんでした。c++を扱う為に必要なようです。

    • $(SRCROOT)/opencv_armv6/lib/libcxcore.a
    • $(SRCROOT)/opencv_armv6/lib/libcv.a
    • -lstdc++
  • (ii) Search Paths: Header Search Paths
    ここに1で作成したヘッダファイルへのパスを追加します。例えば実機用の設定は以下のようになります。

    • $(SRCROOT)/opencv_armv6/include
edit external lib paths
edit external lib paths

3. プログラム作成
1,2で設定自体は完了なので、普通にopencvを使用できるのですが、iPhoneではopencvの画像形式であるIplImageをそのままでは使えないので、UIImageやCGImage形式と相互に変換を行う必要があります。しかし、またまたありがたい事にUIImageとの変換メソッドも先ほどのページに書かれているので拝借します。

UIImage => IplImage : CreateIplImageFromUIImage
IplImage => UIImage : UIImageFromIplImage

僕はこれらのメソッドをIplImageUtil.h/mとして利用させて頂くことにしました。という事でこれらのメソッドを利用してヒストグラムサンプルを書き直してみました。

UIViewのサブクラスに実装しています。drawRect内でリソースロードとかしてますが、サンプルなので気にしません。あとヒストグラムを作成するメソッドをカラー画像の入力に対応するように修正しました。

#import "TestView.h"
#import "IplImageUtil.h"

@implementation TestView

- (void)drawRect:(CGRect)rect {
  // リソース画像ロード
  NSString* path  = [[NSBundle mainBundle] pathForResource:@"lena" ofType:@"jpg"];
  UIImage*  image = [UIImage imageWithContentsOfFile:path];
  printf("@ TestView::drawRect %p @\n", image);
  [image drawAtPoint:CGPointMake(40, 20)];

  // ロードした画像を元にヒストグラムを作成して表示する
  IplImage* iplImage     = [IplImageUtil CreateIplImageFromUIImage:image];
  IplImage* iplHistImage = [self createHistgram:iplImage size:cvSize(240, 240)];
  UIImage*  histImage    = [IplImageUtil UIImageFromIplImage:iplHistImage];
  [histImage drawAtPoint:CGPointMake(40, 260)];
}

/**
 * ヒストグラム画像作成
 */
- (IplImage*)createHistgram:(IplImage*)srcImg size:(CvSize)imageSize {
    IplImage* target = srcImg;
	IplImage* gray = NULL;

	// ターゲットがカラーの場合はグレースケールに変換
    if (target->nChannels > 1) {
	  gray = cvCreateImage(cvSize(srcImg->width, srcImg->height), IPL_DEPTH_8U, 1);
	  cvCvtColor(srcImg, gray, CV_BGR2GRAY);
	  target = gray;	  
	}
  
	// ヒストグラム作成
    int    channelSize[] = { 256 };
	float  levelRange[]  = { 0, 256 };
	float* range[]       = { levelRange };
	CvHistogram* hist    = cvCreateHist(1, channelSize, CV_HIST_ARRAY, range, 1);
	cvCalcHist(&target, hist, 0, NULL);

	// ヒストグラム出力用画像作成
	IplImage* dstImg = cvCreateImage(imageSize, IPL_DEPTH_8U, 3);
	cvSet(dstImg, cvScalarAll(255), 0);
	
	// ヒストグラムのスケール変換
	float max = 0;
	cvGetMinMaxHistValue(hist, 0, &max, 0, 0);
	cvScale(hist->bins, hist->bins, ((double)dstImg->height) / max, 0);

	// 画像に出力
	int binWidth = cvRound((double)imageSize.width / channelSize[0]);
	for (int i = 0; i < channelSize[0]; i++) {
	    int     histValue  = cvRound(cvQueryHistValue_1D(hist, i));
	    CvPoint bottomLeft = cvPoint(i * binWidth, dstImg->height);
	    CvPoint topRight   = cvPoint((i+1) * binWidth, dstImg->height - histValue);
	    cvRectangle(dstImg, bottomLeft, topRight, cvScalarAll(0), CV_FILLED, 8, 0);
	}

	// ヒストグラム破棄
	cvReleaseHist(&hist);
	if (gray) cvReleaseImage(&gray);

	return dstImg;
}

@end

他のページで.framework形式でのライブラリ作成をされている方もいるようなのですが、手元では上手く動きませんでした。Xcodeの設定方法がまずいだけの気がしますが。。

いずれにせよ、これでiPhone + opencvの環境が出来ました。opencvはサンプル見たり書いたりしてるだけで楽しいです。って現実逃避してる場合じゃないのですけども。

4 thoughts on “iPhoneでopencvを動かす”

  1. こんにちは、iPadのアプリ開発でopencvを使いたくて方法を調べてたらたどり着きました。
    手順1で述べられている、サンプルからコピーをして、手順2の設定を行うことで、
    今開発しているプロジェクトに組み込むことは可能でしょうか?
    #可能でしたら、どのファイルをコピーすればいいのか、教えてくださいmm
    opencvはテンプレートマッチングを使用する予定です。
    よろしくお願い致します。

  2. sai 様
    コメントありがとうございます。

    そうですね、想像されているように
    ライブラリファイル(.a)とヘッダファイル(.h)をコピーすれば、プロジェクトに組み込めます。
    また記事にもありますが実機向けのものと、simulator向けのものとで
    組み込むファイルが違いますので注意してくださいませ。

  3. taichinoさん、ありがとうございます。
    先ほど、勝手ながらメールを送らせて頂きました。
    ご確認お願いします。
    #こちらのコメントは削除して頂けると幸いです。

Leave a Reply

Your email address will not be published. Required fields are marked *