web-dev-qa-db-ja.com

OpenCV(JavaCV)とOpenCV(C / C ++インターフェース)

OpenCVのC/C++実装とは対照的に、JavaCVを使用する場合、特定のマシンのセットで相対的に速度が大幅に向上するかどうか疑問に思っています。

私が間違っている場合は修正してくださいが、私の理解では、opencvのc/c ++実装はマシンに近いため、Java OpenCV、JavaCの実装はわずかな速度パフォーマンスを持っています。仮想マシンがソースコードをバイトコードに変換してからマシンコードに変換するため、不利です(ミリ秒単位)。一方、c/c ++では、マシンコードに直接変換されるため、その中間ステップは実行されません。仮想マシンのオーバーヘッド。

私がミスを犯した場合、ここで私を殺さないでください。私は学んでいるだけであり、建設的な批判を歓迎します。

ありがとうございました

21
Pelican

@ejbsの答えにいくつか追加したいと思います。

まず最初に、あなたは2つの別々の問題を心配しました:

  1. JavaとC++のパフォーマンス
  2. OpenCVとJavaCV

JavaとC++のパフォーマンスは長くて長い話です。一方、C++プログラムは、高度に最適化されたネイティブコードにコンパイルされます。ガベージコレクションやその他のVM義務(Java doとして)のために一時停止することなく、常に高速で起動して高速に実行します。一方、コンパイルすると、プログラムC++では、Javaバイトコードがコンパイルされている間、それらが実行されているマシンに関係なく変更できません "ジャストインタイム "であり、常にプロセッサアーキテクチャが実行されるように最適化されています。現代では、非常に多くの異なるデバイス(およびプロセッサアーキテクチャ)があるため、これは非常に重要な場合があります。さらに、一部のJVM(たとえば、Oracle Hotspot)は、すでにネイティブコードにコンパイルされているコードでも最適化できます!VMプログラムの実行に関するデータを収集し、最適化された方法でコードを書き直そうとすることがあります。 この特定の実行したがって、このような複雑な状況では、異なるプログラミング言語での実装のパフォーマンスを比較する実際の方法は、それらを実行して結果を確認することだけです。

OpenCVとJavaCVは別の話です。まず、これらのライブラリの背後にある技術のスタックを理解する必要があります。

OpenCVは、もともと1999年にインテルの研究所で作成され、Cで書かれました。それ以来、メンテナを何度か変更し、オープンソースになり、3番目のバージョン(次のリリース)に達しました。現時点では、ライブラリのコアはC++で記述されており、人気のあるPythonのインターフェイスと他のプログラミング言語のラッパーがいくつかあります。

JavaCVはそのようなラッパーの1つです。したがって、ほとんどの場合、JavaCVでプログラムを実行するときは、実際にはOpenCVも使用し、別のインターフェースを介して呼び出すだけです。しかし、JavaCVはOpenCVの単なる1対1のラッパー以上のものを提供します。実際、FFmpeg、OpenKinectなどを含む画像処理ライブラリの全数がバンドルされています。 (C++では、これらのライブラリーもバインドできることに注意してください)。

そのため、一般に、使用しているものは問題ではありません-OpenCVまたはJavaCVでは、ほぼ同じパフォーマンスが得られます。それはあなたの主な仕事にもっと依存します-それはJavaまたはあなたのニーズにより適しているC++ですか?.

パフォーマンスについてもう1つ重要な点があります。 OpenCVを(直接またはラッパーを介して)使用すると、OpenCV関数が他の実装をいくつかの順序で克服することがあります。これは、コアで低レベルの最適化が多用されているためです。たとえば、OpenCVの filter2D 関数は [〜#〜] simd [〜#〜] -acceleratedであるため、複数のデータセットを並行して処理できます。また、コンピュータビジョンに関しては、このような一般的な機能の最適化により、大幅なスピードアップが容易に実現する可能性があります。

66
ffriend

JavaCVはOpenCVにインターフェースするので、OpenCVに関連する何かを呼び出すとオーバーヘッドが発生しますが、一般的に、重い作業のほとんどはC++側で行われるため、パフォーマンスが大幅に低下することはありません。

詳細を確認するには、パフォーマンスベンチマークを行う必要があります。

PS。私はここでかなり新しいですが、これはStackOverflowに適した質問ではないと確信しています。

4
ejbs

Javaに関するいくつかの洞察をc ++ライブラリへのインターフェースとして追加したい...

A)開発:

1)一方、Javaは、大規模プロジェクトの管理が容易で、コンパイルが非常に高速である可能性があります。非常に困難であり、Javaからネイティブコードをデバッグすることはほぼ不可能です...

コードがネイティブ側でクラッシュするとき...またはメモリリーク(何かが頻繁に発生するとき...).

2)バインディングを自分で構築しない限り(swigなどを使用しても簡単なタスクではありません...)あなたはバインディングビルダーの善意/健康/時間に依存しています...したがって、この場合は私は公式「デスクトップJava」javacv上のバインディング...

B)パフォーマンス。

1)javacvの場合のようにバインディングが最適化される可能性がありますが(neobufferを使用したメモリ転送)、各ネイティブ関数呼び出しのjniオーバーヘッドは非常に小さいままです-これは、ほとんどのopencv関数がこれと比較してX100000 ++ CPUサイクルを消費するため、私たちのケースでは意味がありませんjniオーバーヘッド...

2)大きな問題----世界のゴミ収集を停止(GC)

Javaは、すべてのCPUスレッドを停止するガーベッジコレクターを使用して、リアルタイムアプリケーションでは使用できないようにします。ガーベッジを生成しないようにアプリを再設計したり、空間GCを使用したり、リアルタイムJavaを使用したりするなどの回避策があります(コストがかかる)。 ...)それらはすべて余分な作業であるように見えます(そしてあなたが望んでいたのはopencvへのすてきな簡単なパスです....)

結論-プロのリアルタイムアプリを作成する場合-管理する巨大なモジュール式プロジェクトがない限り、c ++を使用してください-c ++とプリコンパイル済みヘッダーをそのまま使用する(物事をより速くコンパイルする...)while Javaは、ネイティブバインディングのHELLが緩んでしまうと、で作業できることを嬉しく思います...

4
shadowMaster