Merhaba, geliştirdiğim bir projeden bahsetmek istiyorum.
Proje alanı: Computer Vision - Deep Learning
Kullanılan programlama dili: Python
Kullanılan araçlar: PyTorch, ONNX, OpenCV4, PIL, standart veri işleme ve görselleştirme kütüphaneleri (numpy, matplotlib ve seaborn)
Görüntü işleme ile geliştirilen uygulamaların neredeyse hepsi artık bir derin öğrenme modeli vs. kullanıyor bir şekilde. Yani eğer çok basit şeyler yapmaya çalışmıyorsanız (pasaport okuyucu vb.) gelişmiş bir derin öğrenme modeliyle birlikte modern görüntü işleme tekniklerini kullanmak zorunda kalıyorsunuz. Bu projemde modern bir görüntü işleme modeli kullanarak fotoğraftaki insanları belirlemeye çalıştım. Halihazırda model elimde bulunduğu için ekstra bir veri toplayıp model eğitmeme gerek kalmadı, tek gereken şey problemi çözmek için düzgün bir görüntü işleme algoritması oluşturmak oldu. Görüntü işleme modellerini ürün haline getirirken tabii ki performans inanılmaz önemli oluyor, bundan dolayı model ONNX formatına çevirip uygulamaya böyle dahil etmeyi tercih ediyorum ben genellikle. Böylelikle işleme performansı genellikle 5-6 kat artmış oluyor. Modelleme kısmında kullandığım derin öğrenme modelini biraz açıkladım, isterseniz direkt
Bitiş kısmına geçebilir ve sonuca bakabilirsiniz
Geliştirme sebebim
Object detection sistemleri günümüzde çok iyi işlere imza atabiliyor; çalışan güvenliği, robotik, otonom araçlar, güvenlik sistemleri vb. Sürücülerin araç başındaki davranışlarını analiz etmek gibi güvenlik önlemleri almada, otonom araçlar için yol/araç vb. tanımlamarda inanılmaz önem taşıyor. Otonom araçlar ve robotik dışında oldukça insan gücü gerektiren işlemleri bu sayede görüntü işleme sistemlerine yaptırabiliyorsunuz. Çoğunlukla uzun vadede çok daha kârlı ve performansı da insanları geçmiş oluyor. Ayrıca belirli aralıklarla veri toplayıp modeli fine-tune ederek geliştirmeye devam edebilir ve ürününüzü sürekli güncelleyebilirsiniz. Çeşitli ileri analiz yöntemleri ile verinin nasıl eğilim gösterdiğini anlayabiliyorsunuz, bu tabii probleminiz için daha iyi çözümler üretmenize de olanak sağlıyor.
Modelleme
Elimde zaten model olduğu için ekstra veri toplamaya ihtiyaç duymadığımı söylemiştim, modelleme aşamasında düzenlediğim ekstra bir şey olmadı açıkçası. Günümüzde YOLO dışında en popüler obje tanımlama yaklaşımı RCNN (Region Based Convolutional Neural Network) kullanmak. RCNN yapısı da zamanla RCNN, Fast RCNN ve Faster RCNN olarak geliştirildi.
Bu makalede bahsedilen Faster RCNN yapısını ResNet50 backbone u kullanarak eğitmiştim daha önce.
Klasik CNNlerin aksine RCNNlerde işlenen görseli alıp içerisinden belirli algoritmalar yardımıyla bir sürü bölge çıkarıyorsunuz. İlk makalelerde 2000'e yakın bölge ayıklanıyordu. Bu ayıklama işlemi segmentasyon + selective search kullanılarak yapılıyor, elinizdeki her bir görselden 2000 kadar bölge ayıklayıp ayrıca CNN'e gönderip işliyorsunuz. Bu yaklaşımın en büyük dezavantajı her bir fotoğraf için 2000 civarında bölge ayıklayıp işlemenin gerekmesiydi, 1000 tane fotoğrafla eğitmeye kalksanız her eğitim adımında 2 milyon bölge işlemeniz gerekiyor. 60 FPS bir videoda kullanacaksanız saniyede 120000 bölge işlemesi gerekiyor sistemin. Hal böyle olunca da gerçek dünya uygulamalarında performansı oldukça düşük oluyor, 40-50 saniyede bir belirleme yapabiliyor. Aşağıda RCNN yapısını özetleyen bir görsel görebilirsiniz, çıkartılan her bölgede modeli çalıştırmak çok işlem yükü istiyor.

