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.
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.)
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()