Help us understand the problem. What is going on with this article?

iOS で opencv を使う。

More than 5 years have passed since last update.

評価環境

  • 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

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away