OpenCV ile GUI Uygulamalar

OpenCV ile  Java GUI Uygulamalar

Uygulamalarda görsellik oldukça önemlidir, geliştirmekte olduğunuz OpenCV projesi müşteri odaklı bir yazılım olabilir ve bu yazılımda yapılan işlemlerin yani işlenen görüntünün, uygulanan filtrelerin veya üzerine çizim yapılan görüntünün anlık olarak kullanıcıya gösterilmesi gerekebilir. Java da GUI (Grafiksel kullanıcı arabirimi) uygulamalar için genellikle swing tercih edilir fakat swing kullanmak zorunda değilsiniz bu bölümde öğreneceklerinizi diğer kütüphaneler ile de kullanabilirsiniz bu konuda bir sınırlama yoktur.

EK BİLGİ: Netbeans kullanıyorsanız ayrıca bir swing kurulumuna ihtiyacınız yoktur projenize new/frame diyerek bir çerçeve ekleyerek tasarım aracını kullanarak grafiksel ara yüzler geliştirebilirsiniz. Eclipse kullanıyorsanız Help menüsünden Install new software.. seçeneğine tıklayarak açılan penceredeki Work with kısmından –All Available Sites– seçiniz, ardından General Purpose Tools seçeneği altından swing bileşenini seçerek kurabilirsiniz.

OpenCV içerisinde GUI işlemleri için bazı sınıflar bulunmaktadır, daha çok C++ geliştiricilerine yönelik olarak eklenen bu sınıflar ve metotlar ile pencere oluşturma ve resim görüntüleme işlemleri yapılabilmektedir. Java ile GUI uygulamalar için çok fazla kütüphaneler olduğu için projelerinizde bunları kullanmanız doğru bir seçim olacaktır zira uygulamalar sadece video oynatmak ve resim görüntülemekten ibaret olmayacaktır.

OpenCV de görüntüleri dijital olarak mat nesneleri içerisinde barındırıyoruz. Bu dijital görüntüyü kullanıcıya göstermek için bu nesne içerisindeki verileri (pikselleri) okuyup, yorumlayıp bir resim haline getirmemiz gerekiyor. Oluşan bu resmi ise bir frame veya panel ile kullanıcıya gösterebiliriz veya okunan görüntüler dosya sistemine yazılır ve Java’daki io sınıfı ile bu görüntü okunarak görüntülenebilir.

Bir örnek yapalım ve kameradan alınan görüntüleri anlık olarak frame üzerinde görüntüleyelim.

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.imgcodecs.Imgcodecs;
import org.opencv.videoio.VideoCapture;

public class Swing {

	static JFrame frame;
	static JLabel lbl;
	static ImageIcon icon;

	public static void main(String[] args) {
		System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
		Mat kameraVerisi = new Mat();
		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) {				
				videoDevice.read(kameraVerisi);
		//Yakalanan görüntüyü önce dönüştür ve frame içerisine yükle
				GoruntuYukle(GoruntuyuDonustur(kameraVerisi));
			}
		} else {
			System.out.println("Video aygıtına bağlanılamadı.");
			return;
		}
	}
	//Mat nesnesini image tipine dönüştür
	private static BufferedImage GoruntuyuDonustur(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(500, 600);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	//Resmi gösterecek label oluşturur
	public static void GoruntuYukle(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();
	}
}

Daha önce yaptığımız gibi video aygıtından bir görüntü aldık, anlık olarak akış sağlamak için bu görüntü alma işlemini döngü içerisine aldık bu sayede sürekli olarak video aygıtından görüntü akışı sağlandı. Alınan görüntü mat nesnesinden belleğe alındı ve image olarak dönüştürüldü, bir dönüşüm işlemi yapmadan mat tipi olarak swing veya diğer Java GUI kütüphaneleri bu görüntüyü işleyemezler.

17

Anlık olarak bir görüntü akışı elde ettik. Bu akış bir biri ardına devam eden görüntülerin birleşmesi ile elde edildi ve bu sayede görüntü üzerinde istediğimiz değişikliği yapabiliriz. Daha önce gördüğümüz, görüntü üzerine şekil çizme veya metin yazdırma işlemlerini de uygulayabiliriz. Bir örnek yapalım ve akıştaki görüntülere müdahale ederek bazı değişiklikler yapalım.

public static void main(String[] args) {
		System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
		Mat kameraVerisi = new Mat();
		VideoCapture videoDevice = new VideoCapture();
		videoDevice.open(0);
		if (videoDevice.isOpened()) {
		//Sonsuz bir döngü ile sürekli olarak görüntü akışı sağlanı
			while (true) {				
				videoDevice.read(kameraVerisi);
				//Metin yaz
				Imgproc.putText(kameraVerisi, "OPENCV & JAVA", new Point(100,300),2, 2, new Scalar(27,228,94));
				//Çizgi çiz
				Imgproc.line(kameraVerisi, new Point(100,250), new Point(400,250), new Scalar(207,28,228));
		//Yakalanan görüntüyü önce dönüştür ve frame içerisine yükle
				GoruntuYukle(GoruntuyuDonustur(kameraVerisi));
			}
		} else {
			System.out.println("Video aygıtına bağlanılamadı.");
			return;
		}
	}

18

Video dosyasından ve ip kameradan görüntü oynatmak için ise daha öncede gördüğümüz gibi VideoCapture sınıfından oluşturulan nesnenin, kurucu metodunda veya Open metodunda video dosyasının veya ip kameranın adresini vermeniz yeterli olacaktır.