Geçmişten Bugüne Object Detection (Part 1)
--
Bu sene pandeminin de getirisiyle kendimi birçok proje ve çalışmanın içinde buldum. Birkaç projenin birden object detection (namıdiğer nesne tanıma) üzerine olması bu konu üzerinde ister istemez teorik araştırmalar yapmamı gerektirdi ve ben de biraz geriden başlayarak geçmişten bugüne nesne tanımaya kadar nasıl bir yol izlendiğini anlatmak istedim. Bu blog yazıları boyunca Gradient Vectors, HOG (Histogram of Oriented Gradients), CNN (Convolutional Neural Network), DPM (Deformable Parts Model), Overfeat, YOLO (You Only Look Once) ve R-CNN (Regional CNN) gibi bazı yöntemlerden bahsetmeye çalışacağım.
Bu yazıda Gradient Vector’leri tanıtıp sonra da onların kullanıldığı Histogram of Oriented Gradients’tan bahsedeceğim. Öncelikle Gradient Vector’lardan başlamak istiyorum.
Gradient Vectors
Gradient Vector dediğimiz kavram aslında görüntü işlemenin en temel yapıtaşı ve amacı ise bir görüntünün gradient’ını göstermek. Yani aslında bir görüntünün içerisindeki değişimlerin yönünü, büyüklüğünü ve eğilimini incelemek için kullanılıyor. Formülü ise şöyle :
Bu formülü biraz incelersek aslında her bir pixel için kendisi hariç, bir yanındaki pixellerin arasındaki farkı hesaplayarak ortalama değişimin ne kadar olduğuna dair bir çıkarımda bulunuyoruz. Bu formülün sonucunda bulduğumuz vektörden de iki yönde yararlanıyoruz : magnitude (büyüklük) ve direction (yön).
Magnitude ve direction için ise matematikten aşina olduğumuz formülleri kullanıyoruz :
Aslında burada kullandığımız x-gradient ve y-gradient bizim computer vision alanında kullandığımız filtrelere denk geliyor ki bu filtreler de günümüzde benim ilk CNN öğrenirken rastladığım ve herkesin öyle ya da böyle aşina olduğu horizontal/vertical filter’lar. Bu filtrelerin kullanımı da aslında convolution operasyonunun gelişmesini ve computer vision alanında ağırlıklı olarak kullanılmasını sağlıyor. [-1, 0, 1] ile x-gradient hesaplarken yaparken aslında ortadaki pixel’i es geçerek x eksenindeki değişimi görüyoruz; [-1, 0, 1] transpozla ise y-gradient hesaplayarak her bir değeri ilgili pixel’le çarpıp y eksenindeki değişimi görüyoruz.
Burada iki yeni kavramdan bahsettik : filtre ve convolution. Görüntü işleme kapsamında incelersek aslında filtre belirli bir özelliği tespit etmek için kullanılan matristir diyebiliriz, konvolüsyon ise bu filtre fotoğrafın üzerinde kaydırıldığında her bir pixelin filtredeki denk gelen değerle çarpılıp toplanmasıdır.
Başlangıçta [−1,0,1] ve [−1,0,1]’un tranzpozu kullanılarak sırasıyla x eksenindeki ve y eksenindeki değişimler incelenmiştir. Zaman içerisinde de Prewitt ve Sobel operatörleri kullanılarak daha kapsamlı (4 yerine 8 çevre pixel’in incelenmesi) ve verimli filtreler kullanılmıştır:
Anlattığım şeyleri özetlemek için bir örnek üzerinden gitmek istiyorum. Siyah arkaplanın ortasında beyaz bir dairenin yatay ve dikey filtrelerle gradient’ının nasıl bir görüntü oluşturduğunu ve bunu nasıl yorumlamamız gerektiğini inceleyeceğiz.
Bu görüntüde sadece iki renk var ve herhangi bir filtreyle bu görüntüyü işlediğimiz zaman bu resimdeki şekli ve renk geçişlerini gözlemleyebilmeliyiz. Bu görüntüyü yatay bir filtreyle işlediğimiz zaman ise şöyle bir görüntü elde ediyoruz :
Bu görüntüde daire şeklini rahatça gözlemleyebiliriz, dairenin sol kenarının beyaz tonlarında sağ tarafının ise siyah tonlarında olmasından ise şöyle bir çıkarım yapmalıyız : renk geçişi beyaz tonunu gözlemlediğimiz noktada beyaza doğru geçiyor siyahı gözlemlediğimiz noktadan sonra ise siyah. Yani aslında yatay olarak iki farklı renk geçişi var ve bunlar x ekseniyle aynı yönde. Aynı işlemi dikey bir filtreyle gerçeklersek :
Bu sefer de yine aynı şekilde renk geçişlerini ve doğrultularını gözlemleyebiliriz. Eğer iki resmi birleştirirsek, image gradient’a ve dolayısıyla magnitude’una ulaşıyoruz :
Siyah-beyaz fotoğraflarda, pixeller 0–255 değerleri arasında değer alabilir; 0 siyah renk, 255 ise beyaz renktir. Bu fotoğrafta magnitude’a bakarak aslında beyaz olan noktalarda en büyük değişimin olduğu, siyah olan noktaların ise durağan olduğu sonucuna ulaşmalıyız. Filtreyi uyguladığımız fotoğraflarda ise fotoğrafın normal hali gri olarak kodlandığı için gri harici renkleri değişim olarak yorumlamalıyız.
Histogram of Oriented Gradients
Bu yöntem görüntü işlemede object detection için kullanılan en eski yöntem olarak geçiyor. Aslında yukarıda bahsettiğimiz image gradient vektörlerini kullanarak görüntünün daha genelleştirilmiş bir versiyonda eğilimlerine ulaşıyoruz.
Bunu yapmak için adımlarımız şunlar :
- Görüntünün boyutlarını 8x8lik karelere ayırabileceğimiz hale getirmek
- Her bir karedeki her bir piksel için image gradient hesaplamak
- Gradient direction’a bakarak 8x8lik kareler için bir histogram grafiği hazırlamak
- (Opsiyonel) İşleri kolaylaştırmak için normalizasyon yapmak
- Her bir kare için bu histogram grafiğini görselleştirmek
Örnek fotoğraf olarak learnopencv.com’un sitesindeki örnek fotoğrafı kullanacağım :
Bu fotoğrafı 8x8lik karelere ayırabileceğimiz bir resize işlemine soktuktan sonra karelere ayırıldıktan sonraki halini gözlemleyelim:
Her bir kare için ilgili gradient vektörleri hesaplayalım. Kullanacağımız matris, büyüklüklerini içeren olacak ama hepsini görselleştirmek adına:
Daha sonra ise 0, 20, 40, …, 180 olacak şekilde bir histogram oluşturuyoruz. Ara değerleri de yakın olan değere ekliyoruz.
Bu tabloda 0 derece 0 değeriyle, 20 derece 1 değeriyle vs. şekilde temsil ediliyor. Bundan sonraki adımımız bu tablodaki değerleri büyük bir çok boyutlu vektöre çevirmek ve fotoğraf üzerinde görselleştirmek:
Bu fotoğrafta da gözlemleyebileceğimiz üzere benzer alanlarda benzer motifleri görebiliriz, fotoğrafın ortasında daha çok yukarı aşağı eğilimler varken arkaplanda daha yatay bir eğilim var. Buradan hareketle aslında fotoğrafın ortasında bir objeyi hiçbir şekilde derin öğrenme vb kompleks metotlar olmadan klasik görüntü işleme yöntemleriyle bulmuş olduk.
Son olarak, bu elde edilen çok boyutlu matrisler bir Support Vector Machine modeline verilerek yüksek doğruluk oranına sahip sonuçlar elde edilebilir.
Kaynaklar ve resimler :
https://learnopencv.com/histogram-of-oriented-gradients/
https://lilianweng.github.io/lil-log/2017/10/29/object-recognition-for-dummies-part-1.html