ProcessingでPGM形式の画像を扱いたかった話

すっきりとした扱い方はできなかったという話.
今回は読み込みしか行わなかったけど,同様な手順で書き込みもできるはず(確認はしていない).
結論から言うと,PGM形式の画像はProcessingのloadImageで読み込むことはできず,OpenCVを使って一旦png形式にしてからPImage型の変数に読み込んだ.
以下はそれまでの過程.具体的な方法だけ知りたい人は一番最後だけ見るべきかも.

 
そもそもPGM形式とは何かについては,WikipediaPGM Format Specificationを参照.
 
1.ProcessingのloadImage
最初にProcessing標準のloadImageで読み込めないか調べてみる.公式リファレンスによると,読み込めるのは4種類で.gif,.jpg,.tga,.pngのみだということがわかった.
 
2.OpneCV for Processing
ProcessingのライブラリにOpenCV for Processingというものがある.
これはProcessingのスケッチブックから[スケッチ]->[ライブラリをインポート…]->[ライブラリを追加]から簡単に入れることができる.
しかし,試してみるとこれもPGM形式を読み込めないことがわかった.
Githubにソースコードがあるので覗いてみると,OpenCVクラスのloadImageメソッドはPAppletクラスのloadImageを呼び出しているだけだと分かった.つまり標準のloadImageと動作は同じ.
参考:OpenCV.javaの1191行目あたり
 
3.Atelier HypermédiaのProcessing ,Java 用OpenCVライブラリ
なにか他に方法はないかと探していると,あるサイトが見つかった.
ProcessingとJava用のOpenCVライブラリを提供しているらしい.
loadImageメソッドの説明を読むと,対応フォーマットは以下のようになっていることが分かった.

  • Windows bitmaps – BMP, DIB
  • JPEG files – JPEG, JPG, JPE
  • Portable Network Graphics – PNG
  • Portable image format – PBM, PGM, PPM
  • Sun rasters – SR, RAS
  • TIFF files – TIFF, TIF

今度はloadImageでPGM形式が読み込めそうであることが分かった.
”download the OpenCV release version 1.0”に不安を覚えながら(今の最新版は3.2.0)インストールすると,予想通りエラーが起きた.以下がその時のエラーメッセージ
A library relies on native code that’s not available.
Or only works properly when the sketch is run as a 32-bit application.
ん?32bit使えって?じゃあ面倒だけど32bit版のProcessing入れるか…
で,32bit版で表示されたメッセージがこちら
A library relies on native code that’s not available.
Or only works properly when the sketch is run as a 64-bit application.
そもそもOpenCV1.0を入れさせる時点から嫌な予感はしていた.OpenCVのバージョンを変えたり色々試したけど,これ以上はどうすれば良いのかわからなくなったため,このライブラリは諦めた.
 
4.公式のOpenCV
前述のライブラリで最新版のOpenCV3.2.0を入れたとき,Java用にopencv-320.jarとopencv_java.dllが用意されていることに気付いた.Java用に用意されているのならProcessingから読み込めるはずと思い,試してみた.
最初にスケッチ(.pde)があるところにcodeというフォルダを作成し,そこにopencv-320.jarとopencv_java320.dllというファイルを置く.opencv-320.jarとopencv_java320.dllはopencv/build/javaに入っている.パスを合わせないとエラーが出るし,最新版ならバージョン名が変わるので,使う人は適宜そのあたりを修正して使用してほしい.
 
以下は使い方.スケッチの先頭にはimport文を書く必要がある.

import org.opencv.core.*;

Javaに上記のファイルのパスを通す必要がある.これは以下のようなコードで設定できる.

System.setProperty("java.library.path",sketchPath()+"\\code");

ちなみに,sketchPathメソッドは.pdeファイルのあるフォルダの絶対パス.
ライブラリの読み込みは

System.loadLibrary("opencv_java320");

として行う.拡張子の.dllは要らない.
読み込みと書込みはそれぞれ以下のように書くことができる.

mat=org.opencv.imgcodecs.Imgcodecs.imread(path+"\\data\\"+fileName);
org.opencv.imgcodecs.Imgcodecs.imwrite(path+"\\data\\"+fileName.replace(".pgm",".png"),mat);

fileNameには”sample1.pgm”のような文字列,pathにはsketchPath()の結果が入っている想定.
これによりPGM形式をPNG形式に変換することができる.
 
結果として,以下のようなメソッドを作成した.

void convertPgmToPng(String fileName){
  String path=sketchPath();
  Mat mat;
  System.setProperty("java.library.path",path+"\\code");
  System.loadLibrary("opencv_java320");
  mat=org.opencv.imgcodecs.Imgcodecs.imread(path+"\\data\\"+fileName);
  org.opencv.imgcodecs.Imgcodecs.imwrite(path+"\\data\\"+fileName.replace(".pgm",".png"),mat);
}

これにより変換ができた.あとはこのメソッドを実行した後にloadImage(fileName.replace(“.pgm”,”.png”))みたいに読み込めば使える.
 
画像工学,ヒストグラムを作れという課題自体より,PGM形式の扱いの方が難しい気がした.