みの屋.

プログラムを書いてる時に躓いたことやコードの進捗などをメモでまとめていく予定です.(ついでに日常のつぶやきもちらほらと……)

【Mac】javaでOpenCVの環境設定に苦労したメモ

一旦デスクトップマスコットのお話は置いておいて, 今回はここしばらく頭を悩ませていたJavaOpenCVをインストールするためのメモ書きを.

実はOpenCV自体は約2年前からちょこちょこjavaで入れようとしてたものの毎回失敗して後回しにしてたんですが,ある授業で画像処理の課題が出たので改めて挑戦してみることに.

前置きとして,今回やっとOpenCVjavaコンパイルは通ったものの,現時点でまだ実行時にエラーが出てます.

今回のインストール環境(Home brew がインストールされていることが前提)

今まではOpenCVを'.tar'ファイル等で落として環境構築しようとしてたのだけど,brewでインストールしているサイトが多かったため,今回はbrewでインストールすることに.

OpenCVのインストール

ではでは早速brewでインストール………と,その前にまずはしばらくサボっていたbrewのupdateとupgradeを.

因みに3ヶ月?くらいサボっていたため更新に15分以上かかりました.こまめにbrew updateしないとやっぱりいざという時に結構時間食いますね.

そしてやっと本題のOpenCVのインストール!
本当は参考にしたサイト様のリンクを貼りたいのですが,なぜか数日前に削除されてしまっていたので自分で新しくメモ書きします.

  1. まずはantをインストール.brew install antこれがないと目当ての.jarファイルが生成されないらしい…

  2. 次にbrew edit opencvを実行し,-DBUILD_opencv_java=OFFであればONに書き換える.(2017.11月現在 標準でOFFになっていました)
    因みにこの部分をONにしないと--with-javaオプションが働かないです.自分は最初これを知らずにjarファイルが出来なくてがっつり躓きました…

  3. brew install --build-from-source opencvを実行してOpenCVをインストール.
    これは思ったよりは時間かかるので,できれば時間と充電の余裕のある時にした方が良いです.

  4. 3で,エラーを吐かずにインストールが完了していれば,
    /usr/local/Cellar/opencv/3.3.1_1/share/OpenCV/javaopencv_java310.jarができているはず.
    もしjavaというフォルダがなければjarファイルのインストールに失敗しています.2の変更がちゃんと更新されているか確認して更新されていた場合は一度ターミナル自体を再起動した後に再インストールしてみてください.

ここまででjarファイルが作成されていればOpenCVのインストールは成功なので,次は以下のサンプルコードが実際に実行できるかを試していきます.

Sampleコードのコンパイル

今回使用する動作確認用のOpenCVのサンプルコード(hogehoge.java)は以下.

import org.opencv.core.Core;                                                                                            
import org.opencv.core.CvType;                                                                                          
import org.opencv.core.Mat;                                                                                             
                                                                                                                        
public class hogehoge {                                                                                                 
    public static void main(String[] args) {                                                                            
        System.out.println("check1");                                                                                   
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);                                                                   
        System.out.println("check2");                                                                                   
        Mat m = Mat.eye(3, 3, CvType.CV_8UC1);                                                                          
        System.out.println("check3");                                                                                   
        System.out.println("m = " + m.dump());                                                                          
    }                                                                                                                   
}

まずはこのコードをどこかのディレクトリに作成.作成する場所はどこでも大丈夫なので適当に選んじゃっておk
javaコードが用意できたら次はコンパイルしていく.

次にこのコードをコンパイルするためにさっきのopencv_java310.jarが必要なので,

javac  -classpath /usr/local/Cellar/opencv/3.3.1_1/share/OpenCV/java

でクラスパスを指定してコンパイルしてあげるか,あらかじめ

/Libraty/Java/Extensions

の中にjarファイルを入れてあげればクラスパスが通る.
因みに2つともクラスパスを通しているんだけど,-classpathの方はコンパイル&実行するたびにちゃんと指定してあげないとうまく動かないので注意が必要かも.
まとめると,

  • classpath:このコマンドをつけた時だけそのクラスパスを通す.他のファイルには一切影響しない.
  • Extensionsの中に入れる:全てのjavaファイルのコンパイル時に参照される.他のファイルに影響があると困るときは避けた方が良い.

という感じ.

ここまででちゃんとクラスパスが通っていればコンパイルは通るはず…!!
もしExtensionsの中にjarファイルを入れてもこんな感じのエラーが出たらいっそOpenCVアンインストールしてもう一度インストールした方が良いかも…
(自分はこのエラーが出て1年以上悩んだ結果再インストールしたので……)

hogehoge.java:1: エラー: シンボルを見つけられません
import org.opencv.core.Core;
                      ^
  シンボル:   クラス Core
  場所: パッケージ org.opencv.core
hogehoge.java:7: エラー: シンボルを見つけられません
    System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
                       ^
  シンボル:   変数 Core
  場所: クラス hogehoge
エラー2個

……org.opencv.core.Matとかはちゃんと存在していることになっているのになぜかorg.opencv.core.Coreだけが存在しないエラー………インストールのときに何か失敗してたのかな………

とりあえず,今回はこのエラーにめちゃくちゃ悩まされてたのがやっと解決して実行段階へ移れたので次へ進みます.

コードの実行

やっとコンパイルに成功して実行へと!!!!
次のような出力があれば成功なのでようやっと最終段階!!!!!!

mat = [  1,   0,   0;
   0,   1,   0;
   0,   0,   1]

自分はjarファイルをExtensionの中に入れているためコンパイル&実行時に-classpathをつけてないですが,コンパイル-classpathを使ってたら実行時にも指定してあげないと動かないです.

>java hogehoge

check1
check2
Exception in thread "main" java.lang.UnsatisfiedLinkError: org.opencv.core.Mat.n_eye(III)J
    at org.opencv.core.Mat.n_eye(Native Method)
    at org.opencv.core.Mat.eye(Mat.java:492)
    at hogehoge.main(hogehoge.java:10)

……………ん?Matに代入しているところでエラー吐いてる…?
LinkError?途中まで実行できてはいるけどnativeliblaryとか何かしらの参照がうまくいってない…?

…………という感じで今絶賛エラーと格闘しています.
Docker使えよと言われればそれまでなんですが,せっかくコンパイルも通ってここまで来たのでDockerに頼るのは何か悔しい……←
次回はエラーが解決してからの更新となりますが,もしその前にこのエラーの原因を知っている方がいればコメント等で教えていただけると幸いです………………