OpenCV ile Çember-Elips Tespiti Simülasyonu

Ziyaret Sayisi 625

Bu yazımın amacı OpenCV kütüphanesini kullanarak Python ile çember ve elips tespitinin nasıl yapılacağını öğrenmek. Tabii ki çember tespiti yapmanın tek yolu OpenCV kütüphanesini kullanmak ya da Python dilini kullanmak değil. Örneğin aynı işi yapabileceğiniz bir diğer kütüphane olan scikit-image de kullanılabilirdi. Ya da bu kütüphaneleri kullanmaya izin veren diğer dilleri de kullanabilirdik. Amacımız baştan sona OpenCV öğrenmek değil, işimize yarayacak olan kısmı öğrenmek.

Kodların tamamını buraya tıklayarak Github hesabım üzerinden indirebilirsiniz.

Bildiğiniz gibi 3 boyutlu bir dünyada yaşıyoruz ve çembersel yapıdaki bir objeye farklı açılardan baktığımızda onu çember değil, elips olarak görürüz. Benim bu kodu yazmaktaki amacım da kameradan gelen veriyi işleyip, objeye hangi açıdan bakarsam bakayım bir çember tespiti yapmaktı. Bunun içinde kendime bir simülasyon ortamı hazırladım.

İlk Bakış:

Şimdi adım adım nasıl yapacağımızı öğrenmeden önce, programı yazmayı bitirdiğimizde nasıl bir görüntü elde edeceğimizi aşağıdaki görselle inceleyelim.

Pencerenin ortasına siyah renkte bir çember-elips çizip, çizdiğimiz bu şekilde bilgisayarın çember bulmasını sağlayacağız. Gerekli parametreleri kod üzerinden elle değiştirip her değişiklik yaptığımızda programı kapatıp açmak yerine, canlı olarak program çalışırken değiştirebilmek için görselin alt tarafına slider (OpenCV içerisinde trackbar diyeceğiz) ekleyeceğiz.

Görselin sol üstüne bulunan çember sayısını, sağ üst tarafına ise objeye olan bakış açımızı yazacağız. Sol alta ise kullandığımız renklerin anlamlarını yazabiliriz.

Pencere yapısı ve slider şekilleri kullandığınız işletim sistemine göre değişkenlik gösterebilir. Ben Linux’un Ubuntu dağıtımını kullanıyorum. Eğer Windows kullanıyorsanız slider’lar üstte görsel altta gelecektir. Bu durum görüntüyü ciddi oranda bozuyor. Çözümü ise arayüz tasarımı yapmak için kullanılan Qt kütüphanesi ile ara yüzü tekrar tasarlamak. Çünkü OpenCV’de slider’ların yerleri değiştirilemiyor. Bu yazıda Qt kütüphanesini kullanmayacağım fakat yakın zamanda Github üzerindeki kodumu güncelleyip her işletim sisteminin aynı ve düzgün bir arayüz oluşmasını sağlayacağım.

 

Adım 1: Kütüphanelerimizi ekleyelim

Görüntü işlemeyi yapacağımız OpenCV için  cv2 kütüphanesini ve matris işlemleri için kullanacağımız Numpy kütüphanesini ekliyoruz. Üçüncü sıradaki remove fonksiyonu isteğe bağlı. Eğer elde ettiğiniz görselin saklanmasını istiyorsanız kullanmayabilirsiniz.

Adım 2: Trackbar’lar ve Programın Global Değişkenleri

Font ve pencere başlığı değişkenlerimizi globalde tanımlayarak, birazdan yazacağımız fonksiyon içerisinde kolay bir şekilde kullanmayı amaçlıyoruz. Ardından namedWindow fonksiyonu ile bir pencere yaratıyoruz ve bir satır önce hazırladığımız ismi parametre olarak veriyoruz.

Şimdi gelelim trackbar’larımızı oluşturmaya. Gerekli parametreler sırasıyla: trackbar’ın adı, içinde gösterileceği pencerenin adı, varsayılan pozisyonu, alabileceği maksimum değer, bir değer değiştirildiğinde kullanılacak fonksiyon. Son parametrede verdiğimiz fonksiyonu 3. adımda yazmaya başlayacağız.

İlk Trackbar’larımız çizeceğimiz elipsin major ve minor uzunlukları için. Sonrasında ise çizeceğimiz elipsin kalınlığını ve kaç derecelik kısmını çizeceğimizi belirlemek için iki tane daha trackbar açıyoruz. Ardından gerekli parametre değişiklikleri için p1, p2 isimli trackbar’ları açıyoruz. Bunları değiştirdiğimizde görselde tespit edilen çember sayısı da değişecek. Ve son olarak da görsel olarak bize yardımcı olması adına showAll ve showEstimated isimli trackbar’ları açıyoruz. Yazının devamında bu ikisinin amacını göreceksiniz.

Programın düzgün bir başlangıç yapabilmesi için rastgele bir trackbar’ın değerini manuel olarak veriyoruz. Ardından programın otomatik kapanmaması için bir kapatma tuşu ataması yapıyoruz. Bu tuşumuz ‘Q’. Q’ harfine basıldığında bütün pencereler kapatılacak.

Adım 3: circleDetector Fonksiyonunun Başlangıcı ve Girdilerin İşlenmesi

Öncelikle Numpy kütüphanesini kullanarak beyaz arka plana sahip 500×500 piksel ölçülerinde bir arka plan oluşturalım. Sonra, ikinci adımda oluşturduğumuz trackbar’lardan gelen inputları değişkenlere atayalım. Burada parametre olarak trackbar’ın adını ve pecerenin adını veriyoruz.

