Çizgileri takip eden araçlar için çoğu zaman sensörler kullanılır. Ancak şimdiki makalemde sensör kullanmadan sadece görüntü işleyerek kameradan sarı şeritleri tespit edebilen basit bir Python uygulaması hazırlayacağım. Bu tarz bir projeyi kolayca Raspberry ye yükleyerek şerit takip edebilen bir araç yapmanız mümkün olabilir.

Kodlara geçmeden önce izlediğim yola adım adım sırasıyla göz atalım:

  1. Gerekli kütüphaneleri eklemek ve kamerayı çağırmak
  2. Görüntüyü yeniden boyutlandırmak
  3. Görüntüyü HSV boyutuna geçirmek ( image = cv2.cvtColor(image, cv2.COLOR_RGB2HLS) )
  4. Sarı rengi tespit etmek için bir filtre yaratmak ve görüntüye uygulamak
  5. Gürültüleri azaltmak için resmi blur'lamak
  6. Görüntüyü binary görüntüye çevirmek için OTSU eşikleme kullanmak.
  7. Elde edilen görüntüden sınırları tespit etmek, karakterize etmek ve sınırları çizmek.
  8. Karakterize edilen şekillerin orta noktalarını kullanarak kullanıcıyı yönlendirmek. (Kullanıcı = Robot, insan vb.)

Kodlar

from __future__ import print_function
from imutils.object_detection import non_max_suppression
from imutils import paths

import numpy as np
import imutils
import cv2
import sys
import os
import threading
import time

run = False

def sesCal(dosya):
	global run
	os.system('aplay '+ dosya +'.wav')
	time.sleep(3)
	run = False

camera = cv2.VideoCapture(0)

Gerekli kütüphanelerimiz ekledik, ses çalabilmek için fonksiyonumuzu oluşturduk ve kameramızı çağırdık.
Çağırılan kamerada birden fazla görüntü bulunuyor demektir. Bunları bir dizi gibi düşünüp While döngüsü yardımıyla her bir Frame i işleyerek istediğimiz programı elde edebiliriz.

while True:
	
	ret, image = camera.read()
	image = imutils.resize(image, width=300)
	image = cv2.cvtColor(image, cv2.COLOR_RGB2HLS)
	
	lower = np.uint8([90, 20,   50])
	upper = np.uint8([100, 170, 200])
	yellow_mask = cv2.inRange(image, lower, upper)
	yellow = cv2.bitwise_and(image, image, mask = yellow_mask)
	yellow = cv2.cvtColor(yellow, cv2.COLOR_BGR2GRAY)

	blur = cv2.GaussianBlur(yellow,(5,5),0)

	ret,th1 = cv2.threshold(yellow,35,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
	ret1,th2 = cv2.threshold(th1,127,255,cv2.THRESH_TOZERO)
	
	_, contours, hierarchy = cv2.findContours(th2,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

	image = cv2.cvtColor(image, cv2.COLOR_HLS2RGB)

Frame'i yeniden boyutlandırdık, HSV uzayına geçip sarı rengi ayırt etmek için maskeleme uyguladık, gürültüleri gidermek için Blur'ladık ve son olarak da görüntüyü Binar görüntüye çevirdik. Artık elimizde görüntüdeki sarı renkler kalmış oldu. Hemen arkasından bu sarı renklerin sınırlarını belirtmek ve bilgisayara tanıtabilmek için cv2.findContours() methodunu kullanarak contours değişkenine attık. Resmi tekrar RGB uzayına getirdik.


Artık elimizde görüntüden sadece sarı renkler kalmış oldu. Bu renklerden karakterize edilmiş şekiller elde etmek için

	if len(contours)>0:
		c = max(contours, key=cv2.contourArea)
		M = cv2.moments(c)
		area = cv2.contourArea(c)

cv2.moments(c) komutu karakterize edilmiş şekiller elde etmemizi sağlar. Böylece bu karakterize edilmiş şekillerden orta noktalar elde edebilr ve bu noktaları kullanarak algoritmalar oluşturabiliriz. Böylece orta nokta ekranda belirli bir aralıktan küçükse sağa büyüse sola gidilmesi gerektiği söyleyebileceğiz. Tabii ki görüntüde hala istenmeyen sarı renklerden oluşmuş ve karakterize edilmiş şekiller olabilir bunları elemek için şekillerin alanlarını cv2.contouArea(c) komutu yardımıyla tespit ediyoruz ve belirli bir alan değeri altındakileri eliyoruz. Bunun için şu komutları kullanıyoruz

		if area > 2000:
			cx = int(M['m10']/M['m00'])
			cy = int(M['m01']/M['m00'])
			
			cv2.line(image,(cx,0),(cx,720),(255,0,0),1)
			cv2.line(image,(0,cy),(1280,cy),(255,0,0),1)

			cv2.circle(image,(cx,cy), 3, (0,0,255), -1)
			cv2.drawContours(image, contours, -1, (0,255,0), 2)

			if cx < 100:
				print('sol')
				if not run:
					run = True
					threading.Thread(target=sesCal, args=("sol", )).start()

			elif cx > 200:
				print('sag')
				if not run:
					run = True
					threading.Thread(target=sesCal, args=("sag", )).start()
			else:
				print('duz git')

Artık karakterize edilmiş asıl şekillerin orta noktalarını elde ettik ve ufak bir algoritma parçacığı ile belirli değerlerden küçükse sola büyükse sağa gibi basitçe kullanıcıya sesli uyarı vermiş olduk.


Program çalışırken ses dosyası çalıştırmak görüntü işleme işleminin duraklamasına sebep olacağından ses çalma işlemini ayrı bir thread ile yapıyoruz. Son olarak rutin komutlarımızı ekleyerek programımızı çalışmaya hazır hale getirmiş oluyoruz.

	cv2.imshow("input", image)
	key = cv2.waitKey(10)
	if key == 27:
		break
	
cv2.destroyAllWindows()
cv2.VideoCapture(0).release()

Projenin tamamını indirmek için : 

DOWNLOAD