Pengantar OpenCV dengan Java

1. Perkenalan

Dalam tutorial ini, kita akan belajar cara menginstal dan menggunakan pustaka visi komputer OpenCV dan menerapkannya ke deteksi wajah waktu nyata.

2. Instalasi

Untuk menggunakan pustaka OpenCV dalam proyek kita, kita perlu menambahkan ketergantungan opencv Maven ke pom.xml kita :

 org.openpnp opencv 3.4.2-0 

Untuk pengguna Gradle, kita perlu menambahkan dependensi ke file build.gradle kita :

compile group: 'org.openpnp', name: 'opencv', version: '3.4.2-0'

Setelah menambahkan pustaka ke dependensi kami, kami dapat menggunakan fitur yang disediakan oleh OpenCV.

3. Menggunakan Perpustakaan

Untuk mulai menggunakan OpenCV, kita perlu menginisialisasi pustaka , yang dapat kita lakukan di metode utama kita :

OpenCV.loadShared();

OpenCV adalah kelas yang menampung metode yang terkait dengan pemuatan paket asli yang diperlukan oleh pustaka OpenCV untuk berbagai platform dan arsitektur.

Perlu dicatat bahwa dokumentasi melakukan hal-hal yang sedikit berbeda:

System.loadLibrary(Core.NATIVE_LIBRARY_NAME)

Kedua panggilan metode tersebut benar-benar akan memuat pustaka asli yang diperlukan.

Perbedaannya di sini adalah bahwa yang terakhir membutuhkan pustaka asli untuk diinstal . Namun, yang pertama dapat menginstal pustaka ke folder sementara jika tidak tersedia pada mesin tertentu. Karena perbedaan ini, yang loadShared metode biasanya merupakan cara terbaik untuk pergi .

Sekarang setelah kita menginisialisasi pustaka, mari kita lihat apa yang bisa kita lakukan dengannya.

4. Memuat Gambar

Untuk memulai, mari muat gambar sampel dari disk menggunakan OpenCV :

public static Mat loadImage(String imagePath) { Imgcodecs imageCodecs = new Imgcodecs(); return imageCodecs.imread(imagePath); }

Metode ini akan memuat gambar yang diberikan sebagai objek Mat , yang merupakan representasi matriks.

Untuk menyimpan gambar yang dimuat sebelumnya, kita dapat menggunakan metode imwrite () dari kelas Imgcodecs :

public static void saveImage(Mat imageMatrix, String targetPath) { Imgcodecs imgcodecs = new Imgcodecs(); imgcodecs.imwrite(targetPath, imageMatrix); }

5. Pengklasifikasi Kaskade Haar

Sebelum mendalami pengenalan wajah, mari kita pahami konsep inti yang memungkinkan hal ini.

Sederhananya, pengklasifikasi adalah program yang berusaha menempatkan pengamatan baru ke dalam kelompok yang bergantung pada pengalaman masa lalu. Pengklasifikasi bertingkat berusaha melakukan ini menggunakan rangkaian beberapa pengklasifikasi. Setiap pengklasifikasi berikutnya menggunakan keluaran dari sebelumnya sebagai informasi tambahan, meningkatkan klasifikasi secara signifikan.

5.1. Fitur Haar

Deteksi wajah di OpenCV dilakukan oleh pengklasifikasi kaskade berbasis fitur Haar.

Fitur haar adalah filter yang digunakan untuk mendeteksi tepi dan garis pada citra. Filter terlihat sebagai kotak dengan warna hitam dan putih:

Filter ini diterapkan beberapa kali ke gambar, piksel demi piksel, dan hasilnya dikumpulkan sebagai satu nilai. Nilai ini adalah selisih antara jumlah piksel di bawah kotak hitam dan jumlah piksel di bawah kotak putih.

6. Deteksi Wajah

Umumnya, pengklasifikasi kaskade perlu dilatih sebelumnya agar dapat mendeteksi apa pun.

Karena proses pelatihan bisa lama dan membutuhkan kumpulan data yang besar, kami akan menggunakan salah satu model terlatih yang ditawarkan oleh OpenCV. Kami akan menempatkan file XML ini di folder sumber daya kami untuk memudahkan akses.

Mari melangkah melalui proses mendeteksi wajah:

Kami akan mencoba mendeteksi wajah dengan menguraikannya dengan persegi panjang merah.

Untuk memulai, kita perlu memuat gambar dalam format Mat dari jalur sumber kita:

