OpenCV Nesne Tespiti(Yüz ve Göz Tespiti Örneği)

OpenCV Nesne Tespiti

Daha önce bir yazımda haar cascade kullanarak yüz tespitinin nasıl yapılabileceğini anlatmıştım. Bu yazıda ise daha kapsamlı bir örnek üzerinde aynı anda 2 farklı nesne tanımı yaparak onların tespitini yapacağız. Önceki yazıya buradan ulaşabilirsiniz.

Opencv java yüz tespiti – haar cascade classifier

Nesneyi tespit etmek için öncelikle nesneyi sisteme tanıtmamız ve daha sonra bu tanımlanmış veri setini kullanarak görüntü üzerinde arama yapmamız gerekir. Haar cascade sınıflandırıcı bizden xml dosyası alır bu xml dosyaları bir nesnenin binlerce negatif ve pozitifi ile hazırlanmış veri setidir. Pozitif olarak tanımlanan görüntüler istenilen nesnenin bulunduğu negatif olarak tanımlananlar ise bulunması istenilen nesnenin bulunmadığı görüntülerdir. Daha detaylı bilgi için Haar cascade  algoritmasına göz atabilir ve Haar cascade sınıflandırıcı eğitimleri ile de nasıl nesne tanımlanır öğrenebilirsiniz.

OpenCV içerisinde bir çok nesne hali hazırda öğretilmiş olarak gelir bunlardan yüz ve gözü kullanarak anlık olarak bir yüz ve göz tespiti yapacağız. Açıklamaları kaynak kod üzerinde yapacağım adım adım giderek kurguyu anlayabilirsiniz. Koda geçmeden önce aşağıdaki diğer yazılarımı okumanızı öneririm bu sayede çizim işlemlerini ve gui uygulama geliştirme hakkında bilgi edinebilirsiniz. (Kaynak kod güncelliği için Github reposunu takip edebilirsiniz.)

https://github.com/mesutpiskin/OpenCvObjectDetection

OpenCV Matris Üzerinde Çizim İşlemleri

OpenCV ile GUI Uygulamalar

import java.awt.FlowLayout;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.core.MatOfRect;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.videoio.VideoCapture;
/*
 * CONTACT INFO
 * mesutpiskin.com
 * mesutpiskin@outlook.com
 * 
 * Daha detaylý bilgi için linklere göz atýnýz (SEE ALSO)
 * https://mesutpiskin.com/blog/opencv-ile-gui-uygulamalar.html
 * https://mesutpiskin.com/blog/opencv-matris-uzerinde-cizim-islemleri.html
 * https://mesutpiskin.com/blog/321.html
 * 
 * Comment line language Turkish for translate
 * OpenCV version 3.1
*/
public class DetectFace {
 
	static JFrame frame;
	static JLabel lbl;
	static ImageIcon icon;
 
	public static void main(String[] args) {
		System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
		/*Cascade Classifier için öðretilmiþ veri kümesi, opencv build/etc/haarcascades/ içerisinde yer almaktadýr
		  Daha fazla bilgi için Haar Cascade sýnýflandýrýcýlarýna bakabilirsiniz.
		*/

		CascadeClassifier cascadeFaceClassifier = new CascadeClassifier(
				"D:/Programlar/Opencv/3.1.0/opencv/build/etc/haarcascades/haarcascade_frontalface_default.xml");
		CascadeClassifier cascadeEyeClassifier = new CascadeClassifier(
				"D:/Programlar/Opencv/3.1.0/opencv/build/etc/haarcascades/haarcascade_eye.xml");
		
		CascadeClassifier cascadeNoseClassifier = new CascadeClassifier(
				"D:/Programlar/Opencv/3.1.0/opencv/build/etc/haarcascades/haarcascade_mcs_nose.xml");
	    //CascadeClassifier cascadeMouthClassifier = new CascadeClassifier("OpenCV/haarcascades/haarcascade_mcs_mouth.xml"); haarcascade_mcs_mouth on 2.4.11
		//Varsayýlan kamera aygýtýný baþlat
		VideoCapture videoDevice = new VideoCapture();
		videoDevice.open(0);
		if (videoDevice.isOpened()) {
		//Sonsuz bir döngü ile sürekli olarak görüntü akýþý saðlanýr 	
			while (true) {		
				Mat frameCapture = new Mat();
				videoDevice.read(frameCapture);
				
				//Yakalanan görüntüyü önce dönüþtür ve frame içerisine yükle
				MatOfRect faces = new MatOfRect();
				cascadeFaceClassifier.detectMultiScale(frameCapture, faces);								
				//Yakalanan çerçeve varsa içerisinde dön ve yüzün boyutlarý ölçüsünde bir kare çiz
				for (Rect rect : faces.toArray()) {
					//Sol üst köþesine metin yaz
					Imgproc.putText(frameCapture, "Face", new Point(rect.x,rect.y-5), 1, 2, new Scalar(0,0,255));								
					Imgproc.rectangle(frameCapture, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height),
							new Scalar(0, 100, 0),3);
				}
				
				//Gözleri bul ve bulunan array içerisinde dönerek kare çiz
				MatOfRect eyes = new MatOfRect();
				cascadeEyeClassifier.detectMultiScale(frameCapture, eyes);
				for (Rect rect : eyes.toArray()) {
					//Sol üst köþesine metin yaz
					Imgproc.putText(frameCapture, "Eye", new Point(rect.x,rect.y-5), 1, 2, new Scalar(0,0,255));				
					//Kare çiz
					Imgproc.rectangle(frameCapture, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height),
							new Scalar(200, 200, 100),2);
				}
				
				//Burunlarý bul ve bulunan array içerisinde dönerek kare çiz
				MatOfRect nose = new MatOfRect();
				cascadeNoseClassifier.detectMultiScale(frameCapture, nose);
				for (Rect rect : nose.toArray()) {
					//Sol üst köþesine metin yaz
					Imgproc.putText(frameCapture, "Nose", new Point(rect.x,rect.y-5), 1, 2, new Scalar(0,0,255));				
					//Kare çiz
					Imgproc.rectangle(frameCapture, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height),
							new Scalar(50, 255, 50),2);
				}
				
