2018年10月27日土曜日

ClojureのcljプロジェクトでOpenCVを使う方法


背景

Clojureとはlispと呼ばれる関数型プログラミング言語の1つです。
Javaというプログラミング言語が動く環境で動きます。

Clojureを動かすにはleiningenというパッケージ管理プログラムを利用することが多いかと思いますが、cljコマンドをleiningenに変わる管理プログラムとして利用しようという流れがあります。
以前leiningenプロジェクトでOpenCVを動かしたので、同じようなことをcljプロジェクトでするにはどうしたら良いか気になったので、試してみました。

結果としてOpenCVをcljプロジェクトで利用できたので、方法を備忘録を兼ねて共有します。

使ったもの

cljコマンドが動く環境

cljコマンドのインストール手順に従い、インストールします。

Getting Started | Clojure

ubuntuでcljコマンドを使う場合は、上記の手順と合わせてrlwrapというコマンドライン上の操作を便利にしてくれるライブラリをインストールする必要がありました。
sudo apt install rlwrap

自分の使った環境はこちらです。
OS: Ubuntu18.04
Clojure: 1.9.0

OpenCVのjarとOS依存ファイル

下記のようなコマンドで、UbuntuでJava8向けのOpenCV3.4.2をビルドできます。
sudo apt install cmake ant openjdk-8-jdk
mkdir ~/gitprojects
cd ~/gitprojects
git clone https://github.com/opencv/opencv.git opencv_source
cd opencv_source
git checkout tags/3.4.2
mkdir build
cd build
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/
cmake -D BUILD_SHARED_LIBS=OFF ..
make -j4

ビルドしてできたjarファイルとOS依存ファイル(Linuxなのでsoファイル)を後で利用します。
ls ~/gitprojects/opencv_source/build/lib/libopencv_java342.so
ls ~/gitprojects/opencv_source/build/bin/opencv-342.jar

方法

OpenCvでwebカメラを開き、縦横ピクセル数を表示するプロジェクトの作り方を説明します。

今回はclj-opencv-clj-project-practiceというプロジェクトを作ります。プロジェクト名でディレクトリを作り、その中に移動します。
cd ~/gitprojects
mkdir clj-opencv-clj-project-practice
cd clj-opencv-clj-project-practice

libディレクトリを作り、OpenCVのファイルを配置します。
cp ~/gitprojects/opencv_source/build/lib/libopencv_java342.so lib/
cp ~/gitprojects/opencv_source/build/bin/opencv-342.jar lib/

下記のようなdeps.ednファイルを作成し、libディレクトリに配置したOpenCV 3.4.2を利用できるようにします。
ライブラリのパス(java.library.path)を指定するためのjvm-optsはaliasの一部として記述する必要があります。
deps.edn
{:deps {local-file/opencv {:local/root "lib/opencv-342.jar"}}
 :aliases {:local-opencv {:jvm-opts ["-Djava.library.path=lib"]}}}

OpenCVを利用してカメラの幅と高さを表示するプログラムを作成します。
「(clojure.lang.RT/loadLibrary org.opencv.core.Core/NATIVE_LIBRARY_NAME)」を記述しないと、OpenCVの関数が読み込めていない状態になるので、注意が必要です。
(leiningenのproject.cljには、injectionとして上記の設定を書けるのですが、cljのednには現状そのような昨日が無さそうなので、プログラム内に記述します。)
src/main.clj
(ns main
  (:import [org.opencv.core Core Mat]
           [org.opencv.videoio VideoCapture]))

(clojure.lang.RT/loadLibrary org.opencv.core.Core/NATIVE_LIBRARY_NAME)

(def mat-frame (new Mat))
(def cv-camera (new VideoCapture 0))

(defn -main []
  (prn :hello-opencv Core/VERSION Core/NATIVE_LIBRARY_NAME)
  (.read cv-camera mat-frame)
  (prn :camera-image-size (.cols mat-frame) (.rows mat-frame)))

エイリアスを指定して実行します。
エイリアスのオプションは-mでメインファイルを指定する前に渡す必要があります。
clj -O:local-opencv -m main

成功すればカメラの横と縦のピクセル数を表示してくれます。


カメラから画像を取得して内容を確認しているので、OpenCV Javaに関する他の機能も使える状態になっていると思います。

まとめ

cljプロジェクトでOpenCVを使えました。

何かの参考になれば嬉しいです。

0 件のコメント :