はじめに
UnityでOpenCVを使いたい動機と下調べについては前回の記事に書きました
UnityでOpenCVSharpをつかってOpenCVする。マルチスレッドにもしてみる。 (Windows) - 自習室
UnityでOpenCVSharpをつかってOpenCVする。マルチスレッドにもしてみる。 (Windows) - 自習室
今回は、OpenCVを native plugin 化して使う方法についてまとめます、というか、 @hecomi 先生のをなぞった時に出た問題点をまとめておきます
環境
- Windows 8.1 pro 64bit
- Unity 4.6.0f3 pro
- OpenCV for Windows 2.4.10
- Visual Studio 2013 Community
参考にした記事
基本(ただしMac)
この記事で、@hecomi 先生が OpenCVを native plugin 化して使う方法についてまとめてくださっています。基本はこれですが、内容がMacでbundleな感じです。
Unity で OpenCV で作成したテクスチャをネイティブプラグイン経由で利用してみた - 凹みTips
Unity で OpenCV で作成したテクスチャをネイティブプラグイン経由で利用してみた - 凹みTips
公式の基本(ただし英語)
Windowsでのやり方は、公式のLive Trainingで簡潔に説明されていました。前半はC#でManagedなpluginの説明で、23分あたりから、C++で作る Nativeなプラグインの説明になっています。ランダム関数を回して適当に数値を返すだけのプラグインを例にしているので、英語ですがわかりやすいと思います。
Live Training: Introduction to Plugins - YouTube
dllを作ること自体は Visual Studio Expressでもできますが、作った native Pluginを使うことは、Unity Proでないとできません。このあたりはUnityの厳しいところですね。
応用 Windows8.1 で、DllNotFoundException への対処付き
また、 @hecomi 先生が別の記事で、OpenCVのスタティックライブラリをラップしたdllにする方法についてもまとめくださっています。この記事で通常のlibを使ってdllにするとDllNotFoundException が出る、と報告されていますが、私のところでは解消できましたので後ほど紹介します。
Unity と OpenCV を組み合わせて現実・仮想双方を加工した AR な世界を Oculus Rift 越しに覗いてみた - 凹みTips
Unity と OpenCV を組み合わせて現実・仮想双方を加工した AR な世界を Oculus Rift 越しに覗いてみた - 凹みTips
やること
ここでは試しに、先述の Windows8.1 の環境下で、@hecomi さんの一つ目の記事でやられていた、 OpenCVでカメラキャプチャーしてウィンドウを開いて表示しつつ、Unity内でテクスチャとして利用する、をやってみようと思います。
手順
プロジェクトの作成
このあたりは、Unity - Writing Pluginsを参考に。
- Visual Studioで
- VC++ / Win32 Application を
- Application type: DLL
- Additional Options: EmptyProject でつくる
OpenCV周りのプロジェクト設定をする
PROJECT > Properties からいろいろ下記のような設定します
追加のインクルードディレクトリ
OpenCV関連のヘッダを読めるようにします。適宜OpenCVをインストールした場所に読み替えてください
OpenCVのスタティックリンクライブラリを利用する
OpenCVをせっかくdllとしてラップするので、別途 OpenCVのdll群を使わなくてもよいようにしたいです。ユーザにOpenCVをインストールさせたり、完成したアプリのフォルダ内にdllをたくさん含んだ状態で配布するのはちょっといけてない感じです。
そこで、OpenCVからリリースされている <OPENCV_ROOT>\build\x86\staticlib
の .lib
ファイルたちを利用するように指定します。これを使って以下ので順でdllを作成すると、すべての .lib
ファイルが一つのdllに固められて、そのdllだけをユーザに渡せばいい状態になります。
ランタイムライブラリをマルチスレッド(/MT)に変更
ここは @hecomi さんの受け売りです。
DLL化のためのおきまりのコードを書く
#include <iostream>#define DLLExport __declspec (dllexport)extern"C" { DLLExport int GetRandom() { return rand(); } }
先ほど動画を貼ったLive Trainingでは、上記のようなコードで ランダムな数値をはき出すだけの機能を dll 化しています。同様の手法で@hecomiさんのこちらの記事では、OpenCVを使ってカメラをたたいたり、別ウィンドウで表示したり、Unityのテクスチャとして使えるようにしています。コードは @hecomiさんの記事を参考にされてください
DLL化のために必要なスタティックライブラリをリンクする
私の環境ですと、 @hecomiさんの記事 の通りだとライブラリが不足しているようで、unresolved external symbol
エラーが大量発生します。エラーは下記のようなものたちで、多くはOpenCVのDLL本体に含まれているもののようです。これらもリンクするようにして、最終的には以下のような感じになります。
このあたりは、こちらの記事様で勉強させていただきました
- 【OpenCV】スタティックリンクライブラリの使用方法 | イメージングソリューション
- c++ - openCV 243 using static libs error LNK2019 - Stack Overflow
ビルド→Unityで使う
BUILD -> BUILD <Project Name>
で、ビルドされ、ReleaseなりDebugなりのフォルダに .dll
ファイルが生成されます。
これを、Unityで Assets/Plugins/hoge.dll
の位置に置きます
dllで定義された関数をUnityで利用する際は、以下のようにDllをインポートし関数を宣言するコードを用意し、オブジェクトにアタッチして使います。これは先述のUnity公式Live Trainingでの例です。
using UnityEngine; using System.Collections; using System.Runtime.InteropServices; publicclass TestNative : MonoBehaviour { [DllImport("RandomNumberDLL")] privatestaticexternint GetRandom(); // Use this for initializationvoid Start () { print("Native Random Number: " + GetRandom()); } }
同様に @hecomi さんの記事を参考に、dllに定義したOpenCVを使った関数を呼び出してください
その2:スタティックライブラリを使わない場合
先述の Unity公式 live Trainingと同じやり方になります。
通常のライブラリファイルをリンクする
ProjectのPropertiesで staticlib
フォルダを参照するように指定している追加のライブラリディレクトリを、 lib
フォルダを参照するように書き換えます。
ランタイムライブラリを /MD にする
システム環境変数にOpenCVのDLLのありかを通す
Path
に以下の二つを記入します (F:\develop\opencv\
の部分は、ご自身の環境に合わせてください)
F:\develop\opencv\build\x64\vc12\bin; F:\develop\opencv\build\x86\vc12\bin;
はじめ x64
のものだけを追加していたのですが、 dll を 32bit でビルドしてたため、DllNotFoundException が発生しました。 x86
のbinもPathに通したら、エラーがなくなりました。
ビルドなど以下略
ここから先は、staticlibを使う場合と同じです
最後に
これで、 @hecomi さんの記事のように、カメラ画像がテクスチャに貼れて、同時に別ウィンドウが開きカメラ画像が見られたらOKです。
@hecomi さんありがとうございました。