OpenCVのセットアップ方法(iOSアプリ用)

OpenCVはオープンソースの画像処理やマシンラーニングを行うためのライブラリです。高機能で多くの機能を持っていて、画像処理やマシンラーニングの処理を一から全て実装するよりも効率的に開発が行えます。

高機能なだけではなく、非常に高速です。内部ではOpenCLやSIMD、IPP (Intel Performance Primitive)、スレッドによる並列化などを行い、普通に実装したら得られない速度を実現しています。

この記事では、OpenCVを使ったiOSアプリを開発するための、OpenCVの開発環境のセットアップ方法を解説します。

macOSアプリのセットアップ方法については次の記事をご覧ください。

関連記事

2020年4月18日 zshでのPATHの設定方法を追加しました。cmakeのオプションでインストール先を指定するように変更しました。 OpenCVはオープンソースの画像処理やマシンラーニングを行うためのライブラリです。高機能で多くの[…]

スポンサーリンク

SDKをダウンロードする

iOS版のSDKはビルド済みのフレームワークがGitHubのReleaseページで公開されています。これをダウンロードします。この記事執筆時点の最新版は4.3.0です。

GitHub

Open Source Computer Vision Library. Contribute to opencv/op…

Xcodeのプロジェクト設定

OpenCVをアプリで使用するには、アプリにダウンロードしたフレームワークを組み込みます。以下の様にしてプロジェクトを設定します。

フレームワークをコピー

ダウンロードした opencv2.framework にはヘッダファイルも含まれています。次のようなフォルダ構成になるようにコピーします。

OpenCVTest_iOS
├── OpenCVTest_iOS
│   ├── AppDelegate.swift
│   ├── Assets.xcassets
│   ├── Base.lproj
│   ├── ContentView.swift
│   ├── Info.plist
│   ├── Preview Content
│   └── SceneDelegate.swift
├── OpenCVTest_iOS.xcodeproj
│   ├── project.pbxproj
│   ├── project.xcworkspace
│   └── xcuserdata
└── common
    └── opencv2.framework

フレームワークの追加

プロジェクトにフレームワークを追加します。わかりやすさで私の場合はフォルダに関連付けしないFrameworksというフォルダを作り、そこに入れました。

フレームワークを埋め込む設定

次にアプリにフレームワークを埋め込む設定を行います。アプリのターゲットの設定を開き、「General」タブを表示します。次に、「Frameworks, Libraries, and Embedded Content」の「opencv2.framework」の「Embed」の設定を「Do Not Embed」から「Embed & Sign」に変更します。

opencv2.frameworkのコードサイニングに失敗するとき

本来は「Embed & Sign」の設定でコードサイニングされるはずなのですが、私が試したときはエラーになってしまいました。エラーログには以下の様に出力されていました。

/Users/akira/Library/Developer/Xcode/DerivedData/OpenCVTest_iOS-ddbvsflgaojdtzettnxansgeptsx/Build/Products/Debug-iphonesimulator/OpenCVTest_iOS.app/Frameworks/opencv2.framework: code object is not signed at all
In subcomponent: /Users/akira/Library/Developer/Xcode/DerivedData/OpenCVTest_iOS-ddbvsflgaojdtzettnxansgeptsx/Build/Products/Debug-iphonesimulator/OpenCVTest_iOS.app/Frameworks/opencv2.framework/Versions/Current/opencv2

opencv2.frameworkのコードサイニングが行われていないためにエラーになっています。そのための「Embed & Sign」の設定のはずなのですが。(「Embed & Sign」はコピーした後フレームワークをコードサイニングするという設定です)

仕方がないので、次のように操作して、スクリプトフェーズでコードサイニングを行うように設定します。

(1) 「Embed & Sign」の設定を「Do Not Embed」に戻す。

(2) 「Build Phases」タブを表示し、「Run Script」フェーズを追加する

(3) opencv2.frameworkにコードサイニングを行うスクリプトを設定する。

codesign --force --deep \
--sign "${CODE_SIGN_IDENTITY}" \
--timestamp \
"${SRCROOT}/common/opencv2.framework" 

テスト

次のような簡単なコードでOpenCVが動作するか試してみます。OpenCVはC++なので、Objective-C++で書き、Swift側から呼びます。使用する画像はリソースで埋め込んだので、UIImageで読み込みます。

// OpenCVTest.h

#import <UIKit/UIKit.h>

@interface OpenCVTest : NSObject

+ (nullable UIImage *)filteredImage;

@end
// OpenCVTest.mm

#import "opencv2/opencv.hpp"
#import "opencv2/imgproc.hpp"
#import "opencv2/imgcodecs.hpp"
#import "opencv2/imgcodecs/ios.h"
#import "OpenCVTest.h"

@implementation OpenCVTest

+ (nullable UIImage *)filteredImage
{
    UIImage *srcImage = [UIImage imageNamed:@"P4071145"];
    cv::Mat srcImageMat;
    cv::Mat dstImageMat;

    // UIImageからcv::Matに変換
    UIImageToMat(srcImage, srcImageMat);
    
    // 色空間をRGBからGrayに変換
    cv::cvtColor(srcImageMat, dstImageMat, cv::COLOR_RGB2GRAY);
    
    // cv::MatをUIImageに変換
    UIImage *dstImage = MatToUIImage(dstImageMat);
    
    return dstImage;
}

@end

後は、Swift側から呼びます。私はSwiftUIで試しました。次のようなコードです。

// ContentView.swift
import SwiftUI

struct ContentView: View {
    var filteredImage: UIImage? = {
        OpenCVTest.filteredImage()
    }()
    
    var body: some View {
        ZStack {
            if self.filteredImage != nil {
                Image(uiImage: self.filteredImage!)
                    .resizable()
                    .aspectRatio(self.filteredImage!.size, contentMode: .fit)
            } else {
                Text("No Image")
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

実機でもシミュレータでもOpenCVを使った色変換ができます。Xcodeのプレビュー上でも動作します。

スポンサーリンク
最新情報をチェックしよう!
>現役のプログラマーが書くプログラミング情報

現役のプログラマーが書くプログラミング情報

日々の開発の中での学びや分かったこと、調べたことなどを書いていくブログです。

CTR IMG