YOLOv8 ile Nesne Sayımı | Object Counting

Nesne Sayımı veya Object Counting işlemi basitçe, videodaki nesnelerin sayısının tespit edilmesi anlamına gelir. Öncelikle sayısı tespit edilecek sınıflar karar verilir ve sonrasında Object Tracking algoritmalarınında yardımıyla bu nesneler sayılır. Dolayısıyla bu yazıyı okumaya başlamadan önce nesne takibi yazıma göz atmanızı tavsiye ederim.

Biz bu çalışmada, havalimanında yolcuların bavullarının aktığı bant üzerinden kaç adet bavul geçtiğini sayacağız. Bu yazıda öğreneceğiniz temellerle, kendi nesne sayım uygulamalarınızı gerçekleştirebileceksiniz. Aslında gerçek hayatta da bu konuyla ilgili pek çok örnek vardır:

  • Kavşaktan geçen araç sayısı
  • Konveyorden akan ürün sayısı
  • Metro istasyonuna giren çıkan insan sayısı

gibi uygulamalar nesne sayımı uygulamasına dair güzel örnekledir.

1. Kurulumlar

Nesne sayımı işlemine başlamadan önce ilk olarak Ultralytics ve OpenCV kütüphanesini aşağıdaki komutlarla indirmelisiniz:

pip install ultralytics
pip install opencv-python

Çalışma boyunca kullanacağımız dosyaları blog yazımın başındaki bağlantıdan bilgisayarınıza indirebilirsiniz.

Şimdi dosya düzenini ayarlayalım. Boş bir klasör içerisinde object_counting.py adında bir dosya oluşturalım. Ardından test videomuzu da, yine kendi oluşturduğumuz video adındaki dizine koyalım. Çalışmada kullanacağımız model best.pt olacak. Bunu da, kendi oluşturduğumuz models isimli dizine yüklemeliyiz. burada kullandığımız best.pt modelini daha öncesinde bu çalışma için eğitildi ve sizlerle hazır olarak paylaşılıyor.

Tüm bu işlemler size karmaşık gelmeye başladıysa yukarıdaki videoyu da takip ederek yapabilirsiniz.

2. Nesne Sayımı

Kodlarımızı yazmaya başlamak için object_counting.py dosyamızı açıp kütüphaneleri ekleyelim:

import os
os.environ ["KMP_DUPLICATE_LIB_OK"] = "TRUE" 

import cv2
import numpy as np

from ultralytics import YOLO
from collections import defaultdict

Kütüphaneleri ekledikten sonra, metin ve renklendirme için kullanacağımız bazı parametreleri tanımlayalım:

# Text & Color Params 
thickness = 2

color_black = (0,0,0)
color_red = (0,0,255)
color_green = (0,255,0)
color_white = (255,255,255)

font_scale = 0.7
font = cv2.FONT_HERSHEY_SIMPLEX

Şimdi videomuzu okuyup buna dair parametreleri tanımlayalım:

# Video Params
video_path = "video/luggage.mp4"
cap = cv2.VideoCapture(video_path)

height, width = 720, 1280
print("[INFO].. Width:", width)
print("[INFO].. Height:", height)

Yukarıdaki kod bloğunda önce videomuzu okuduk ardından videomuzun en/boy değerlerini ve toplam kare sayısını bir değişken içerisinde depoladık. Bu bize videomuzun toplam kaç kareden oluştuğunu gösterecek. Ardından modelimizi ve buna dair parametreleri tanımlayalım:

# Model Params
model_name = "models/best.pt"
model = YOLO(model_name)

counter = {}
track_history = defaultdict(lambda: [])

Artık videomuzu işlemeye hazırız. Bir while döngüsü kurarak her bir kareyi tek tek işlemeye başlayabiliriz. Aşağıdaki kod bloğu kareleri tek tek okuyup, bant üzerinde akan bavulları saymaktadır. Bu kop bloğunu parçalar halinde düşünerek anlamaya çalışalım. Daha önce yaptığımız Object Tracking çalışmasında da benzer kodlar geliştirmiştik.

