ちょっと仕事で画像処理を使う機会が出たので、学生実験以来にOpenCVに触ってみる。静的型付けではないPythonは嫌いで、今更C++で頑張るのもきついので、Javaでやってみた。公式にサポートされているのは、この3つのようだが、Javaに関する情報は少ないので、テストコードを載せてみる。
公式にJava対応のラッパーが用意されているが、Gradleで入らないので、JavaCVを使用することにした。
build.gradleのdependenciesに追加
implementation group: 'org.bytedeco', name: 'javacv-platform', version: '1.5.1'
テストコード
import java.util.Arrays;
import org.bytedeco.opencv.global.opencv_highgui;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.RectVector;
import org.bytedeco.opencv.opencv_core.Scalar;
import org.bytedeco.opencv.opencv_objdetect.CascadeClassifier;
import org.bytedeco.opencv.opencv_videoio.VideoCapture;
public class DetectionTest {
public static void main(String[] args) {
// 分類器
// https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_frontalface_default.xml
String faceCascade = "C:\haarcascades\haarcascade_frontalface_default.xml";
CascadeClassifier faceDetector = new CascadeClassifier(faceCascade);
// Webカメラの読み込み(普通はID:0のようだ)
VideoCapture cap = new VideoCapture(0);
Mat frame = new Mat();
// 動画から1フレームを抽出
while (cap.read(frame)) {
// 一応コピーを作成
Mat out = new Mat(frame);
// 検出結果の収納先(Rectの集合クラス)
RectVector detected = new RectVector();
// 検出処理
faceDetector.detectMultiScale(frame, detected);
// 検出結果の範囲を描画
Arrays.stream(detected.get()).forEach(r -> opencv_imgproc.rectangle(out, r, new Scalar(0, 255, 0, 0)));
// GUIに表示
opencv_highgui.imshow("Web camera", out);
// キーボードのqが押されたら終了
int key = opencv_highgui.waitKey(1);
if (key == 'q') {
break;
}
}
// リソースのクローズ
cap.release();
opencv_highgui.destroyAllWindows();
}
}
分類器にhaarcascade_eye.xmlを指定すれば瞳認識もできる。ちょっと試した感じでは顔認識は結構優秀だが、瞳認識は余計なところまで検出される場合が結構あるようだ。それにしてもこんなに簡単にできるのはすごい。