【问题标题】:Computer vision, C++ OR Java计算机视觉、C++ 或 Java
【发布时间】:2012-02-01 19:27:18
【问题描述】:

我是计算机视觉领域的新手,最近我使用 OpenCV 和 Java 实现了一些示例。我对该领域的潜力印象深刻,并希望继续学习更多。

我了解到 OpenCV 是用 C++ 编写的,而 Java 有一个包装器 (JavaCV),我知道 Java 中的应用程序比 C++ 慢,而且大多数企业应用程序都是用 C++ 编写的。

我的问题是:我有几年的 Java 经验,我觉得用它编写任何应用程序都很舒服;转向 C++ 学习 CV 是否明智,或者我应该坚持使用 Java 并使用它的包装器。

【问题讨论】:

  • Java 并不比 C++ 慢很多。从迁移到 C++ 所带来的性能提升肯定不够大,以至于值得你为此放弃多年的 Java 经验。我会使用 Java 包装器,然后 如果 你发现你需要额外的性能提升,你可以考虑用 C++ 重写,但可能你会发现 Java 版本就可以了。
  • 似乎任何 API 的“包装器”都有固有的开销。这是否会产生明显的差异取决于开销的性质以及被调用的功能。例如。如果单个方法调用在本机代码中导致 1/20 亿 CPU 操作,则包装器的开销可能可以忽略不计。我会说最好写一些简单的测试用例应用程序。并针对典型用法对它们进行概要分析。
  • 如果 JavaCV 封装了 OpenCV 并且做得很好,它应该同样快。包装库往往会变得更快,因为它们更粗粒度;当使用更快的语言完成更多循环时。
  • Java 实际上可以比 C++ 更快(反之亦然),但总的来说它是一个洗牌(除了语言规范限制 Java 的某些领域 - 以及 JVM 甚至比 C++ 编译器更弱的向量化) . @Andrew 如果我们使用相同的语言(应该内联),一个典型的包装器应该没有任何开销。 JNI 调用是这里的问题,因为它确实有一些固有的开销,并且在某些情况下可能需要大量编组 - 不过取决于 API。
  • @AndrewThompson C++ 的包装器存在一些非常可怕的陷阱,它们会降低性能并且难以避免。但基本上你是对的。 OP:如果您没有 C++ 经验,那么您的 C++ 代码很有可能会比 Java 代码慢。学习 C++ 的开销也是不可忽略的。

标签: java c++ opencv computer-vision


【解决方案1】:

计算机视觉是一个要求很高的领域——虽然你最好坚持你所知道的,并且只有在需要性能时才转向 opencv,但另一个事实是你需要深入研究数学,学习和构建一个好的计算机视觉应用程序的指针和算法。而在 Java 中做到这一点可能比学习 c++ 更麻烦。

因此,如果您只想对某个学校项目的图像应用过滤器,请选择 Java。但如果你想更多地使用 OpenCV、学习视觉算法或编写自己的算法,我强烈建议你学习 C++ - 不是那么可怕!

编写本机代码的一个原因是灵活性 - 你会想要做各种在 Java 中困难或影响性能的技巧。

简而言之,学习 C++ 比计算机视觉要简单得多。 OpenCV 不仅仅是一个你想调用来进行处理的库。它是最前沿的技术——你会想要理解它、破解它、构建它、浏览代码,而不是调用 someJNIfunc();

如果您这样做,请注意 OpenCV 提供两个接口 - 一个用于 C,一个用于 C++。虽然它们提供相同的功能,但 C++ 与 Java 很相似——具有自动内存管理和更多的优点。可以参考this的帖子看看区别

