OpenCV tutorial〜ヒストグラム〜

イントロダクション

ようやく、OpenCVのチュートリアルを続ける準備ができました。

前回は、ビデオキャプチャを作成してJavaFXで起動しました。

問題というか気に入らない事

せっかく作成したビデオキャプチャと次に作成するヒストグラムのプログラムを別々に作成、もしくは変更するという方向でチュートリアルが記載されているので「画面切り替え」という形で今まで作成したものを残していく方法でやっていこうと思います。

画面切り替え作成はこんな感じでやりました。

そして、プロジェクトの構成を変えました。(リソースフォルダを使用するように修正)

スクリーンショット 2019-02-02 14.26.11.png

いざ、チュートリアル

参考にするサイトはこちらです。

今回のチュートリアルは「ビデオキャプチャ」作成後の状態(ソース)から始まっているようです。※自分にはふた通りの解釈ができました。

さぁ読み込んで理解してやるぞ!

結局。。。

よくわからなかった(記載している文言とキャプチャがずれているように見えた)のでソースから入ります。コードから入るのは理解力不足なのかもしれない。。。が、わからないなら結論から入るのもアリだと思うのです。

というわけで、チュートリアルページの一番下、以下キャプチャ参照(日本語に翻訳してます。。。)スクリーンショット 2019-02-02 14.58.55.png

Gitにあるソースを参照して写経します。元々の画面への追加は後日。。。

写経、そして起動

写経したら、早速動かしてみたいと思うのが人情(だと思う。。。)と言うわけで動かしてみました。

早速Exception

こんなのでました。

ちょっとわかりづらいけど、選択している部分に

at zenryokuservice.opencv.fx.tutorial.Tutorial2.start(Tutorial2.java:35)

実行したクラス名があります、そのクラス「start」メソッドTutorial2.javaの35行目でエラってます。。。という内容です。下の部分がそうです。

「Video.xml」とコーディングしてます。。。ファイルがないから落ちるな(笑)

「Video.fxml」に修正、サイド実行する

どーん!

またException、いつものことなので「なんだまだかよ?」みたいな感じです。

ポイントは下の方に記載がある、赤い字の部分です。

Caused by: java.lang.ClassNotFoundException: it.polito.teaching.cv.VideoController
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:920)

「java.lang.ClassNotFoundException」は「クラスが見つかりませんよ!」というExceptionです。

作成したパッケージが「zenryokuservice.〜」で始まっているのに「it.polito〜」で始まっているのは明らかにおかしい→コピペが犯人です。自分が悪いわけじゃありません(ちゃんとやらないのがいけません。。。)というわけで、Video.fxmlのパッケージ名を修正します。

it.polito.teaching.cv.VideoController」
   →「zenryokuservice.opencv.fx.tutorial.VideoController」

そして再度実行!はい!いらっしゃい!

今度は、FXMLローダあたりのエラーのようです。

Caused by: java.lang.UnsatisfiedLinkError: org.opencv.videoio.VideoCapture.VideoCapture_3()J
at org.opencv.videoio.VideoCapture.VideoCapture_3(Native Method)
at org.opencv.videoio.VideoCapture.<init>(VideoCapture.java:72)
at zenryokuservice.opencv.fx.tutorial.VideoController.initialize(VideoController.java:72)
... 24 more

この「UnsatisfiedLinkError」は自分にもよくわかりませんでした。。。が赤い字で示す通り、VideoController.javaの72行目

this.capture = new VideoCapture();

「んー!なんでだ?わからんぞ?。。。」と5分くらい考えましたがわからなかったです。駄菓子菓子、OpenCVのライブラリの設定をしていなかった事に気がつきました(笑)

そう!OpenCVでプロジェクトにライブラリを設定する、実行時にライブラリを読み込む事が必要なのです。

/** ネイティブライブラリを読み込む */
static {
    System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
}

「static { 〜 }」の部分はメインメソッドの前に起動される部分です。

【補足】

Javaを起動するときに走る順番

  1. 「JVM(javaコマンドだと思ってください)
  2. 「staic」のついているフィールド、メソッド、スコープ(「{」と「}」で囲まれている部分)がJVMに読み込まれます。
  3. メインメソッド

大雑把にこんな感じです。そして修正して再実行!

Caused by: java.lang.ClassCastException: javafx.scene.layout.BorderPane cannot be cast to javafx.fxml.FXMLLoader
	at zenryokuservice.opencv.fx.tutorial.Tutorial2.start(Tutorial2.java:45)
	at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863)
	at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
	at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
	at java.security.AccessController.doPrivileged(Native Method)
	at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
	at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
Exception running application zenryokuservice.opencv.fx.tutorial.Tutorial2

BorderPaneはFXMLLoaderにキャストできません。というわけで下のように修正をします。

<変更前>

FXMLLoader loader = FXMLLoader.load(getClass().getResource("Video.fxml"));

<変更後>

FXMLLoader loader = new FXMLLoader(getClass().getResource("Video.fxml"));

凡ミスのようです。。。これで最後であって欲しい。。。

どーだぁ!

キターーーー!

ちなみに「Show Logo」のチェックボックスを押下するとエラリます。。。

これでなんとか動いたので、この処理の内容をみていきます。

ただし、次回にします。

でわでわ。。。