Bu problemi aşmak için RCNNi geliştiren araştırmacı Fast RCNNi sunmuştu. Fotoğraftan 2000 bölge ayıklamak yerine fotoğrafı CNN'e gönderip bölgeleri ona belirletmeyi düşündü, bu şekilde elde ettiğiniz bölgelere ROI (Region of Interest) deniyor. Normalde bir sürü bölge elde edildiği için bunları filtrelemek adına selective search algoritması kullanılıyor. Tabii selective search sistemi yine yavaşlatıyor, ancak genel olarak daha az işlem yaptığımız için performans klasik RCNNinkinden daha yüksek. Ortalamada 2 saniyede bir yeni belirleme yapabiliyor. RCNNden 25 kat daha hızlı performans gösteriyor

Yine aşağıda Fast RCNN yapısını özetleyen bir görsel görüyorsunuz. Artık başlangıçta bir CNN kullanarak görseli işleyip, sonrasında bölgeleri ayıklayıp belirleme yapıyor, dolayısıyla performansı da artmış oluyor.
Selective searchten kurtulmak çok önemliydi, çünkü greedy bir algoritma olduğu için performansı çok etkiliyor ve yavaş çalışabiliyordu. Bu yüzden Faster RCNN geliştirilirken onu elemeye çalıştılar. Faster RCNN bölgeleri seçmek için direkt derin öğrenme kullanıyor, yani sisteme RPN (Region Proposal Network) denilen bir model daha ekleniyor. RPNlerin çalışma mekaniği biraz farklı, o yüzden onu anlatmayacağım. Kabaca açıklamak gerekirse; RPN, CNN ile işlenen veriyi alıp bir sliding window kullanarak k adet anchor box denilen kutuları oluşturuyor, bu sayıyı biz belirleyebiliyoruz. Anchor box dediğimiz şey ise sabit boyutlu bir kutu. RPN bunları oluşturduktan sonra her bir kutu için 2 tahmin yapıyor:
- Kutunun bir obje olup olmadığı
- Kutunun içinde obje varsa objeyi içeren kutunun koordinatları
Bu tahminlere göre filtrelenen bölgeler başlangıçta işlenen veriyle birlikte ana sınıflandırıcıya gönderiliyor. Sonrasında da tahminler elde ediliyor. Böylelikle RCNNdeki bölgeleri tamamen RPN ile çözmüş ve belirlemiş oluyoruz. Genel olarak tahmin süresi görsel başına ortalama 0.2 saniye olarak gözüküyor. Tabii başlangıçta veri işlerken kullanılan CNN yapısı, RPN özellikleri ve final sınıflandırıcının yapısı performansı inanılmaz etkileyebiliyor. Benim kullandığım model de Faster RCNN oldu, fotoğraftan başlagıçta işleyebilmek için ResNet50 adında kompleks ve karmaşık bir model kullanıyorum, bu hızı biraz düşürse de modeli ONNX formatına çevirdiğimde toparlayacağını düşündüm açıkçası. Az çok işe yaradı gibi

Aşağıda Faster RCNN yapısını açıklayan bir görsel var, işlemleri derin öğrenme modelleri ile yaptığımızda aslında basit tensor çarpımları vs. yaptığımız için sistem kısmen daha hızlı hale geliyor.
Bitiş
Ben yukarıda bahsettiğim modeli kullanarak insanları içeren kutuları belirledikten sonra kutular üzerinde IoU metriği kullanarak kişileri tespit etmeye çalıştım. Her bir kutuyu tanımlanan bir obje olarak ele alıp, video ilerledikçe bu objelerin kutularını güncellemeye çalıştım, ayrıca insanların hareketlerini takip edebilmek adına kutuların hareketini belirten çizgiler çizdim. Karşılaştığım yegane problem kutuları takip etmek oldu, başlangıçta çözmek için kutu içindeki insanları karşılaştırmayı düşündüm fakat performansı çok düşürüceğini fark edine IoU kullanmaya karar verdim. Şu anki halinde tanımlanan obje ekrandan çıktığında çizilen çizgi de kayboluyor. Ancak tabii bunu engellemek mümkün. Şimdi de sonuçları görelim, aşağıda projenin çıktısını görebilirsiniz:
project video