【讨论】:

    【解决方案2】:

    我建议您暂时坚持自己喜欢的方式。仅当您发现它没有公开您想要的某些 API 或性能实际上成为问题时才切换到 C++。现在,您正处于学习阶段。

    【讨论】:

    • +1:如果您正在学习,请坚持您现在所知道的并以此为基础。
    【解决方案3】:

    JavaCV 使用称为 JavaCPP 的包装器从 Java 程序调用 OpenCV。 JavaCPP 自动生成临时本地库,这些库构成了 JNI 用来让 Java 程序调用 OpenCV 本地库的桥梁。

    这个解决方案很优雅,而且效果很好,但是在安装正确的版本和正确设置类路径方面非常挑剔。您可以在 JavaCV 讨论论坛和http://code.google.com/p/javacv/wiki/Windows7AndOpenCV 了解人们面临的困难。

    我在 XP、Windows 7 和 Ubuntu 10.11 上使用 OpenCV-2.3.1 进行了这项工作,但我仍然花了几天时间才将它全部更新到 OpenCV-2.4.2。 ffmpeg 在所有平台上都特别棘手。

    如果您使用 Java 进行高级程序控制,则几乎没有速度开销,因为图像对象和基于列表的数据结构是通过指针在本机端维护的。一个陷阱是知道谁负责释放分配的内存,因此要为复杂程序导致的 VM 崩溃做好准备。

    将数据对象传输到 Java 端会有一些开销。我发现将关键点位置复制到 Java 端的 Point 对象大约需要 1 微秒。这听起来并不多,但在具有数千个关键点的实时应用程序中,它可以发挥作用。我们还通过 ByteBuffers 将 JavaCV IplImage 对象复制到 Java。这需要一毫秒或更短的时间,因此非常适合实时使用。

    在我们的例子中,我们有大量的 Java 代码可以用来对抗 OpenCV。 Java 的垃圾收集使许多事情变得容易得多。我很满意学习 JavaCV 的开销是值得的。

    我发现有必要在 Eclipse 中构建项目并从源代码编译 JavaCV 而不是使用 javacv.jar。 (不过,您将需要其他 .jar 文件。)这使您可以检查异常以跟踪库版本和类路径错误。并且需要 JavaCV 源代码来了解 JavaCV 如何公开 OpenCV API。

    【讨论】:

      【解决方案4】:

      在 OpenCV 库中花费了多少时间,在您的程序中花费了多少时间?如果您的程序完全在 C++ 中,它不能将您的程序(库外)花费的时间减少到几乎没有。例如如果您将 99% 的时间花在库中,那么使用 C++ 不能使其速度提高 1% 以上。

      【讨论】:

        【解决方案5】:

        对于简单的程序,Java 和 C++ 在速度上没有任何显着差异。但是对于具有大量计算复杂性的大型代码,C++ 速度更快。 包装器确实存在开销问题。但这对于一个小程序来说可以忽略不计。如果您用 Java 编写复杂的代码,那么将其重写为 C++ 并不容易。这是因为 Java 中没有大量可用的函数,这与 C++ 有很大的不同。

        对于 OpenCV,您应该使用 Java 还是 C++ 取决于您的动机。 如果您真的想学习 OpenCV 并从事一些大型项目,我建议您继续使用 C++。但是,如果您只是想通过 OpenCV 获得一些乐趣,那么最好坚持您所知道的。

        【讨论】:

          【解决方案6】:

          在 C++ 或 Java 中,最好使用 C++。我几乎没有 Java 经验,但我推荐 C++ 的原因是它在 ML&CV 库中的常见用法。

          强大而灵活的计算机视觉应用的最佳解决方案之一可能是下一个序列:

          1. 使用灵活的 Python 和流行的机器学习库训练模型;
          2. 存储预训练的权重;
          3. 使用具有有用但不广泛的Mat 类的 OpenCV 库将最佳模型架构重写为 C++,或编译为 C++ ML 模型;
          4. 使用您的设备处理器的明确规格进行编译。

          此解决方案的优势在于应用程序工作速度、代码安全性、开发速度以及与许多设备的兼容性。 此外,Python Tensorflow 和其他模型可以加载到 C++,例如PyTorch。 此外,使用 C++ OpenCV 代码从 CV 社区获得帮助要容易得多。

          缺点是大量的开发问题和开发速度(Java 可能不会忽略),有时 OpenCV 库的严格灵活性限制,以及许多你一开始可能没有想到的其他问题。

          【讨论】:

            猜你喜欢
            • 2018-11-07
            • 1970-01-01
            • 2011-10-18
            • 2017-08-26
            • 2013-08-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-12-04
            相关资源
            最近更新 更多