[SwiftUI] OpenCV + SwiftUI でアプリを作る

SwiftUI2021

     
⌛️ 2 min.
OpenCV と SwiftUI を組み合わせたアプリを作ってみます

環境&対象

以下の環境で動作確認を行なっています。

  • macOS Ventura 13.2 Beta
  • Xcode 14.2
  • iOS 16.0

OpenCV

一言でいうと、画像処理のライブラリです。

OpenCV の詳細は、こちらで確認してください。

プロジェクト設定

Google してみると、ローカルにコンパイルする方法が多く解説されています。

が、簡単に使用開始できる Swift Package を使っていきます。

GitHub のページは、こちら

プロジェクト作成

普通に(?)、プロジェクトを作成します。iOS だけでなく macOS にも対応しているので、MultiPlatform プロジェクトで作成しても問題ありません。

MEMO

macOS では、Accelerate.framework と OpenCL.framework も追加することが必要です。

SwiftPackage を追加

先ほどの URL を使って、Siwft Package を登録します。

MEMO

2023.1.15 時点では、最新版の 4.7.0 は、取得できません。
1つ前のバージョン 4.6.0 を Exact Version として設定するとうまく取得できます。

詳細は、こちらを見てください。

プロジェクトへの設定追加

Swift Package を追加した後に、以下の設定が必要となります。

ライブラリ追加

[Project]-[Target]-[General] で “Frameworks, Libraries, and EMbedded Content” に libc++.tbd を追加します。

libc++
libc++の追加

リンカー設定

[Project]-[Target]-[Build Settings] で Linking / Other Linker Flags に “-all_load” を追加します。

-all_load
-all_load 追加

これで、設定は完了です。

macOS/iOS の相違点

AppKit/UIKit では、画像データとして、NSImage/UIImage とそれぞれ別々のクラスが用意されています。

つまり、Multiplatform App として作ろうとしても、NSImage と UIImage が別々のクラスであることが理由で、異なるコードを作る必要が発生してしまいます。

例えば、以下のように宣言しておくと、NSUIImage というクラスで処理するようにコードを書くことで、実際の macOS/iOS で それぞれ NSImage/UIImage が使われるコードにすることができます。

#if os(iOS)
typealias NSUIImage = UIImage
#else
typealias NSUIImage = NSImage
#endif

実際には、上記の typealias 以外にも、メソッドの細かい引数の違い等を吸収する必要があります。

以降では、自作した NSUIBridge ライブラリを使って、実装していきます。

Github の URL は、こちら

OpenCVの初めの一歩

画像処理のコードを少し書いてみます。

Swift 版の OpenCV では、Imgproc というクラスのクラスメソッドに、OpenCV の多くのメソッドが定義されています。

また、OpenCV では、Mat と呼ばれる構造でデータを扱うようで、多くのメソッドの引数に、Mat を受け取ります。

例えば、カラー画像をグレースケール化するときに使用するときには、以下のようなコードになります。

// (1)
let image: NSUIImage = NSUIImage(named: "cat")!
// (2)
let srcMat = Mat(nsuiImage: image)
// (3)
let dstMat = Mat()
// (4)
Imgproc.cvtColor(src: srcMat, dst: dstMat, code: ColorConversionCodes.COLOR_BGR2GRAY)
// (5)
let result = dstMat.toNSUIImage()
コード解説
  1. (Assets に登録している) cat というデータ を読み込んで、UIImage/NSImage として用意します
  2. UIImage/NSImage から、Mat データを作成します
  3. 変換先の Mat データを用意します
  4. Imgproc のクラスメソッドとして定義されている色変換メソッドをコールします
  5. 処理後の Mat から、UIImage/NSImage を取得します

chaining method っぽくしてみる

上記のように、書いても問題ないのですが、SwiftUI 等で慣れてきているので、chaining method っぽく書けるようにしてみます。

以下のような extension を Mat に定義します。

extension Mat {
    func cvtColor(code: ColorConversionCodes) -> Mat {
        let dstMat = Mat()
        Imgproc.cvtColor(src: self, dst: dstMat, code: code)
        return dstMat
    }
}

上記のようにすると、先ほどのコードは、以下のようにかけることになります。

image = srcMat.cvtColor(code: .COLOR_BGR2GRAY).toNSUIImage()

最初のデータを cvtColor して、イメージを取得しているということが読みやすくなっている気がします。

SwiftUI

SwiftUI との組み合わせでの例を説明します。

View の中で、openCV のロジックを記述していくのは気が引けるので、ViewModel 内に書くことにします。

class ViewModel: ObservableObject {
    @Published var image: NSUIImage = NSUIImage(named: "cat")!

    func applyOpenCV() {
        let srcMat = Mat(nsuiImage: image)
        image = srcMat.cvtColor(code: .COLOR_BGR2GRAY)
            .toNSUIImage()
        return
    }

    func reload() {
        image = NSUIImage(named: "cat")!
    }
}

@Publish 指定した image を 持ち、applyOpenCV メソッドが呼ばれると 先ほどの cvtColor 処理したイメージを image に設定するメソッドを追加しています。

テスト用に、image に初期イメージを再設定するメソッドも追加してます。

openCV を使っているので、”import opencv2″ を書き忘れないでください。

struct ContentView: View {
    @StateObject var viewModel = ViewModel()

    var body: some View {
        VStack {
            Image(nsuiImage: viewModel.image)
                .resizable().scaledToFit()
            Button(action: {
                viewModel.applyOpenCV()
            }, label: {
                Text("ApplyOpenCV")
            })
            Button(action: {
                viewModel.reload()
            }, label: {
                Text("Reload")
            })
        }
        .padding()
    }
}

View の方は、Image を使って、処理前/処理後のデータを表示しています。
さらに、openCV の処理開始用のボタン、初期イメージを再設定するボタンを配置しています。

以下のようなアプリになり、openCV の処理が適用されていることを確認できます。

まとめ

OpenCV を使用するアプリの作り方

OpenCV を使用するアプリの作り方
  • Swift Package 化されている OpenCV を使うと簡単
  • Libraries 設定で libc++.tbd の追加が必要
  • BuildSettings/Linking 設定で、-all_load の追加が必要

説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。

SwiftUI おすすめ本

SwiftUI を理解するには、以下の本がおすすめです。

SwiftUI ViewMatery

SwiftUI で開発していくときに、ViewやLayoutのための適切なmodifierを探すのが大変です。
英語での説明になってしまいますが、以下の”SwiftUI Views Mastery Bundle”という本がビジュアル的に確認して探せるので、便利です。

英語ではありますが、1ページに コードと画面が並んでいるので、非常にわかりやすいです。

View に適用できる modifier もわかりやすく説明されているので、ビューの理解だけではなく、どのような装飾ができるかも簡単にわかります。

超便利です

SwiftUIViewsMastery

販売元のページは、こちらです。

SwiftUI 徹底入門

# SwiftUI は、毎年大きく改善されていますので、少し古くなってしまいましたが、いまでも 定番本です。

Swift学習におすすめの本

詳解Swift

Swift の学習には、詳解 Swift という書籍が、おすすめです。

著者は、Swift の初期から書籍を出していますし、Swift の前に主力言語だった Objective-C という言語についても同様の書籍を出しています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です