【问题标题】:OpenCV + Android + UnityOpenCV + Android + Unity
【发布时间】:2018-05-04 03:20:05
【问题描述】:

我正在寻找一种在 Unity 项目中使用 OpenCV 的方法,而我的目标平台是 Android 设备。

我知道 Unity 资源商店中存在一些资源,但我不想使用它们,因为我觉得它们太贵了。

通过使用this 教程在 dll 中预编译 OpenCV,我设法在 Unity 中使用 opencv 作为 C++ 原生插件,但 dll 表示 Windows 桌面,因此它对我为 Android 构建项目没有太大帮助。

我还找到了 opencv jar 存档,我知道它们可以轻松导入 Unity,但我不知道下一步该怎么做:那就是如何从 Unity C# 脚本访问 OpenCV 内容。

所以,如果有人知道如何在 Unity 编辑器中使用 OpenCV 配置一个虚拟的 hello world 项目以构建到 Android,或者甚至有提示,我会提供任何相关信息。

提前致谢。

PS:我知道这个问题有点模糊,相信我这不是一个 LMGFY 问题,因为在谷歌上有很多这样的问题,没有真正的答案,所以请不要急于 -1 投票。

更新

使用this 教程,我设法使用Android Studio 为Android 构建了opencv,但我仍然不知道如何在C# 脚本中使用OpenCV。比如如何创建一个cv::Mat?

所以我设法做到了:

  • 使用 Android Studio(来自 Java)构建 OpenCV 并运行一些本机代码。
  • 构建 Unity native example(一个单一的 C 函数)并从 C#script 调用它。

但我仍然不知道如何使用 OpenCV 依赖项构建一些 C++ 代码并从 C# 脚本调用此代码。

【问题讨论】:

  • 不是-1,但实际上是+1,当我几年前尝试使用它时,只有付费解决方案可用。我不知道团结世界的现状,但我的大学想做同样的工作,我建议他开箱即用,不要团结自己。
  • 我终于做到了,最后也没那么复杂。如果有人感兴趣,我稍后会发布答案,但好消息是它可以轻松完成。
  • “它可以很容易地完成”然后请逐步分享答案/Tut。感谢尽快回复
  • 回复已发布;-)
  • 您的链接不适用于您给出的问题。

标签: c# android opencv unity3d unity5


【解决方案1】:

所以我终于设法让它工作了!!!!!!!!!! =)

我在这里发布它对我有用的方式。所以我设法做的是使用 Visual Studio 构建一个带有 OpenCV 链接的 .so C++ 库。在 Unity 中导入这个库,并在 .so 库中定义一个非常简单的 Android 应用程序调用函数。在 Android 手机上运行该应用。

使用的配置:

  • Unity 2017.2.0f2
  • Visual Studio 2017
  • 适用于 Android 的 OpenCV 3.3.1。 opencv-3.3.1-android-sdk.zip 可从OpenCV website 下载。
  • Android 智能手机:在 Lenovo Phab 2 Pro(Google Tango Phone)和 HTC 10 上测试

请注意,我将描述的步骤对我有用,但如果您的 Android 设备上有不同的 CPU,对您来说可能会有所不同(例如,您必须为 ARM64 而不是 ARM 构建,但事实是这些步骤只是一个示例)。

我假设您已经在您的计算机上安装了 Android SDK、NDK 和 Unity,因此您已经能够使用 Unity 构建 Android 应用程序。

第 1 步:使用 Visual Studio 2017 创建 C++ Android 库。

  • 文件 > 新建 > 项目

从左侧的下拉菜单中转到模板 > Visual C++ > 跨平台 > Android,然后选择“动态共享库 (Android)”。 (您可能必须安装能够使用 VS2017 为 Android 构建的 VS 工具)。我将为此示例保留默认的“SharedObject1”名称。

在“解决方案平台”(调试/发布下拉菜单旁边)中选择“ARM”。我建议你在发布版本中构建,但在这里我们将坚持调试,因为工作流程完全相同。

第 2 步:将此 C++ Android 项目与适用于 Android 的 OpenCV 链接。

  • 解压 opencv-3.3.1-android-sdk.zip 到任何你想要的地方(选择并记住这个地方,因为你需要把文件保存在这个地方)。您应该有一个包含 3 个子文件夹的文件夹,分别称为“apk”、“samples”和“sdk”。
  • 在 Visual Studio 中,转到项目 > SharedObject1 属性。在配置中选择“所有配置”(因此它适用于调试和发布),平台选择“ARM”。然后:
    • 在 C/C++ 下,将 OpenCV 包含的完整路径添加到“其他包含目录”。这个路径是:C:\Path-to-OpenCV-android-sdk\sdk\native\jni\include。
    • 在 Linker > General 下,将 OpenCV 库的完整路径添加到“Additional Library Directories”。这个路径是:C:\Path-to-OpenCV-android-sdk\sdk\native\libs\armeabi-v7a。
    • 在 Linker > Input 下,将 OpenCV 库文件的完整路径添加到“Additional Dependencies”。这个路径是:C:\Path-to-OpenCV-android-sdk\sdk\native\libs\armeabi-v7a\libopencv_java3.so。

请注意,如果您知道如何设置环境变量,则可以使用环境变量来代替完整路径。这里就不解释了。

第 3 步:是时候为我们的库编写一些 C++/OpenCV 代码并构建它了

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
    }
}

然后构建库:构建 > 构建解决方案。如果您在此处遇到“找不到文件 blablabla”之类的错误,请检查您是否将完整路径放入 STEP 2 或检查您的环境变量。如果还有其他错误不知道,在cmets中询问。

这应该在 Path-to-your-VS-Project\SharedObject1\ARM\Debug(或 Release)下生成了一个 libSharedObject1.so 文件。

