😺

Kotlin x OpenCV 環境構築方法

2023/08/25に公開

OpenCVをKotlinで動かすための環境構築方法について書きます。非常に厄介かつ未だに腑に落ちていないのですが参考にしていただけると幸いです。

開発環境

  • 統合開発環境: IntelliJ
  • OS: Windows 10

OpenCVはWindows版をダウンロードし、「opencv\build\java」内にある「opencv-460.jar」と「opencv_java460.dll」を扱います

本題

ビルドシステムの「IntelliJ」「Gradle(Kotlin DSL)」の2種類の場合について書きます。

動かしたいコードは以下になります。

// サンプルコード(カメラ映像を表示)
import org.opencv.core.Mat 
import org.opencv.core.Core 
import org.opencv.highgui.HighGui 
import org.opencv.videoio.VideoCapture 
fun main() { 
	System.loadLibrary(Core.NATIVE_LIBRARY_NAME)
	val cap = VideoCapture(0) 
	val frame = Mat() 
	while (cap.read(frame)) { 
		HighGui.imshow("window", frame) 
		val key = HighGui.waitKey(100) 
		if (key == 81) { break } 
	} 
	cap.release() 
	HighGui.destroyAllWindows() 
	System.exit(0) 
}

IntelliJの場合

こちらの場合は比較的簡単です。
下図のように、モジュールを追加して次にdllファイルの設定を行います。ファイルタブからプロパティ構造を選択すると表示される画面で設定

Gradle(Kotlin DSL)の場合

厄介になるのがこちらの方。
結論から書くと

  • jarファイル → build.gradle.kts内で指定
  • dllファイル → パスが通っている「java\bin」内などに移動する必要

まず、jarファイルはbuild.gradle.kts内で指定することができます。具体的には以下

// build.gradle.kts
dependencies {
    implementation(files("$projectDir/libs/opencv-460.jar"))
}

事前にプロジェクトディレクトリ内にlibsというフォルダを作成し、その中にjarファイルを設置している状態です。そのjarファイルの設定を行っているコードになります。

次に、dllファイルはパスが取っているフォルダに移動する必要があります。
私の場合は、「C:\Program Files\Java\jdk-18.0.1\bin」内へ移動しました。これによって、エラーが出ずに実行することができます。

この結論に至るまでの経緯

長い長い試行錯誤がありました。おそらく誰しもが引っかかるだろう以下のエラー

no opencv_java460 in java.library.path

このエラーをどうにかしてgradleだけで解決できないかと考えました。ただ、それは無理だという結論で今は考えています。もしかしたら別にいい方法があるのかもしれませんが疲れました...
これはローカルだけでなく、「openpnp/opencv」や「JavaCV」からダウンロードした場合でも同様に発生

「java.library.path」に対して設定を施せば解決できるだろうと踏んだのです。例えば、「setProperty」や「-Djava.library.path」を設定すればいけるだろうと。しかし、上手くいかない。

それでは、「java.library.path」の内容を追記しようと考えました。しかし、ネットにあった以下のようなコードはセキュリティ的に動作しない。

// 動かなかったコード
sys_paths = ClassLoader.class.getDeclaredField("sys_paths");
sys_paths.setAccessible(true);
sys_paths.set(null, null);

http://blog.livedoor.jp/tamanooboshi/archives/26885529.html

java.library.pathの内容を見ると、環境変数Pathなのです。そこで、Pathが通っているフォルダにdllファイルを移行すれば解決するのではないかと考えた。それが、BINGO!だったわけです。
もちろん、新たにdllファイルを置いたディレクトリをPath通すアプローチもOK。

プログラムで簡単にdllファイルを移動できるだろうと踏んだのですが管理者権限の問題から、プログラムではなく、実際にコピペで移動した方が簡単でした。

Discussion