while True:
    ret, frame = cap.read()
    if ret == False:
        break

    frame = cv2.resize(frame, (width, height))
    results = model.track(frame, persist=True, verbose=False)[0]
    bboxes = np.array(results.boxes.data.tolist(), dtype="int") # 2.0 -> 2

    cv2.line(frame, (int(width/2), 0), (int(width/2), height), color_red, thickness)
    cv2.rectangle(frame, (int(width/2)+7, int(height/2)+5), (int(width/2)+175, int(height/2)-25), color_white, -1)
    cv2.putText(frame, "Reference Line", (int(width/2)+10, int(height/2)), font, font_scale, color_red, thickness)

    # Bagajların ortasına nokta atılacak     
    for box in bboxes:
        x1, y1, x2, y2, track_id, score, class_id = box
        text = "ID:{} LUGGAGE".format(track_id)
        
        cx = int((x1+x2)/2)
        cy = int((y1+y2)/2)
        center_coordinates = (cx, cy)

        if cx > int(width/2) :
            cv2.circle(frame, center_coordinates, 3, color_red, -1)
            cv2.rectangle(frame, (x1,y1), (x2,y2), color_red, 2)
            cv2.rectangle(frame, (x1,y1), (x1+175,y1-25), color_red, -1)
            cv2.putText(frame, text, (x1, y1-5), cv2.FONT_HERSHEY_SIMPLEX, 0.7, color_white, 2)
            
        else: 
            cv2.circle(frame, center_coordinates, 3, color_green, -1)
            cv2.rectangle(frame, (x1,y1), (x2,y2), color_green, 2)
            cv2.rectangle(frame, (x1,y1), (x1+175,y1-25), color_green, -1)
            cv2.putText(frame, text, (x1, y1-5), cv2.FONT_HERSHEY_SIMPLEX, 0.7, color_white, 2)
            counter[track_id] = x1, y1, x2, y2

        number_of_luggage = len(list(counter.keys()))  

        info = f"Counter: {number_of_luggage}"
        cv2.rectangle(frame, (5,5), (150,40), color_white, -1)
        cv2.putText(frame, info, (15,30), font, font_scale, color_red, thickness)  

    cv2.imshow("Object Counting", frame)
    if cv2.waitKey(10) & 0xFF == ord("q"):
        break

cap.release()
cv2.destroyAllWindows()

Daha önceki object tracking blog yazımda kullandığım kodlardan farklı olarak burada bazı eklemeler olduğunu farketmişsinizdir. Şimdi farklı olan kısmı birlikte inceleyelim:

    # find the center point of the objects
    for box in bboxes:
        x1, y1, x2, y2, track_id, score, class_id = box

        text = "ID:{} LUGGAGE".format(track_id)
        
        cx = int((x1+x2)/2)
        cy = int((y1+y2)/2)
        center_coordinates = (cx, cy)

        if cx > int(width/2) :
            cv2.circle(frame, center_coordinates, 3, color_red, -1)
            cv2.rectangle(frame, (x1,y1), (x2,y2), color_red, 2)
            cv2.rectangle(frame, (x1,y1), (x1+175,y1-25), color_red, -1)
            cv2.putText(frame, text, (x1, y1-5), cv2.FONT_HERSHEY_SIMPLEX, 0.7, color_white, 2)
            
        else: 
            cv2.circle(frame, center_coordinates, 3, color_green, -1)
            cv2.rectangle(frame, (x1,y1), (x2,y2), color_green, 2)
            cv2.rectangle(frame, (x1,y1), (x1+175,y1-25), color_green, -1)
            cv2.putText(frame, text, (x1, y1-5), cv2.FONT_HERSHEY_SIMPLEX, 0.7, color_white, 2)
            counter[track_id] = x1, y1, x2, y2
        
        number_of_luggage = len(list(counter.keys()))  

        info = f"Counter: {number_of_luggage}"
        cv2.rectangle(frame, (5,5), (150,40), color_white, -1)
        cv2.putText(frame, info, (15,30), font, font_scale, color_red, thickness)  

Burada tespit ve takip edilen nesnelerin orta noktasına for döngüsü ile birer daire çiziliyor. Ardından gelen if-else bloğu ise nesnenin referans çizginin sol tarafına geçip geçmediğini kontrol ediyor. Eğer nesne sol tarafa geçtiyse nesnenin rengi yeşil oluyor. Çizginin sol tarafına geçen her bir nesnenin ID‘sini bir sözlük içerisinde depolayarak daha sonra bu nesnelerin kaç tane olduğunu hesaplatıp ekrana yazıyoruz.

3. Endüstriyel Uygulamalar

Bu blog yazısı, nesne sayımı işleminin YOLOv8 ile nasıl yapıldığını sizlere anlatmak amacıyla oluşturulmuştur. Buna benzer çalışmaları geliştirmenizi ve benimle paylaşmanızı dört gözle bekliyorum. 🚀

Son olarak, burada paylaşılan kodlar temel seviyede çalışmaları ifade etmektedir. Endüstriyel çalışmalara uygun algoritmalar geliştirmek ve sorunlarınıza hızlı bir şekilde çözüm üretmek için iletişim formu üzerinden benimle iletişime geçebilirsiniz.

Oğuzhan Gürbüz

Oğuzhan Gürbüz

Merhabalar,
Görsel Analiz'in kurucusuyum.
İnsansız kara araçları üzerine çalışıyorum. Görüntü işleme, derin öğrenme ve ROS gibi alanlarda danışmanlıklar ve eğitimler veriyorum. Şirketlere ve araştırmacılara bu tip sistemleri geliştirmelerinde yardımcı oluyorum.

2 Comments

Leave a Reply

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Ücretsiz Bilgisayarlı Görü eğitimlerini kaçırmamak için hemen abone ol !