OpenCV + Android + Unity
This is just to add on to Pierre's answer, I wanted to comment but I don't have enough reputation. I followed his answer using the latest version of OpenCV(4.0.1) and there were a few extra things I needed to do.
First, replace the import with #include <opencv2/opencv.hpp>
. The other import statement points to old code.
Then go to the project's properties and select C/C++->Language. Set the language standard to C++ 11 and set Enable Run-Time Type Information to yes.
Then go to Code Generation and set Enable C++ Exceptions to yes.
After that, you should be all set.
So I finally managed to get it work !!!!!!!!!! =)
I am posting the way it worked for me here. So what I managed to do is build an .so C++ library with link to OpenCV with Visual Studio. Import this library in Unity and build a very simple Android application calling function defined in the .so library. Run the app on an Android phone.
Configuration used:
- Unity 2017.2.0f2
- Visual Studio 2017
- OpenCV 3.3.1 for Android. opencv-3.3.1-android-sdk.zip downloadable from OpenCV website.
- Android smartphone : tested on Lenovo Phab 2 Pro (Google Tango Phone) and HTC 10
Note that the steps I will describe worked for me but it might be different for you if you have a different CPU on your Android device (you'll have to build for ARM64 instead of ARM for instance, but the truth is that these steps are just an example).
I will assume that you already have Android SDK, NDK and Unity installed on your computer, so and that you are already able to build android app with Unity.
STEP 1: create a C++ Android Library with visual Studio 2017.
- File > New > Project
From the Dropdown menu on the left go to Templates > Visual C++ > Cross Platform > Android, and select "Dynamic Shared Library (Android)". (You might have to install the VS tools the be able to build for Android with VS2017). I'll keep the default "SharedObject1" name for this example.
In "Solution platform" (next to Debug/Release dropdown) select "ARM". I suggest you build in release but here we'll stick in debug as the workflow is exactly the same.
STEP 2: Link this C++ Android Project with OpenCV for Android.
- Extract opencv-3.3.1-android-sdk.zip wherever you want (choose and remember the place nevertheless because you'll need to keep the files in this place). You should have a folder with 3 subfolders called "apk", "samples" and "sdk".
- In Visual Studio, go to Project > SharedObject1 Properties. In configuration choose "All configurations" (so it applies in both Debug and Release), and platform choose "ARM". Then:
- Under C/C++, add the FULL path to OpenCV's includes to "Additional Include Directories". This path is: C:\Path-to-OpenCV-android-sdk\sdk\native\jni\include.
- Under Linker > General, add the FULL path to OpenCV's libraries to "Additional Library Directories". This path is: C:\Path-to-OpenCV-android-sdk\sdk\native\libs\armeabi-v7a.
- Under Linker > Input, add the FULL path to OpenCV's libraries file to "Additional Dependencies". This path is: C:\Path-to-OpenCV-android-sdk\sdk\native\libs\armeabi-v7a\libopencv_java3.so.
Note that instead of the full path, you can use environment variable if you know how to set them. I won't explain that here.
STEP 3: Time to write some C++/OpenCV code for our library and build it
ShareObject1.h
extern "C"
{
namespace SharedObject1
{
float Foopluginmethod();
}
}
ShareObject1.cpp
#include "SharedObject1.h"
#include <opencv2\core.hpp> // use OpenCV in this C++ Android Library
extern "C"
{
float SharedObject1::Foopluginmethod()
{
cv::Mat img(10,10,CV_8UC1); // use some OpenCV objects
return img.rows * 1.0f; // should return 10.0f
}
}
Then build the library: Build > Build Solution. If you have errors here like "Files not found blablabla", check that you put the full paths in STEP 2 or check your environment variables. If you have other errors, I don't know, ask in comments.
This should have generated a libSharedObject1.so file under Path-to-your-VS-Project\SharedObject1\ARM\Debug (or Release).
STEP 4: Let's go to Unity
- Create a new Unity Project and name it like you want.
- Create a new Scene and save it.
- File > Build Settings. Under Platform select Android and click "Switch Plateform".
- Click on Player Settings. Under "Other Settings", change the Package Name to what you feel like at the moment (Unity doesn't like the default value). Select "ARMv7" for Device Filter.
- Add your scene to the build.
In your scene, select the Main Camera and add a new C# Script named "CallNativeCode" to it: "Add Component" > type "CallNativeCode" > New Script > Create And Add. In the inspector, in Clear Flags choose "Solid color" and put a dark color (this is just for the quick demo).
CallNativeCode.cs
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
public class CallNativeCode : MonoBehaviour
{
[DllImport("SharedObject1")]
private static extern float Foopluginmethod();
void OnGUI ()
{
// This Line should display "Foopluginmethod: 10"
GUI.Label(new Rect(15, 125, 450, 100), "Foopluginmethod: " + Foopluginmethod());
}
}
Under the Assets folder, create a subfolder called "Plugins" (the spelling is important), and an other sub folder under Plugins called "Android". In this folder, copy the files libSharedObject1.so and libopencv_java3.so (the paths to these two files is in STEP 2 and 3). So you should have something like that :
Select libSharedObject1.so in Unity Editor and check that in the inspector the Selected plaforms for plugin has only Android checked, and that the CPU is ARMv7. Do the same for libopencv_java3.so.
Now you can Build and Run your app on a phone, and enjoy ! ;-)
So this is just a dummy application, but it displays the right phrase, it works !!! =) That means that we managed to make our Android Unity app call OpenCV C++ code. Regarding more complex OpenCV C++ code, well, this is not the topic here, it's time to let your creativity flow.
Just to share what i had to do to compile the .so using C++17 with OpenCV 4.1.0 in Visual Studio.
First, i had to update my AndroidNDK via the VS-Installer to n15c. Using a separately downloaded NDK did not work for me. When starting to build, the NDK_ROOT will be printed so you can check if it's setup correctly.
Follow Pierre's Steps 1 and 2. In Linker->Input, i only set the library name in "Library Dependencies". I my case, that's opencv_java4, which is how the Linker likes it, derived from libopencv_java4.so
In Tab General set:
- Platform Toolset: Clang 5.0
- Configuration Type: Dynamic Library (.so)
- Target API: Nougat 7.0 (android-24) (others might be fine, too)
- Use of STL: LLVM libc++ shared (c++_shared)
In Tab Language set:
- Enable Run-Time Information: true
- C++ Language Standard: c++17 (-std=c++1z)
In Tab Code Generation set Enable C++ Exceptions to yes
In Tab Linker->Command Line add -lm -lz
I also had to set Not using Precompiled Headers in C/C++ -> Precompiled Headers. I don't think this is generally necessary though.
Hope this will be helpful for someone!