LoginSignup
102
98

More than 5 years have passed since last update.

iOS で opencv を使う。

Last updated at Posted at 2014-06-21

評価環境

  • xcode5
  • opencv 2.4.9

opencv のダウンロード

http://opencv.org/downloads.html
以下から framework をダウンロードします。
スクリーンショット 2014-06-21 20.47.43.png

framework を利用すると非常に簡単に組み込めます。
その一方、framework作成時のコンパイラ設定とプロジェクトのコンパイラ設定が異なるとビルドできないこともあります。
自分でビルドすれば、コンパイラの設定違いに悩まされることはないです。
少なくともこの記事の記載時点では、特にプロジェクトのデフォルトの設定から変える必要はありません。

xcode でプロジェクトから参照する

プロジェクトでフレームワークを追加します。
先ほどダウンロードしたフレームワークを指定します。

スクリーンショット 2014-06-21 18.00.24.png

ソースを .mm にする

opencv の c++ ライブラリを使うので、ソースを .mm にします。
これで objective-c と c++ の混在ができます。
スクリーンショット 2014-06-21 20.58.21.png

ヘッダをインポートします

// .mm ファイル

// opencv の import
#import <opencv2/opencv.hpp>
#import <opencv2/highgui/ios.h>

opencv を使う

iOS では一般的に UIImage 型を利用します。
一方 opencv では cv::Mat 型を利用します。

そのため、iOS 上での一般的な処理の流れは以下のようになります。

  1. UIImage を cv::Mat に変換する。
  2. opencv API を利用します。
  3. cv::Mat を UIImage に変換して、表示などに利用。

UIImage を cv::Mat にする

UIImageToMat を用います。
変換のために以下のような変換メソッドを用意します。

- (cv::Mat)matWithImage:(UIImage*)image
{
    // 画像の回転を補正する(内蔵カメラで撮影した画像などでおかしな方向にならないようにする)
    UIImage* correctImage = image;
    UIGraphicsBeginImageContext(correctImage.size);
    [correctImage drawInRect:CGRectMake(0, 0, correctImage.size.width, correctImage.size.height)];
    correctImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    // UIImage -> cv::Mat
    cv::Mat mat;

    UIImageToMat(correctImage, mat);
    return mat;
}

cv::Mat を UIImage にする

MatToUIImage を用います。

サンプルコード

//
//  ViewController.mm
//  opencvSample1
//
//

#import "ViewController.h"

#import <opencv2/opencv.hpp>
#import <opencv2/highgui/ios.h>

@interface ViewController () {
    UIImage*    _origImage;
}

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // ImageView の Outlet として imageView を用意した。
    // imageView には予め画像を設定してあるので、ここで元の画像をとっておく。
    _origImage = self.imageView.image;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (cv::Mat)matWithImage:(UIImage*)image
{
    // 画像の回転を補正する(内蔵カメラで撮影した画像などでおかしな方向にならないようにする)
    UIImage* correctImage = image;
    UIGraphicsBeginImageContext(correctImage.size);
    [correctImage drawInRect:CGRectMake(0, 0, correctImage.size.width, correctImage.size.height)];
    correctImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    // UIImage -> cv::Mat
    cv::Mat mat;

    UIImageToMat(correctImage, mat);
    return mat;
}
- (IBAction)onGray:(id)sender {
    cv::Mat     mat = [self matWithImage:_origImage];

    // グレイスケール化
    cv::cvtColor(mat, mat, CV_BGR2GRAY);
    // 変換結果を画面に表示
    self.imageView.image = MatToUIImage(mat);
}

- (IBAction)onNot:(id)sender {
    cv::Mat     mat = [self matWithImage:_origImage];
    // ネガポジ反転
    mat = ~mat;

    self.imageView.image = MatToUIImage(mat);
}

- (IBAction)onOtsu:(id)sender {
    cv::Mat     mat = [self matWithImage:_origImage];

    // グレイスケール化してから大津法で二値化
    cv::cvtColor(mat, mat, CV_BGR2GRAY);
    cv::threshold(mat, mat, 0, 255, cv::THRESH_BINARY|cv::THRESH_OTSU);
    self.imageView.image = MatToUIImage(mat);
}

- (IBAction)onAdaptive:(id)sender {
    cv::Mat     mat = [self matWithImage:_origImage];

    // グレイスケール化してから適応的二値化
    cv::cvtColor(mat, mat, CV_BGR2GRAY);
    cv::adaptiveThreshold(mat, mat, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C, cv::THRESH_BINARY, 7, 8);
    self.imageView.image = MatToUIImage(mat);
}

サンプルコードによる出力例

元画像
スクリーンショット 2014-06-21 21.22.13.png

グレイスケール画像
スクリーンショット 2014-06-21 21.20.55.png

ネガポジ反転
スクリーンショット 2014-06-21 21.21.40.png

大津法による二値化
スクリーンショット 2014-06-21 21.22.40.png

適応的二値化
スクリーンショット 2014-06-21 21.23.13.png

実機での評価

実機でうまく動かせない場合は、Architecture を以下のように変更します。
スクリーンショット 2014-06-21 18.01.39.png

102
98
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
102
98