OpenCV(JavaCV)与OpenCV(C/C++接口)的区别

26

我只是在想,在使用JavaCV和C / C ++实现的OpenCV之间,是否会有显着的速度性能优势。

如果我理解得不对,请纠正我,但我认为OpenCV的C / C ++实现更接近机器,而OpenCV的Java实现(JavaCV)则会稍微慢一些(以毫秒为单位),因为有一个虚拟机将您的源代码转换为字节码,然后再转换为机器代码。而使用C / C ++,它直接转换为机器代码,因此不需要经过那个虚拟机开销的中间步骤。

如果我犯了错误,请不要责怪我;我正在学习,并欢迎建设性的批评。

谢谢


但是Java是跨平台的,而C/C++是平台相关的。 - praveen_mohan
使用Maven获取OpenCV库并使其正常工作的问题会少一些 :p - MilacH
3个回答

73
我想补充一下@ejbs的回答。首先,您关注了两个不同的问题:
1. Java vs. C++ 的性能 2. OpenCV vs. JavaCV
Java与C ++的性能是一个漫长而复杂的故事。一方面,C ++程序编译成高度优化的本地代码,它们启动快速并且始终运行快速,无需暂停进行垃圾回收或其他虚拟机任务(如Java)。另一方面,一旦编译完成,C++程序无法改变,无论在哪台机器上运行,而Java字节码则被“即时编译”,并且总是针对它们运行的处理器架构进行优化。在现代世界中,由于有大量不同的设备(和处理器架构),这可能真的很重要。此外,一些JVM(例如Oracle Hotspot)甚至可以优化已经编译为本地代码的代码! VM会收集有关程序执行的数据,并且时不时地尝试以使其针对此特定执行进行优化的方式来重新编写代码。因此,在这种复杂的情况下,比较不同编程语言中实现的性能的唯一真正方法就是运行它们并查看结果。
OpenCV vs. JavaCV 是另一个故事。首先,您需要了解这些库背后的技术堆栈。OpenCV最初是在1999年,由英特尔研究实验室创建的,使用C编写。从那时起,它几次改变维护者,并成为开源并达到了第三个版本(即将发布)。目前,该库的核心是用C ++编写的,具有Python中的流行界面以及其他编程语言的许多包装器。

JavaCV是其中之一的包装器。因此,在大多数情况下,当您使用JavaCV运行程序时,实际上也在使用OpenCV,只是通过另一种接口调用它。但是,JavaCV提供的不仅仅是对OpenCV进行一对一的包装器。事实上,它捆绑了整个图像处理库,包括FFmpeg、OpenKinect等。(请注意,在C++中,您也可以绑定这些库)。

因此,一般来说,无论您使用OpenCV还是JavaCV,您都将获得几乎相同的性能。它更多地取决于您的主要任务——Java还是C++更适合您的需求。

还有一个关于性能的重要点。使用OpenCV(直接或通过包装器),您有时会发现OpenCV函数比其他实现快几个数量级。这是因为其核心部分大量使用低级别优化。例如,OpenCV的filter2D函数被SIMD加速,因此可以并行处理多组数据。当涉及到计算机视觉时,这些常见函数的优化可能很容易导致显着的加速。


非常深入的解释,感谢您抽出时间。 - Pelican
这是很棒的东西,我的意思是,这解释得非常清楚,你刚刚回答了我的问题,节省了我寻找易懂解释所需的时间。 - kinsley kajiva

4
JavaCV与OpenCV相接,因此当您调用与OpenCV相关的内容时,会有一些开销,但通常大部分繁重的工作仍然在C ++端完成,因此不会有非常大的性能损失。您需要进行性能基准测试以了解更多信息。
PS. 我在这里还很新,但我非常确定这不是适合在StackOverflow上提问的问题。

2
你为什么认为这不适合在 Stack Overflow 上发布? - ffriend
我不确定能给你一个好的理由,恐怕更多是凭直觉。 - ejbs
是的,我知道这种感觉 :) 然而,这个问题很具体,可能有具体的答案,所以我认为没问题。 - ffriend
感谢朋友和EJB,对于实时应用程序的情况,例如在高速公路上检测飞驰而过的汽车,JavaCV接口仍然足够快吗?我知道我有点儿傻,Java非常快,但为什么他们会提供这个库的C/C++实现呢?难道不是因为它相比其他任何语言(如Java、Python)都更快吗?如果我错了,请纠正我。 - Pelican
我相信原始实现是用C++编写的,所以这仅仅是历史原因。我不确定它是否足够快,也许?如果你满意的话,请别忘了接受我的答案 ;) - ejbs
谢谢ejbs,我刚刚做了。 - Pelican

3
我想在Java作为C++库接口方面提供更多见解...
A)开发:
1)虽然Java可能更容易管理大型项目并且编译速度非常快,但是从Java调试本地代码非常困难,几乎不可能...当本地端代码崩溃或内存泄漏(这种情况经常发生...)时,你会感到无助...
2)除非您自己构建绑定(即使使用SWIG等也不是易事...),否则您将取决于绑定构建者的善意/健康/时间....因此,在这种情况下,我更喜欢官方的“桌面Java”绑定而不是Javacv...
B)性能。
1)尽管绑定可以进行优化(使用Neobuffer进行内存传输),例如在Javacv中,但每个本机函数调用仍存在非常小的JNI开销-在我们的情况下,这是毫无意义的,因为大多数OpenCV函数与此JNI开销相比消耗X100000 ++ CPU周期...
2)最大的问题——停止世界垃圾收集器(GC)
Java使用垃圾收集器来暂停所有CPU线程,使其不适用于实时应用程序。有一些解决方法,如重新设计您的应用程序以不产生垃圾,使用特殊的GC或使用实时Java(需要花费一定的费用...)它们似乎都是额外的工作(而你想要的只是一个好的、易于使用的路径到OpenCV...)
结论-如果您想创建专业的实时应用程序-那么请使用C++,除非您有一个巨大的模块化项目需要管理-否则只需坚持使用C++和预编译头文件(使编译更快...)虽然Java很容易使用,但当涉及本地绑定时,情况就会变得混乱...我知道我曾经在那里...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接