12 Ağustos 2021 Perşembe

OpenCV: SVM ve HOG ile nesne tespiti

Bu yazı kapsamında Python ile OPENCV kütüphanesini kullanarak basit bir nesne tespiti/sınıflama uygulamasını nasıl gerçekleştirebileceğinizi anlatacağım. Örneğimizde OpenCV ML (machine learning) modülü içerisindeki SVM(Support Vector Machine) ve Object Detection modülü içerisindeki HOG yöntemlerini kullanacağız.


SVM etiketlenmiş bir veri kümesindeki farklı sınıfları birbirinden ayıracak hyperplane(düzlemleri) çıkararak sınıflama işlemi gerçekleştirir. OpenCV dökümantasyonundan detaylı bilgilere erişebilirsiniz. HOG(Histogram of Gradient) yöntemi ise görüntü üzerinden özellik çıkarımı yapan bir yöntemdir. Alternatif olarak SURF ve ORB metotları da bir başka özellik çıkarımı yöntemleri olarak sıralanabilir. Özellik çıkarımından kastedilen şey, örneğin 224x224 boyutlarındaki bir görüntüyü işleyip, bu görüntüyü ifade eden 255 elemandan oluşan bir vektörün çıkarılması olarak düşünülebilir. Elde edilen bu daha düşük boyutlu vektörde önemli bilgilerin(özelliklerin) tutulması, gereksiz bilgilerin ise atılması hedeflenmektedir.

HOG metotunda, yatay ve dikey gradyanlar alındıktan sonra bu gradyanların histogramı hesaplanır. x ve y ekseninde hesaplanmış gradyan örneğini aşağıdaki resimde görebilirsiniz. Bu ve bunun gibi görüntü işlemede temel teşkil eden konuları öğrenmek ve uygulamalı örneklerle bunları pekiştirmek için udemy'deki kursuma göz atabilirsiniz. :) (İletişim sayfasından ulaşırsanız sizlere kupon kodu tanımlayabilirim) 



HOG metotunda görüntü ızgaralara bölünerek her bir ızgara içerisindeki gradyanların histogramları hesaplanır. Algoritmaya girdi olarak verilen bu ızgara boyutları elde edilecek özellik vektörünün boyutunu doğrudan etkilemektedir. HOG metodu hakkında daha detaylı bilgiler için learnopencv sayfasına göz atabilirsiniz.


Kullanacağımız yöntemlerle ilgili bu çok temel bilgilerden sonra kodları yazmaya başlayabiliriz. İlk yapacağımız bir çeşit makine öğrenmesi yöntemi olan SVM'i eğitmek amaçlı kullanacağımız bir örnek veri seti hazırlamak. Ben örnek olarak kolonya tespit uygulaması yapmaya karra verdim, bu sebeple kolonya içeren ve içermeyen bir dizi görüntü içeren iki farklı klasör oluşturdum. Siz görüntü sayısını arttırarak yöntemin performansını daha iyi test edebilirsiniz. Hazırladığım örnek veri setine ait görüntüleri aşağıda görebilirsiniz.



Şimdi bu kadar girizgahtan sonra bu 2 klasördeki görüntüleri alıp, HOG ile özellik çıkarımını yapıp, SVM ile modeli eğitip sonucunu bir dosyaya kaydeden örnek python kodunu paylaşıyorum.




import cv2
import os
import numpy as np


def loadImages(hog, path):
    file_list = os.listdir(path)
    x = []
    for filename in file_list:
        img = cv2.imread(path + filename)
        hist = hog.compute(img)
        x.append(hist)
    return x


winSize = (128, 128)
blockSize = (64, 64) 
blockStride = (64, 64)
cellSize = (32, 32)
nBin = 9 

hog = cv2.HOGDescriptor(winSize, blockSize, blockStride, cellSize, nBin)



featuresCologne = np.array(loadImages(hog, "dataset/1/"))
featuresOther = np.array(loadImages(hog, "dataset/0/"))

labelsCologne = np.ones(((len(featuresCologne),1)), np.int32)
labelsOther = np.zeros(((len(featuresOther),1)), np.int32)

features = np.float32(np.concatenate((featuresCologne, featuresOther), axis=0))
labels = np.concatenate((labelsCologne, labelsOther), axis=0)

svm = cv2.ml.SVM_create()
svm.setType(cv2.ml.SVM_C_SVC)
svm.setKernel(cv2.ml.SVM_LINEAR)
svm.setTermCriteria((cv2.TERM_CRITERIA_MAX_ITER, int(1e7), 1e-6))

print("training....")
ret = svm.train(features, cv2.ml.ROW_SAMPLE, labels)
svm.save('svm_data_hog.xml')



Eğitilmiş modeli kullanarak bir video üzerindeki belirli bir bölgedeyi (ROI) tarayan ve buraya göstermiş olduğum kolonyayı tanımaya yarayan kod parçacığını ise aşağıya bırakıyorum.


import cv2
import numpy as np

winSize = (128, 128)
blockSize = (64, 64) 
blockStride = (64, 64)
cellSize = (32, 32)
nBin = 9 

hog = cv2.HOGDescriptor(winSize, blockSize, blockStride, cellSize, nBin)

svm = cv2.ml.SVM_create()
svm = cv2.ml.SVM_load("svm_data_hog.xml")

cap = cv2.VideoCapture(0)
if not cap.isOpened():
    print("Cannot open camera")
    exit()

x,y,w,h = 20, 50, 243, 348

while True:
    ret, frame = cap.read()
    if not ret:
        print("Can't receive frame. Byess")
        break

    cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255),1)

    patch = frame[y:y+h, x:x+w, :]
    hist = hog.compute(patch)
    inputX = np.float32(np.expand_dims(hist, axis=0))
    
    res = svm.predict(inputX)[1]
    print(res)

    ch = cv2.waitKey(1)
    if  ch == ord('q'):
        break

    if res[0] == 1:
        cv2.putText(frame, "It is a Cologne", (x,y), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255),1)

    cv2.imshow("frames", frame)

cap.release()
cv2.destroyAllWindows()


Ve son olarak uygulamanın örnek bir çıktısı





Her türlü görüş, öneri ve sorularınızı iletebilirsiniz...

Hiç yorum yok:

Yorum Gönder