Computer Vision の世界でちょー有名なライブラリ。
PythonやC++で用いるのが当然視されているものですが、Java bindingも公式で提供されています。試してみました。
JavaCV、というラッパーがあるのも知っていますが、公式で提供されているならまずはそちらを使ってみようと。
公式ページにJava bindingの説明があるのですが、……これ、自分でビルドしなければ使えないって誤解されそう。何故プレビルドのバイナリがちゃんとある(jarもJNI DLLも揃っている)って最初に書いていないんだろう。
プレビルドのバイナリ、ちゃんとあります。
自己展開書庫になっている最新リリースをダウンロードしてフォルダに内容展開すれば、jarもdllも入ってます。
そのjarをclasspathに置いて、JNIのお作法通りSystem.loadLibrary()でdllをロードするだけで使えます。
面倒なインストールとかいらないです。JNI自体が面倒じゃん、というのは置いておいて。
《2024/6/20追記》
プレビルドのバイナリに入っているjarには基本的な機能のパッケージだけが入っているようです。org.opencv.text などは入っていませんでした。そういうパッケージが必要な場合は自分でビルドする必要があるのでしょう。もしくは、JavaCVを使うか。
以下メモ書き。
- Mat → BufferedImageの変換にImageIOを通す必要はありません。HighGui.toBufferedImage()というそのものズバリのユーティリティクラスが用意されています。ImageIOを通すよりずっと高速です。……もしかしたら何か制限があるから(CV_8U縛りになったりとか)「Mat → BufferedImageの変換にはImageIOを通す」という方法がメジャーなのかもしれませんが。《2024/6/20追記/HighGui.toBufferedImage()は、MatがCV_8U1のグレースケールかCV_8U3のBGRの場合にBufferedImageに高速に変換する実装になっていました。それ以外の場合はHighGui.toBufferedImage()にかける前にMatを変換する必要があります。ちなみにその実装を参考にすれば、CV_8U4のBGRAのMatから4BYTE_ARGBのBufferedImageに変換するように機能拡張するのは簡単に実現できます》
- BufferedImage → Mat の変換にも、CV_8U限定で良ければ、ImageIOを通す必要はありません。ByteBuffer.allocateDirect()でダイレクトバッファを確保して、そこにBufferedImageのピクセル情報を1ピクセルずつ書き込んで、それからMatを構築する方が、ずっとずっと高速です。allocateDirect()は扱いづらいのでちょっと、という場合は、少しパフォーマンスは落ちますがJava22から正式仕様となったFFM APIのArenaを使ってもOKです。CV_8U以外は少し工夫が要ったり、その結果ImageIOを通す方が楽だったりするかもですが。
- imread()は日本語を含むパスを処理できません。この対策として、JavaでImageIOを使ってBufferedImageを作り、Matに変換するという方法がありますが、JavaでイメージデータをByteArrayOutputStreamでバイト配列に読み込んで(このときにはFiles.copy()が使えます。ちょー簡単)、そのバイト配列をMatOfByteに入れて、そのMatOfByteからMatを作る、という方法でも行けます。メモリは食いますがこの方がImageIOを使うより速いです。《2024/6/20追記/前述のBufferedImage → Mat の変換でも良いです。メモリを食うのは同じ》
- imwrite()も日本語を含むパスを処理できません。この対策は、上記の「Mat → BufferedImageの変換」で良いはずです。
- この「Mat → BufferedImageの変換」を使って、ImageIOでは対応していないがopenCVでは対応しているイメージ形式をJavaに読み込む、ということも出来ます。
Matさえなんとかなったら後はいろいろ出来るはず。