Sırada bu inputların bazılarının işlenmesi var. Bakış açımızı hesaplamak için angle isimli değişkene major ve minor inputları ile arccos hesabı yapıyoruz ve elde ettiğimiz radyan cinsinden değeri dereceye dönüştürüyoruz. Tahmin edersiniz ki burada sıfıra bölünme hatasıyla karşılaşma ihtimalimiz var. Bunu engellemek için ise minor inputunun sıfıra eşit olduğu durumu kontrol edip if koşulu içerisinde tekrar pozisyonunu 1 olarak ayarlıyoruz. Böylece trackbarımız aslında sıfırdan değil bir’den başlamış olacak.

Diğer if koşulumuz ise benim spesifik amacım için yazdığım ama belki sizinde işinize yarayacak olan bir durum. Ben bu çembere 3D dünyamızda sadece sağdan, soldan veya karşıdan bakmayı tercih ediyorum. Eğer siz alttan ve üstten görünümleri de denemek istiyorsanız bu koşula ihtiyacınız yok.

 

Adım 4: Elips Çizimi ve Çember Tespiti Fonksiyonu

Elipsimizi çizmek için OpenCV içerisindeki ellipse fonksiyonunu kullanıyoruz. Parametreleri sırasıyla: üzerine çizeceğimiz görsel, merkez koordinatları(tuple olarak verilmeli), major minor uzunlukları (tuple), duruş açısı, çizilmeye başlanacağı açı, çizmeyi bırakacağı açı, renk (tuple), kalınlık. Gerekli inputlarımızı bu parametrelere yerleştiriyoruz. Ardından elipsin merkezini görmek için çok küçük bir çember çiziyoruz. çap parametresine 2 vererek nokta gibi görünmesini sağlıyoruz.

İşte şimdi beklediğimiz an geldi. Bilgisayara çemberleri buldurma vakti. HoughCircles fonksiyonunu kullanarak çemberleri buluyoruz. Parametreleri sırasıyla: görsel kaynağı, tespit metodu, görsel büyüklüğü oranı (scale, 1 yazıldığında orijinal boyutu kullanırsınız), aranacak çemberler arası mesafe, maskeleme miktarı algoritması 1, maskeleme miktarı algoritması 2, aranacak minimum çaplı çember, aranacak maksimum çaplı çember. Trackbar’lardan aldığımız p1 ve p2‘yi burada kullanıyoruz.

Ben bu yazıyı yazarken tarih 2021’nin Ocak ayını gösteriyor ve OpenCV’nin kendi dokumantasyonunda belirttiği üzere HoughCircles fonksiyonuna verilecek metodlardan sadece HOUGH_GRADIENT metodu kullanıma açık. Diğer fonksiyonlar da tamamlandığında çok daha efektif sonuçlar elde edebileceğiz.

 Adım 5: Tespit Edilen Çemberleri Gösterme ve Diğer Görsel Ögeler

Bu adımda göreceğimiz her şeyi try bloku içerisine yazıyoruz. Çünkü görselde çember bulunamadığında hata döndürülüyor. Öncelikle tespit ettiğimiz çemberi kullanabilmek için 16 bitlik tam sayı sistemine çeviriyoruz. Sonrasında çember sayımızı bir değişkene atıp, bunu görselimizin köşesine putText metodu yardımıyla yazıyoruz. Ardından bütün çemberlerin verilerinin ortalamasını alarak bulacağımız yegane çember için bir liste açıyoruz. Elemanları sırasıyla merkez koordinatları olan x, y ve çap uzunluğu olacak.

Şimdi tespit ettiğimiz çemberleri, eğer showAll trackbarı açıksa, for döngüsü yarımıyla tek tek görselimize çizelim. Bunun için yine OpenCV’nin circle metodunu kullanıyoruz. ve her çemberin verilerini estimatedCircle listesine ekliyoruz.

Ve ardından yegane çemberimizi çizmek için elde ettiğimiz verilerin ortalamasını alıyoruz ve circle metodu ile farklı bir renkte çiziyoruz.

Şimdide except bloku içerisinde çember bulunamama durumunda ekrana çember bulunamadı yazısını yazıyoruz.


Ve son olarak finally bloku içerisinde renklerin anlamlarının olduğu açıklamayı görsel üzerine yazıp, ardından görselimizi global’de oluşturduğumuz pencere üzerinde imshow metodu yardımıyla açıyoruz.

 

Adım 6: Kodu Çalıştırma ve Deneyler Yapma

     

 

Program çalıştığında karşımıza böyle bir ekran gelecek. Yarıçapı 100 olan bir çember çizdiğimizi ve bilgisayarın burada 1 adet çember bulduğunu (kırmızıyla gösterilmiş) görüyoruz. Artık major-minor uzunluklarını değiştirip testlerimizi yapabiliriz.

Görüldüğü gibi çizdiğimiz şeklin merkezi çok yakın bir şekilde tespit edilebiliyor. Ancak yarı çap uzunluğu bulma konusunda birtakım sorunlar halen mevcut. Projede geliştirme yaptıkça bu sorunlarda çözülecektir. Github hesabım üzerinden projeyi takibe alabilirsiniz.

Çember bulunamayacak kadar dar bir açıya gelindiğinde p2 parametresini düşürerek daha fazla çember bulmasını sağlayabiliriz.

Çok fazla çember bulunduğunda ekran yeşille kaplanmasın diye showAll parametresini sıfıra çekebiliriz.

Bundan sonrası size kalmış. Yazımın başlarında belirttiğim Qt kütüphanesi ile arayüz tasarlama işini şimdilik size bırakıyorum.

Projenizde başarılar , yazdığınız kodların tek seferde çalışmasını dilerim. Hatasız bir kod ile bir sonraki yazıda görüşmek üzere…

Twitter FuzuliKral, Github GulerEnes.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir