note


JavaでOpenCVのインストール・eclipseの設定など(Mac OSX)

メモ。
基本的にOpenCVの
Introduction to Java Development の内容です。

・ダウンロード

Sourceforgeからダウンロードできます。
もしくは、Gitコマンドでダウンロード。
%git clone git://github.com/Itseez/opencv.git
%cd opencv
%git checkout

・インストール

[事前準備]
cmakeを入れましょう。僕はhomebrewでいれました。

Sourceforgeからダウンロードした場合、解凍してできたopencvディレクトリに移動。
ビルド用のディレクトリを作ります。
%mkdir build
%cd build

Sourceforgeからダウンロードした場合、解凍してできたopencvディレクトリに移動。
Makefileを作って、コンパイルする。
%cmake -DBUILD_SHARED_LIBS=OFF ..
%make -j8


これで、opencv/build以下にopencv一式がコンパイルされました。


・eclipseの設定

新しいプロジェクトを作成するとする(例に習って、HelloCVとする)。
これにbuild pathを通す。Librariesの設定から、Add Libraryを選択。


eclipse_user_lib


User Libraryを選択。

eclipse_user_lib2

eclipse_user_lib3

eclipse_user_lib4

下の名前はopencv-2.4.4だけど、バージョン違ってたらそれに合わせましょう。

eclipse_user_lib5

次に、JNIライブラリの設定。

eclipse_user_lib6

Jarファイルには、opencv-245.jar(245はバージョンによります) (場所はopencv/build/bin/の中) (245はバージョンによります)を指定。
次に、JNIライブラリの場所を指定。


eclipse_user_lib7

ここは、libopencv_java245.dylib (245はバージョンによります)(場所はopencv/build/lib の中)を指定。
で、この設定したユーザライブラリをプロジェクトのライブラリに指定します。

eclipse_user_lib8


試しに、次のプログラムを作ってコンパイル・実行してみましょう。


import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;

public class Main {
public static void main(String[] args) {
System
.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat m
= Mat.eye(3, 3, CvType.CV_8UC1);
System
.out.println("m = " + m.dump());
}
}



eclipse_run


こうなればオッケー。

・顔認識のサンプルプログラム



最後に、顔認識のプログラムを動かしてみましょう。

[事前準備]
opencv/data ディレクトリをeclipseプロジェクトにコピー。
このdataディレクトリには顔認識に必要な学習ファイルが存在していて、プログラムで使います。

lena

この画像をlena.png という名前でダウンロードして、同じくeclipseプロジェクトの適当な場所にコピー(例: YOUR_PROJECT/resources/とか作って、その中とか)。
次のプログラムを作成。



import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.highgui.Highgui;
import org.opencv.objdetect.CascadeClassifier;

//
// Detects faces in an image, draws boxes around them, and writes the results
// to "faceDetection.png".
//
class DetectFaceDemo {
public void run() {
System
.out.println("\nRunning DetectFaceDemo");

// Create a face detector from the cascade file in the resources
// directory.
CascadeClassifier faceDetector
= new CascadeClassifier(“data/lbpcascades/lbpcascade_frontalface.xml”);
Mat image
= Highgui.imread(“resources/lena.png");

// Detect faces in the image.
// MatOfRect is a special container class for Rect.
MatOfRect faceDetections
= new MatOfRect();
faceDetector
.detectMultiScale(image, faceDetections);

System
.out.println(String.format("Detected %s faces", faceDetections.toArray().length));

// Draw a bounding box around each face.
for (Rect rect : faceDetections.toArray()) {
Core
.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 255, 0));
}

// Save the visualized detection.
String filename
= "faceDetection.png";
System
.out.println(String.format("Writing %s", filename));
Highgui
.imwrite(filename, image);
}
}

public class HelloOpenCV {
public static void main(String[] args) {
System
.out.println("Hello, OpenCV");

// Load the native library.
System
.loadLibrary(Core.NATIVE_LIBRARY_NAME);
new DetectFaceDemo().run();
}
}




実行したら、次のファイルが生成されているはずです。

faceDetection


・おまけ



BufferedImage から Mat オブジェクトへの変換。
imgという名前でBufferedImageのオブジェクトが作成されている場合:

Pixels pixels = ((DataBufferByte)img.getRaster().getDataBuffer()).getData();
Mat mat = new Mat(img.getHeight(),img.getWidth(),CvType.CV_8UC3);
mat.put(0, 0, pixels);

これでmatに画像データがコピーされた行列ができます。
ちなみに
img.getRaster().getDataBuffer() の返り値がDataBufferIntで、
エラー:
java.awt.image.DataBufferInt cannot be cast to java.awt.image.DataBufferByte
が発生した場合(BufferedImageのタイプによります。
この辺この辺を参考に。)、


public byte[] getImageBytesForBufferedImageOfDataTypeSize1(BufferedImage image) {
int[] pixels = new int[image.getWidth()*image.getHeight()];
byte[] bytes = new byte[image.getWidth()*image.getHeight()*3];
DataBufferInt buffer = (DataBufferInt)(image.getRaster().getDataBuffer());

int j =0;
for(int i = 0; i < image.getWidth()*image.getHeight(); i++){
pixels[i] = buffer.getElem(i);

bytes[j] = (
byte)(0xFF & ((pixel[i] & 0x000000FF) >> 0)); //r
bytes[j+1] = (
byte)(0xFF & ((pixel[i] & 0x0000FF00) >> 8)); //g
bytes[j+2] = (
byte)(0xFF & ((pixel[i] & 0x00FF0000) >> 16)); //b
j+=3;
}
return bytes;
}



といった感じで強引にbytes[]に直す。

pixels
= getImageBytesForBufferedImageOfDataTypeSize1(img);
Mat mat = new Mat(img.getHeight(),img.getWidth(),CvType.CV_8UC3);
mat.put(0, 0, pixels);

で、Matオブジェクトが生成できます。


・おまけその2


ということで、AR.Droneと組み合わせて簡易的な顔認識・追従ができます。