OpenCV Renk Tespiti Obje Takibi

OpenCV Renk Tespiti Obje Takibi

Bu projede kamera aygıtından alınan görüntü üzerinde belirlediğimiz bazı renkleri tespit edecek ve bu renge sahip objeleri işaretleyeceğiz. Öncelikle bir renk aralığı belirleyeceğiz daha sonra kamera aygıtından yakalanan RGB renk uzayına sahip görüntüyü HSV renk uzayına çevireceğiz. Görüntü üzerinde eşikleme, aşındırma ve genişletme operatörlerini uygulayacağız. Kenar bulma gibi metotları kullanarak renklerin ayrımını tespit edip nesneleri işaretleyeceğiz.

Renk tespiti için HSV uzayını kullanacağız, RGB renk uzayında yapılacak olan threshold HSV renk uzayında yapılacak threshold a göre yetersizdir. HSV de H (HUE) değeri daha ayırt edilebilir şekilde değiştiği için farklı renkli objelerin resimde tespiti çok daha kolay olmaktadır. HSV uzaydaki renk kodları aralığını aşağıdaki görselden tespit edebilirsiniz. Proje 2 adet sınıftan oluşacak, birincisi Frame’ler ve görüntülenecek olan kamera görüntüsünü yönetecek sınıf, diğer ise renk tespitini ve işaretleme gibi işlemleri yerine getirecek sınıf.

41

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
import org.opencv.core.Mat;

//Kameradan alınan ve işlenen görüntüler jpanel üzerinde görüntülenecek
class Panel extends JPanel {
	private static final long serialVersionUID = 1L;
	private BufferedImage image;
 
	public Panel() {
		super();
	}
	private BufferedImage getimage() {
		return image;
	}
	public void setimage(BufferedImage newimage) {
		image = newimage;
		return;
	}
 
	public void setimagewithMat(Mat newimage) {
		image = this.ConvertImage(newimage);
		return;
	}
 
	/* Mat nesnesini frame içerisinde göstermek için BufferedImage tipine
	çeviriyoruz*/
	public BufferedImage ConvertImage(Mat matrix) {
		// Mat nesnesinin sütun, satır ve boyutunu BufferedImage nesnesi içintutuyoruz
		int cols = matrix.cols();
		int rows = matrix.rows();
		int elemSize = (int) matrix.elemSize();
		byte[] data = new byte[cols * rows * elemSize];
		int type;
		matrix.get(0, 0, data);
		// Mat nesnesinin kaç kanallı, hangi renk uzayında olduğunu tespit ediyoruz.
		switch (matrix.channels()) {
		// Tek kanallı gri renk uzayına sahip matris
		case 1:
			type = BufferedImage.TYPE_BYTE_GRAY;
			break;
		// Üç kanallı BGR renk uzayına sahip matris
		case 3:
			type = BufferedImage.TYPE_3BYTE_BGR;
	/*
	 * Opencv rgb renk uzayını bgr olarak tuttuğu için görüntülemede
	 * düzgün bir görüntü elde etmek amacıyla rgb uzayına çeviriyoruz
	 */
			byte b;
			for (int i = 0; i<data.length; i = i + 3) {
				b = data[i];
				data[i] = data[i + 2];
				data[i + 2] = b;
			}
			break;
		default:
			return null;
		}
		BufferedImage image2 = new BufferedImage(cols, rows, type);
		image2.getRaster().setDataElements(0, 0, cols, rows, data);
		return image2;
	}
 
	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
 
		BufferedImage temp = getimage();
 
		if (temp != null)
			g.drawImage(temp, 10, 10, temp.getWidth(), temp.getHeight(), this);
	}
}

Renk tespitini yapacak olan ikinci sınıf.

import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import org.opencv.videoio.VideoCapture;

public class Detector {