Mat loadedImage = loadImage(sourceImagePath);

Kemudian, kami akan mendeklarasikan objek MatOfRect untuk menyimpan wajah yang kami temukan:

MatOfRect facesDetected = new MatOfRect();

Selanjutnya, kita perlu menginisialisasi CascadeClassifier untuk melakukan pengenalan:

CascadeClassifier cascadeClassifier = new CascadeClassifier(); int minFaceSize = Math.round(loadedImage.rows() * 0.1f); cascadeClassifier.load("./src/main/resources/haarcascades/haarcascade_frontalface_alt.xml"); cascadeClassifier.detectMultiScale(loadedImage, facesDetected, 1.1, 3, Objdetect.CASCADE_SCALE_IMAGE, new Size(minFaceSize, minFaceSize), new Size() );

Di atas, parameter 1.1 menunjukkan faktor skala yang ingin kita gunakan, menentukan seberapa besar ukuran gambar dikurangi pada setiap skala gambar. Parameter berikutnya, 3 , adalah minNeighbours. Ini adalah jumlah tetangga yang harus dimiliki calon persegi panjang untuk mempertahankannya.

Akhirnya, kita akan melakukan loop melalui wajah dan menyimpan hasilnya:

Rect[] facesArray = facesDetected.toArray(); for(Rect face : facesArray) { Imgproc.rectangle(loadedImage, face.tl(), face.br(), new Scalar(0, 0, 255), 3); } saveImage(loadedImage, targetImagePath);

Saat kita memasukkan gambar sumber kita, kita sekarang akan menerima gambar keluaran dengan semua wajah yang ditandai dengan persegi panjang merah:

7. Mengakses Kamera Menggunakan OpenCV

So far, we've seen how to perform face detection on loaded images. But most of the time, we want to do it in real-time. To be able to do that, we need to access the camera.

However, to be able to show an image from a camera, we need a few additional things, apart from the obvious — a camera. To show the images, we'll use JavaFX.

Since we'll be using an ImageView to display the pictures our camera has taken, we need a way to translate an OpenCV Mat to a JavaFX Image:

public Image mat2Img(Mat mat) { MatOfByte bytes = new MatOfByte(); Imgcodecs.imencode("img", mat, bytes); InputStream inputStream = new ByteArrayInputStream(bytes.toArray()); return new Image(inputStream); }

Here, we are converting our Mat into bytes, and then converting the bytes into an Image object.

We'll start by streaming the camera view to a JavaFX Stage.

Now, let's initialize the library using the loadShared method:

OpenCV.loadShared();

Next, we'll create the stage with a VideoCapture and an ImageView to display the Image:

VideoCapture capture = new VideoCapture(0); ImageView imageView = new ImageView(); HBox hbox = new HBox(imageView); Scene scene = new Scene(hbox); stage.setScene(scene); stage.show();

Here, 0 is the ID of the camera we want to use. We also need to create an AnimationTimerto handle setting the image:

new AnimationTimer() { @Override public void handle(long l) { imageView.setImage(getCapture()); } }.start();

Finally, our getCapture method handles converting the Mat to an Image:

public Image getCapture() { Mat mat = new Mat(); capture.read(mat); return mat2Img(mat); }

The application should now create a window and then live-stream the view from the camera to the imageView window.

8. Real-Time Face Detection

Finally, we can connect all the dots to create an application that detects a face in real-time.

The code from the previous section is responsible for grabbing the image from the camera and displaying it to the user. Now, all we have to do is to process the grabbed images before showing them on screen by using our CascadeClassifier class.

Let's simply modify our getCapture method to also perform face detection:

public Image getCaptureWithFaceDetection() { Mat mat = new Mat(); capture.read(mat); Mat haarClassifiedImg = detectFace(mat); return mat2Img(haarClassifiedImg); }

Now, if we run our application, the face should be marked with the red rectangle.

We can also see a disadvantage of the cascade classifiers. If we turn our face too much in any direction, then the red rectangle disappears. This is because we've used a specific classifier that was trained only to detect the front of the face.

9. Ringkasan

Dalam tutorial ini, kita belajar bagaimana menggunakan OpenCV di Java.

Kami menggunakan pengklasifikasi kaskade terlatih untuk mendeteksi wajah pada gambar. Dengan bantuan JavaFX, kami berhasil membuat pengklasifikasi mendeteksi wajah secara real-time dengan gambar dari kamera.

Seperti biasa, semua contoh kode dapat ditemukan di GitHub.