				//Aðýz bul ve bulunan array içerisinde dönerek kare çiz
			   /*MatOfRect mouth = new MatOfRect();
				cascadeMouthClassifier.detectMultiScale(frameCapture, mouth);
				for (Rect rect : mouth.toArray()) {
					
					Imgproc.rectangle(frameCapture, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height),
							new Scalar(129, 90, 50),2);
				}
				
				*/
				
				//Resmi swing nesnesinde gösterebilmek için önce image haline çevir ve ekrana bas
				PushImage(ConvertMat2Image(frameCapture));
				System.out.println(String.format("%s yüz(FACES) %s göz(EYE) %s burun(NOSE) detected.", faces.toArray().length,eyes.toArray().length,nose.toArray().length));
			}
		} else {
			System.out.println("Video aygýtýna baðlanýlamadý.");
			return;
		}
	}
	//Mat nesnesini image tipine dönüþtür
	private static BufferedImage ConvertMat2Image(Mat kameraVerisi) {
	
		
		MatOfByte byteMatVerisi = new MatOfByte();
		//Ara belleðe verilen formatta görüntü kodlar
		Imgcodecs.imencode(".jpg", kameraVerisi, byteMatVerisi);
		//Mat nesnesinin toArray() metodu elemanlarý byte dizisine çevirir
		byte[] byteArray = byteMatVerisi.toArray();
		BufferedImage goruntu = null;
		try {
			InputStream in = new ByteArrayInputStream(byteArray);
			goruntu = ImageIO.read(in);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		return goruntu;
	}
  	
//Bir frame (çerçeve) oluþturur
	public static void PencereHazirla() {
		frame = new JFrame();
		frame.setLayout(new FlowLayout());
		frame.setSize(700, 600);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	//Resmi gösterecek label oluþturur
	public static void PushImage(Image img2) {
		//Pencere oluþturulmamýþ ise hazýrlanýr
		if (frame == null)
			PencereHazirla();
		//Daha önceden bir görüntü yüklenmiþ ise yenisi için kaldýrýr
		if (lbl != null)
			frame.remove(lbl);
		icon = new ImageIcon(img2);
		lbl = new JLabel();
		lbl.setIcon(icon);
		frame.add(lbl);
		//Frame nesnesini yeniler
		frame.revalidate();
	}
}

Python örneğini yapacak olursak (sadece yüz için);

import cv2

capture = cv2.VideoCapture(0)
cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

while True:

    ret, frame = capture.read()   
    faces = cascade.detectMultiScale(frame, 1.5, 3)

    for (x,y,w,h) in faces:
        cv2.rectangle(frame,(x,y),(x+w,y+h),(255,255,255),2)
       
        
    cv2.imshow('Kamera',frame)
    if cv2.waitKey(30) & 0xff ==27:
        break

capture.release()
cv2.destroyAllWindows()