LoginSignup
79
67

More than 3 years have passed since last update.

OpenCV が Objective-C / Swift で使えるようになります & 使ってみた

Last updated at Posted at 2020-06-09

2020年6月13日:一部加筆・修正しました。

2020年4月27日、OpenCV にこんな PR が現れました。
Objc binding by komakai · Pull Request #17165 · opencv/opencv

これまで、OpenCV には Java のラッパーが含まれていたため、Android で簡単に OpenCV を利用することができましたが、iOS、macOS では Objective-C、Swift で使うために自分で C++ を呼び出すためのラッパーを書く必要がありました。そこで、@komakai さんによって提案されたのがこの PR でした。

そして今日 2020年6月9日、その PR が無事に master ブランチへマージされ、自分で Objective-C++ を書くことなく、Objective-C、Swift で使うことができるようになりました🎉

今回は iOS プロジェクトで Swift から OpenCV を使うデモを行ってみたいと思います。

環境

$ swift --version
Apple Swift version 5.2.4 (swiftlang-1103.0.32.9 clang-1103.0.32.53)

$ cmake --version   
cmake version 3.17.3

$ python --version      
Python 2.7.18

$ xcode-select --version
xcode-select version 2373
  • macOS Catalina 10.15.5 (19F101)
  • Xcode 11.5 (11E608c)

OpenCV をダウンロードする

OpenCV 4.4 に含まれると思われますが、記事執筆時点では Release に含まれていないので、git clone で master ブランチのものを持ってきます。

$ xcode-select --install
$ git clone https://github.com/opencv/opencv.git

OpenCV.framework をビルドする

続いて OpenCV.framework をビルドします。

./build_framework.py <outputdir>

を実行する必要があるので、私の環境では以下のようにしました。時間がかかるのでゆっくり待ちましょう。

$ cd opencv/platforms/ios
$ ./build_framework.py .

Using IPHONEOS_DEPLOYMENT_TARGET=8.0
Using iPhoneOS ARCHS=['armv7', 'armv7s', 'arm64']
Using iPhoneSimulator ARCHS=['i386', 'x86_64']
... つづく

CMAKE_Swift_COMPILER が見つからないエラー

私ははじめ CMake のバージョンを 3.15.5 で実行していたのですが、No CMAKE_Swift_COMPILER could be found. となってしまい、フレームワークをビルドすることができませんでした。PR の中でもこのエラーは認識されていて、しばらくは 3.16 以降が必要となっていましたが、その後最小サポートバージョンが 3.15 に引き下げられました。でもまだエラーが出る気がするんだけど…?
このエラーについて私は 3.17 を使うことで回避しました。

Xcode プロジェクトに opencv2.framework を導入

<outputdir> で指定したディレクトリに opencv2.framework が出来ているので、Xcode プロジェクトに導入します。libc++.tbd も追加します。
001.png

Swift で opencv2 を import

ここで Swift で import opencv2 をします。またコードを書いていきます。自分で Objective-C++ のラッパーを書かなくていいのはものすごく楽…。これまでは Objective-C++ を書いて、 Bridging Header も書いてからようやく Swift を書く…という流れでしたが、より簡単になりました。

import UIKit
import opencv2

class ViewController: UIViewController {

    @IBOutlet weak var srcImageView: UIImageView!
    @IBOutlet weak var dstImageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()
        let image = UIImage(named: "サンプル画像")!
        self.srcImageView.image = image
        self.dstImageView.image = self.convertColor(source: image)
    }

    func convertColor(source srcImage: UIImage) -> UIImage {
        let srcMat = Mat(uiImage: srcImage)
        let dstMat = Mat()
        Imgproc.cvtColor(src: srcMat, dst: dstMat, code: .COLOR_RGB2GRAY)
        return dstMat.toUIImage()
    }
}

unrecognized selector sent to instance

しかしながら、記事執筆時点では let srcMat = Mat(uiImage: srcImage) の部分で unrecognized selector sent to instance の実行時エラーが発生します。
実装は opencv/modules/imgcodecs/misc/objc/ios/Mat+Converters.mm にあり、そこで UIImageToMat() を呼び出しているわけですが…

"Other Linker Flags" に -all_load を追加する

unrecognized selector sent to instance の実行時エラーが発生する問題があるとしていましたが、"Other Linker Flags" に -all_load を追加する必要がありました。
スクリーンショット 2020-06-13 0.17.41.png
(Thanks @komakai ! Mat initWithUIImage: does not work (Objective-C / Swift) · Issue #17532 · opencv/opencv

実行結果

自分で Objective-C++ のラッパーを書くことなく、OpenCV を使うことができました!!
IMG_8007-2.PNG

他のサンプル

フレームワークをビルドする際に指定した には opencv2.framework の他に samples があり、その中に ColorBlobDetection と FaceDetection の2つが入っています。Sign して opencv2.framework のパスを指定するだけで iOS App を Run できるので、こちらを試してみるのもいいですね。

79
67
13

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
79
67