OpenCV ile Portakalın Peşinde
Bu yazımda bir önceki yazımda ele aldığım kodlardan yararlanacak, sadece bir kaç küçük değişiklik yapacağım.
Bu kez çember içine alarak işaretlediğimiz nesnenin (portakalın) merkez noktasını izlenebilir hale getireceğiz. İzlemeyi, en son ardışık 50 merkez noktasını çizgilerle birbirine birleştirerek yapacağız.
Bu betikte 2 kütüphaneye daha gereksinim var: collections ve numpy.
collections kütüphanesinin deque sınıfı her iki ucundan eleman eklenebilen ve önceden belirtilmişse maksimum eleman saısı sabit kalan nesneler üretir. Numpy kütüphanesini ise izleme çizgilerinin kalınlığını hesaplarken karekök almada kullanacağız. Onun yerine math kütüphanesini de kullanabilirdik ama, bu tür çalışmalarda numpy‘yi el altında tutmamızda büyük yarar var.
Bu kez kaynak kodları bir bütün halinde vereceğim. Sadece önceki örnekle karşılaştırdığımızda değişen satırları açıklamam yeterli olacak.
Kodlar aşağıda. Açıklamaları da onun altına ekledim.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
import cv2 import imutils from collections import deque import numpy as np video_file = '' # ''ab03.mp4' # if given frames are read from file WIDTH = 800 # width of the windows NO_OF_POINTS=50 # ONLY_MAX = False # if True only the max circle is drawn GREEN_RANGE = ((29, 86, 6), (64, 255, 255)) RED_RANGE = ((139, 0, 0), (255, 160, 122)) BLUE_RANGE = ((110, 50, 50), (130, 255, 255)) ORANGE_RANGE = ((160, 100, 47), (179, 255, 255)) YELLOW_RANGE = ((10, 100, 100), (40, 255, 255)) colorLower, colorUpper = YELLOW_RANGE # select color range if len(video_file) == 0: kamera = cv2.VideoCapture(0) # default web camera=0 else: kamera = cv2.VideoCapture(video_file) # read from file pts= deque(maxlen=NO_OF_POINTS) cv2.namedWindow('frame') cv2.moveWindow('frame', 10, 10) # 'frame' window position # cv2.namedWindow('mask') # cv2.moveWindow('mask', WIDTH + 50, 10) # 'mask' window position while True: (ok, frame) = kamera.read() # if filename is given but frames cannot be read then exit if len(video_file) > 0 and not ok: break frame = imutils.resize(frame, WIDTH) hsv = cv2.GaussianBlur(frame, (25,25), 0) hsv = cv2.cvtColor(hsv, cv2.COLOR_BGR2HSV) mask = cv2.inRange(hsv, colorLower, colorUpper) mask = cv2.erode(mask, None, iterations=3) mask = cv2.dilate(mask, None, iterations=3) mask_copy = mask.copy() contours = cv2.findContours(mask_copy, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2] center = None if len(contours) > 0: cmax = max(contours, key=cv2.contourArea) for ctr in contours: (x, y), radius = cv2.minEnclosingCircle(cmax) mts = cv2.moments(cmax) center = int(mts['m10']/mts['m00']),int(mts['m01']/mts['m00']) if radius >= 40: # draw circle if radius>40 px cv2.circle(frame, (int(x), int(y)), int(radius), (255, 255, 0), 4) pts.appendleft(center) # draw tracked points in deque for i in range(1,len(pts)): if pts[i] and pts[i-1]: # thickness=3 thickness = int(np.sqrt(NO_OF_POINTS / float(i + 1)) * 1.1) cv2.line(frame,pts[i-1],pts[i],(0,255,255),thickness) cv2.imshow("frame", frame) # cv2.imshow("mask", mask) key = cv2.waitKey(1) & 0xFF if key == ord('q') or key == 27: break # release all objects and free memory kamera.release() cv2.destroyAllWindows() |
3 ve 4 numaralı satırlarımızda yeni kütüphaneleri içe aktarıyoruz.
7. satırdaki WIDTH değerini 800 yaptım. Çünkü bu kez sadece bir pencereyi görselleştireceğiz.
8. satırda NO_OF_POINTS = 50 satırını ekledim. Bu sabit, merkez noktalarından kaç tanesini izleyeceğimizi belirliyor. Sayıyı azaltırsak izleme çizgilerimiz daha kısa, çoğaltırsak daha uzun olacaktır.
9. satırdaki ONLY_MAX artık kullanılmayacak. Çünkü sadece tek bir nesneyi (en büyük olanı) izleyeceğiz.
36. satıra kadar bir değişiklik yok. Burada frame isimli çerçevenin görüntüsünü cv2.GaussianBlur() metoduyla yumuşatıyoruz. Bu sayede görüntülerdeki renk dağılımları çok keskin hatlar oluşturmuyor. Aslında bizim örneğimizde bu metodu kullanmasak da olur.
46. satırda center değişkenini tanımlıyoruz. Bu değişken her görüntü karesinde yakalanan en büyük çemberin merkez noktasını tutacak.
49. satırdaki cmax değişeni en büyük alana sahip kontur değerlerini tutuyor.
51. satırda cmax’ı içine alan en küçük çembere ait merkez ve yarıçap bilgilerini buluyoruz.
52 ve 53. satırlarda şeklimizin ağırlık merkezini hesaplatıyoruz. Aslında bunun yerine center = (int(x),int(y)) kullansak da pek bir şey değişmeyecektir. Deneyebilirsiniz.
57-63 arası satırlarda yeni merkez noktamızı pts’ye ilk eleman olarak ekliyoruz. Böylece tüm elemanlar birer sıra sağ kayıyor ve en sondaki eleman siliniyor.
62. satırdaki thickness hesabı, çizgi kalınlığının, konumuna bağlı olarak değişmesini sağlıyor. Olayı basitleştirmek istersek onun yerine thickness=3 gibi bir satır kullanabiliriz. Elbette bu durumda çizgilerimizin kalınlığı sabit olur.
Son değişikliğimiz, 67.satırı devre dışı bırakmak. Böylece mask çerçevesini görünmez yapıyoruz.
Videoda kodların çalışır halini görebilirsiniz.
Bu yazıyı daha fazla uzatmayacağım. Çünkü ana fikirde bir önceki örneğimize göre önemli bir değişiklik yok. Ama istersek eğlenmek için bazı değişklikler yapabiliriz.
Örneğin ben cizgi kalınlıklarını biraz abartıp, rengini de kırmızı yaptım. Aşağıdaki videoda bu değişikliği görebilirsiniz. Siz de pts (deque) eleman sayısını azaltabilir veya çoğaltabilir, çizgi renkleriyle oynayabilirsiniz. Ya da renk aralıklarını değiştirerek farklı nesneleri izleyebilir veya web kamera yerine bir video dosyası kullanabilirsiniz (elinizde uygun bir video varsa).
Bir sonraki yazımda yüz tanıma konusunu yeniden ele alacağım.
Beni izlemeye devam edin.
Ahmet Aksoy