	public static void main(String arg[]) {
		System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

		// Anlıkolarakyakalanankameragörüntülerinigöstereceğimiz frame ve panel
		JFrame cameraFrame = new JFrame("Anlık kamera görüntüsü");
		cameraFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		cameraFrame.setSize(640, 480);
		cameraFrame.setBounds(0, 0, cameraFrame.getWidth(), cameraFrame.getHeight());
		Panel panelCamera = new Panel();
		cameraFrame.setContentPane(panelCamera);
		cameraFrame.setVisible(true);

		// İşlenecekgörüntünün threshold uygulandıktan sonraki halini
		// göstereceğimiz frame ve panel
		JFrame thresholdFrame = new JFrame("Threshold görüntü");
		thresholdFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		thresholdFrame.setSize(640, 480);
		thresholdFrame.setBounds(0, 0, cameraFrame.getWidth(), cameraFrame.getHeight());
		Panel panelThreshold = new Panel();
		thresholdFrame.setContentPane(panelThreshold);
		thresholdFrame.setVisible(true);

		// Video akışıiçin, 0 ilevarsayılankamerayıbaşlatacağız
		VideoCapture capture = new VideoCapture(0);
		// Parametreleri atıyoruz
		/*capture.set(3, 1366);
		capture.set(4, 768);
		capture.set(15, -2);*/
		// Saf kameragörünrüsü
		Mat webcam_image = new Mat();
		// Hsv renk uzayında görüntüsü
		Mat hsv_image = new Mat();
		// 1. ve 2. threshold
		Mat thresholded = new Mat();
		Mat thresholded2 = new Mat();
		// Kameradan görüntü oku
		capture.read(webcam_image);
		// Kameradan alınan görüntüleri gösterecek olduğumuz frame boyutları
		// kameradan okunang örüntüye göre ayarlanıyor.

		cameraFrame.setSize(webcam_image.width() + 50, webcam_image.height() + 50);
		thresholdFrame.setSize(webcam_image.width() + 50, webcam_image.height() + 50);

		Mat array255 = new Mat(webcam_image.height(), webcam_image.width(), CvType.CV_8UC1);
		array255.setTo(new Scalar(255));
		Mat distance = new Mat(webcam_image.height(), webcam_image.width(), CvType.CV_8UC1);

		List<Mat> lhsv = new ArrayList<Mat>(3);
		Mat circles = new Mat();
		// Renktespitiburadabelirttiğimizminve max değerleregöreyapılacak
		// hsvuzayındaverdiğimizrenktonlarıarasındaki her renktespitedilecektir.
		// Renkaralıklarıiçinhsvrenktablolarınagözatabilirsiniz.

		Scalar minColor = new Scalar(5, 100, 100, 0);
		Scalar maxColor = new Scalar(10, 255, 255, 0);
		// Kamera aygıtı çalışıyor ise
		if (capture.isOpened()) {
			while (true) {
				capture.read(webcam_image);
				// Bir görüntü okunmuş ve boşdeğilse
				if (!webcam_image.empty()) {
					// Kameradan okunan görüntü hsv renk uzayına dönüştürülür
					Imgproc.cvtColor(webcam_image, hsv_image, Imgproc.COLOR_BGR2HSV);
					Core.inRange(hsv_image, minColor, maxColor, thresholded);

					// Erode ve dilate işlemi uygulanır yapısal element ölçüleri
					// iki işlemdede aynıdır
					Imgproc.erode(thresholded, thresholded,
							Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(8, 8)));
					Imgproc.dilate(thresholded, thresholded,
							Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(8, 8)));
					/*
					 * Split metodu
					 * ilegörüntüüzerindekihistogramlarıparçalıyoruz. Matrisin
					 * her boyutu ayrı ayrı nesnelere atanıyor.
					 */
					Core.split(hsv_image, lhsv);
					Mat S = lhsv.get(1);
					Mat V = lhsv.get(2);
					// dizilerarası element farklarıhesaplıyoruz
					Core.subtract(array255, S, S);
					Core.subtract(array255, V, V);
					S.convertTo(S, CvType.CV_32F);
					V.convertTo(V, CvType.CV_32F);
					// 2 boyutluvektörlerimizinbüyüklüğünühesaplıyoruz
					Core.magnitude(S, V, distance);
					/*
					 * Verilendeğerlerarasında thresholding uyguluyor.
					 * pikselindeğeriverilendeğerlerarasındaise o
					 * piksel,beyazdeğilsesiyahyapılıyor.
					 */
					Core.inRange(distance, new Scalar(0.0), new Scalar(200.0), thresholded2);
					Core.bitwise_and(thresholded, thresholded2, thresholded);
					// thresholded içingaussian blur filtresiuyguluyoruz
					Imgproc.GaussianBlur(thresholded, thresholded, new Size(9, 9), 0, 0);
					// Şeklindışhatları
					List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
					Imgproc.HoughCircles(thresholded, circles, Imgproc.CV_HOUGH_GRADIENT, 2, thresholded.height() / 8,
							200, 100, 0, 0);
					// thresholding sonrasınesnenin binary
					// haliüzerindebağlınoktalarıtesiğediyoruz
					Imgproc.findContours(thresholded, contours, thresholded2, Imgproc.RETR_LIST,
							Imgproc.CHAIN_APPROX_SIMPLE);
					// Nesneninkonumunaaşağıdakirenkileçiziyoruz
					Imgproc.drawContours(webcam_image, contours, -2, new Scalar(10, 0, 0), 4);

					/*
					 * Panellerüzerinegörünrüleriatayıp frame'lerin
					 * tekrardançizilmesinisağlıyoruz
					 */
					panelCamera.setimagewithMat(webcam_image);
					panelThreshold.setimagewithMat(thresholded);
					cameraFrame.repaint();
					thresholdFrame.repaint();

				} else {
					JOptionPane.showMessageDialog(null, "Kamera aygıtına bağlanılamadı!");
					break;
				}
			}
		}

	}

}