第 4 步:让我们使用 Unity

  • 创建一个新的 Unity 项目并根据需要为其命名。
  • 创建一个新场景并保存。
  • 文件 > 构建设置。在平台下选择 Android 并点击“切换平台”。
  • 单击播放器设置。在“其他设置”下,将包名称更改为您现在的感觉(Unity 不喜欢默认值)。为设备过滤器选择“ARMv7”。
  • 将您的场景添加到构建中。

在您的场景中,选择主摄像机并向其添加一个名为“CallNativeCode”的新 C# 脚本:“添加组件”> 键入“CallNativeCode”> 新脚本> 创建并添加。在检查器中,在 Clear Flags 中选择“纯色”并放置一个深色(这只是为了快速演示)。

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());
    }
}

在 Assets 文件夹下,创建一个名为“Plugins”的子文件夹(拼写很重要),并在 Plugins 下创建一个名为“Android”的子文件夹。在此文件夹中,复制文件 libSharedObject1.solibopencv_java3.so(这两个文件的路径在步骤 2 和步骤 3 中)。所以你应该有类似的东西:

在 Unity Editor 中选择 libSharedObject1.so 并检查检查器中的 Selected plaforms for plugin 是否仅检查了 Android,并且 CPU 是 ARMv7。对 libopencv_java3.so 执行相同操作。

现在您可以在手机上构建和运行您的应用,尽情享受吧! ;-)

所以这只是一个虚拟应用程序,但它显示了正确的短语,它可以工作!!! =) 这意味着我们设法让我们的 Android Unity 应用程序调用 OpenCV C++ 代码。关于更复杂的 OpenCV C++ 代码,好吧,这不是这里的主题,是时候让你的创造力发挥出来了。

【讨论】:

  • 嘿,非常感谢您花时间写下来,但是我不得不问一下,您对此有任何未定义的参考问题吗?我目前正在尝试使用 OpenCV 进行 ARCore 手部识别,并且我收到一条链接器错误,消息为 undefined reference to 'cv::error(int, std::string const&amp;, char const*, char const*, int)',由 cv::Mat() 构造函数调用。我知道答案已经很久了,但是你有没有机会知道如何解决这个问题?
  • @kubci98 在构建 C++ 共享库时会发生这种情况吗?我的猜测是检查您是否正在为正确的平台(32 位与 64 位...)构建并检查 Visual Studio 是否可以找到 opencv 库二进制文件。
  • 是的,在构建时。此外, cv::error 是我遇到此问题的唯一函数,因此这似乎不是一些大规模的链接问题。我实际上已经尝试按照您的描述逐步执行此操作,是的,我仍然有这个问题。最后,我自己重写了函数(创建了一个新的 cv::error(...) 函数,它只是将第二个参数作为异常抛出),现在我的代码可以编译并且运行良好。
  • 好的,所以这实际上再次发生在我的 cv::putText 身上,我设法修复了它(它实际上看起来像是一个 STL 问题)。如果您得到任何未定义的对 cv::... 函数的引用,请转到调试 > 项目名称属性... > 配置属性并将“使用 STL”设置为“LLVM 共享库 (c++_shared)”。
  • @Thmsbrhn 如果您使用相同版本的所有内容,您应该没有问题。如果您使用其他版本,可能会有一些额外的步骤,在 cmets 和该主题的额外答案中提到。你能告诉你在哪一步出现这个错误吗?
【解决方案2】:

这只是为了补充皮埃尔的答案,我想发表评论,但我没有足够的声誉。我使用最新版本的 OpenCV(4.0.1) 遵循了他的回答,我还需要做一些额外的事情。

首先,将导入替换为#include &lt;opencv2/opencv.hpp&gt;。另一个 import 语句指向旧代码。

然后转到项目的属性并选择 C/C++->Language。将语言标准设置为 C++ 11,并将 Enable Run-Time Type Information 设置为 yes。

然后转到代码生成并将启用 C++ 异常设置为是。

在那之后,你应该准备好了。

【讨论】:

  • 感谢您将我一年前的答案更新到最新版本;-) 我很高兴看到它仍然有用。 =>为你+1
【解决方案3】:

只是为了分享我在 Visual Studio 中使用 C++17 和 OpenCV 4.1.0 编译 .so 所要做的事情。

首先,我必须通过 VS-Installer 将我的 AndroidNDK 更新到 n15c。使用单独下载的 NDK 对我不起作用。开始构建时,将打印 NDK_ROOT,以便您检查它是否设置正确。

按照 Pierre 的步骤 1 和 2。 在Linker->Input中,我只在“Library Dependencies”中设置了库名。我的情况是 opencv_java4,这是链接器喜欢它的方式,源自 libopencv_java4.so

在标签常规设置:

  • 平台工具集:Clang 5.0
  • 配置类型:动态库 (.so)
  • 目标 API:Nougat 7.0 (android-24)(其他可能也可以)
  • 使用 STL:LLVM libc++ 共享 (c++_shared)

在标签语言设置:

  • 启用运行时信息:true
  • C++ 语言标准:c++17 (-std=c++1z)

在标签代码生成中将启用C++异常设置为

在标签链接器->命令行添加-lm -lz

我还必须在 C/C++ -> Precompiled Headers 中设置 Not using Precompiled Headers。不过,我认为这通常没有必要。

希望这对某人有所帮助!

【讨论】:

  • 感谢您的更新,很高兴看到这仍然有用=)
猜你喜欢
  • 2020-01-17
  • 2021-08-18
  • 2018-03-07
  • 1970-01-01
  • 2015-07-29
  • 1970-01-01
  • 2015-02-17
  • 2016-07-15
  • 1970-01-01
相关资源
最近更新 更多