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

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

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

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

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

SDKをダウンロードする

iOS版のSDKはビルド済みのフレームワークがGitHubのReleaseページで公開されています。これをダウンロードします。この記事はバージョン4.3.0に基づいて書いています。

Releases · opencv/opencv (GitHub)

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側からObjective-C++のクラスを呼べるように、ブリッジングヘッダーで読み込みます。ブリッジングヘッダーは プロジェクト名-Bridging-Header.h という名前でヘッダーファイルを作成します。今回のプロジェクトだと OpenCVTest_iOS-Bridging-Header.h です。ブリッジングヘッダーには次のようにコードを書きます。

#import "OpenCVTest.h"

ブリッジングヘッダーは、ターゲットの Build Settings で指定します。

 

後は、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のプレビュー上でも動作します。

投稿者プロフィール

林 晃
林 晃macOS/iOSアプリ/SDK/ミドルウェア開発が専門の開発者
アールケー開発代表。macOS/iOSアプリ/SDK/ミドルウェア開発が専門の開発者。ObjC/Swift/C++使い。豊富な開発実務経験を基に、教育コンテンツ開発、技術書執筆、技術指導、技術セミナー講師、企業内研修講師、行政・自治体職員研修講師も行います。

基礎から学ぶMetal


「基礎から学ぶMetal」を執筆しました。本書はMetalを使ってGPUプログラミングを行うための最初のステップを解説するMetalの解説書です。

私が初めてGPUプログラミングを行ったとき、どこから手をつけて、学んでいけば良いのか分からず呆然としました。もし、あのとき、これを教えてくれればという部分を解説しました。本書で解説している部分はMetalの基礎となる部分で、Metalを使うときに必ず触れることになる部分です。

詳細

基礎から学ぶSwiftUI


「基礎から学ぶ SwiftUI」というタイトルの本を執筆しました。

SwiftUIの入門書です。

SwiftUIのコンセプトは「ユーザーインターフェイスを作るための最短パスを提供する」「一度学べば(Appleのプラットフォームの)どこにでも適用できる」です。

SwiftUIの概要から始まって、一つ一つのテクノロジートピックに注目しながらSwiftUIとは何か?どんなことができるのか?どのようなコードを書けば良いのかなどを丸々一冊使って解説しています。

詳細

関連記事

  1. M1 Mac でのドライバの読み込み判断フロー

  2. コマンドライン引数でモックに差し替える

  3. 【Docker】 macOS Catalina 10.15 で使うとき…

  4. Combine入門 | CombineでNotificationを受け…

  5. SwiftとObjective-Cを共存させるならObjective-…

  6. Apple Notarization Service に対応するための…

最近の著書

  1. 基礎から学ぶ SwiftUI

人気記事

最近の記事