ArUco işaretçilerinin birbirlerine göre pozisyonlarını almak

Ali Yasin Eser
İyi Programlama
Published in
4 min readJun 23, 2018

--

Herkese selamlar. Bitirme projemi gerçekleştirirken (Ultrason destekli biyopsi operasyonunda artırılmış gerçeklik rehber yazılımı) kaynak eksikliğini fark ederek bir raporlama yoluna gitmeye karar verdim. Her aşamayı bir parçaya ayırarak size aktarmaya çalışacağım. Bugün size ArUco işaretçilerinin birbirlerine göre pozisyonlarını ve rotasyonlarını almaktan bahsedeceğim. Matematik kısmını işlemeyeceğim fakat gerekli bilgiyi kaynaklar kısmında bulabilirsiniz.

Bu aşamada yapmış olmamız gerekenler, kamera kalibrasyonu ve ArUco işaretçilerinin takibi. Bu aşamaları gerçekleştirmekte sorun çekmediyseniz, sonraki aşama çok basit kalacaktır.

ArUco işaretçilerin üç boyutlu pozları ArUco kütüphanesinin estimatePoseSingleMarkers fonksiyonu ile saptanır açıklamasını yapmıştık. Fonksiyonun bize verdiği vektörler olan rotasyon ve öteleme vektörleri, her işaretçi için ayrı ayrıdır ve işaretçilerin orta noktasını merkez referans(0,0,0) olarak almakta ve kameranın bu referansa olan mesafesi ve rotasyonunu vermektedir. Bu merkez referanslar aslında her işaretçi için ayrı bir üç boyutlu uzay manasına gelmektedir.

İki adet işaretçinin poz tahminini yaparak elimize rotasyon ve öteleme vektörlerinin geçtiğini varsayalım. Vektörlerimize A ve B vektörleri diyelim. Amacımız, A ve B vektörlerinin farkını bularak bu farkı A veya B(işlemi nasıl yaptığımıza bağlı) vektörü ile toplayarak bir işaretçinin pozisyon ve rotasyonunu diğerinin cinsinden elde edebilmek.

İki işaretçi ve bir kameranın bulunduğu ortam. Elde edilmek istenen vektör AB vektörü.

Yukarıdaki şemada görüldüğü üzere kamera tarafından iki işaretçi gözüküyor. İşaretçi bir ve iki için A ve B, kamera için C dedik. ArUco bize AC ve BC vektörlerini sağlamakta. Elde etmemiz gereken ise AB vektörü. Yapılması gereken işlem:

AB = AC - BC

Bunun için önce rvec ve tvec denilen vektörlerimizi nasıl tersine çeviririz bunu öğrenmemiz gerek. Rodriguez açısı ile ifade edilmiş bir rotasyon ve verilen öteleme vektörü için python kodumuz şu şekildedir:

Burada Rodriguez fonksiyonunun işlevinden bahstememiz gerek. Rodriguez fonksiyonunu burada basitçe vektörden matrise geçmek için kullanıyoruz. Rodriguez açılarını 3x3 matris veya 3x1 vektör şeklinde ifade etmemiz mümkün. Bunu yapmamızın sebebi vektör çarpımında boyutların eşleşmesini sağlamak. Hatırlatmak gerekirse iki matrisi çarpmak için ilk matrisin sütun sayısı ile ikinci matrisin satır sayısı eşit olmalı. Transpoz ve çarpımın matematiksel ispat ve tanımını yapamayacağım, ilgililer openCV dökümantasyonuna başvurabilirler.

Bu kısımda soru işaretleri mevcut değilse sonraki aşamaya geçebiliriz. Geldiğimiz nokta:

AB = AC + (-BC)

Elimizde AC ve (-BC) vektörü bulunmakta. Geriye sadece bu iki rotasyon+öteleme vektör setlerini toplamak kaldı. Fakat bunun için de openCV fonksiyonu kullanarak işlerimizi kolaylaştırabiliriz. Kullanacağımız fonksiyonun ismi composeRT ve yaptığı şey verilen iki rvec ve tvec değerlerini birleştirmek. Bu aşamayı relativePosition (ilgili/alakalı pozisyon) adı altında bir fonksiyonu yazarak ifade edecek olursak:

Burada yaptıklarımız:

  • Vektörleri 3x1 forma sokarak openCV hatalarından kurtulduk
  • Yazdığımız inversePerspective fonksiyonu ile ikinci işaretçi vektörlerini tersine çevirdik.
  • İlk işaretçi ile tersine çevrilmiş ikinci işaretçi vektörlerini birleştirdik ve aradaki farkı elde etmiş olduk. info değişkeniyle alıp sadece ilk elemanlarını almamızın sebebi sadece okuma kolaylığıdır. Çok daha fazla parametre döndürmekte( vektörlerin türevleri vb. bilgileri de iletiyor fakat ihtiyacım olmadığı için bilgim edinmedim, dökümantasyondan ulaşabilirsiniz).
  • Daha sonraki openCV işlemleri için sonuç vektörlerini 3x1 matris formuna çeviriyoruz.

Fonksiyonumuz tamam. Bir de tam kod ile görmek lazım değil mi? Aşağıda tam kodunu bulacağınız örneğin bilmediğiniz kısımlarını önceki yazılarımda[kalibrasyon, takip] bulabilirsiniz.

Kodumuzu örneğin “deneme.py” isminde bir dosyaya koyduğumuz zaman çalıştıracağımız komut:

python deneme.py --coefficients 0 --firstMarker 12 --secondMarker 34

Burada:

  • coefficients: sıfır ise calibrasyon yapılmadı, 1 ise yapıldı. Yapıldı ise kod üzerinden hangi dizinde olduğunu belirtin.
  • firstMarker: ilk olarak kabul ettiğiniz işaretçinin ArUco numarası.
  • secondMarker: ikinci olarak kabul ettiğiniz işaretçinin ArUco numarası.

Kullanımı da şu şekilde:

  • Video gerçek zamanlı olarak akmakta. Belirttiğiniz iki işaretçiyi tutarsanız şunu göreceksiniz:
Video akışında bu şekilde sadece işaretçiler tespit edilmiş olmalı.
  • Eğer “c” tuşuna basarsanız kalibrasyon yapılacak. Bahsettiğim kalibrasyon, iki işaretçinin birbirine göre olan rotasyon ve lokasyon farkının alınıp bunun ikinci işaretçinin rotasyon ve lokasyonuyla toplanması. Karşınıza şu şekilde çıkmalı:
Artık aradaki farkı elde ettik. Tam lokasyonu tespit ederek işaretçinin ortasını bulduk.
  • Bu aşamadan sonra perspektif dönüşümü iki işaretçi arasında gerçekleştirdiniz demektir. İkinci işaretçiyi hareket ettirdikçe xyz referansları da değişecektir. Bunun sebebi ikinci işaretçinin lokasyon ve rotasyonuna göre yaptığınız kalibrasyonun sabit oluyor olması. Kodu değiştirerek bunu her çerçevede(frame) yaparsanız ikisi arasındaki lokasyon ve rotasyona sürekli sahip olabilirsiniz. Yapmadığınızı varsayalım, iki işaretçi arasında iki santimetre solunda ve 10 derece açı varsa siz artık ikinci işaretçinin iki santimetre solunda ve 10 derece açıyla döndürülmüş noktasını bulabilirsiniz demektir. Bu bilgi size çok çeşitli bilgiler sunabilir, örneğin bir işaretçi ile üç boyutlu dünyada en önemli referansları elde edip bir çözüm gerçekleştirebilirsiniz. Hayal gücünüze kalmış. Yapmadığınız durumda karşılaşacağınız görüntü:
Tek zamanlı kalibrasyon sonucu. İkinci işaretçi ile toplandıkça kaymaktadır.

Kodun çoğu önceki yazılarımda mevcut. Yorumlar ile destekleyerek github üzerinde bitirme projemin bulunduğu proje sayfasından güncelleyeceğim, daha günceline oradan erişmeniz mümkün. Yine de anlamak adına baştan yazmanız sizin için daha uygun olacaktır.

Gelelim bitirme projemin bunlarla ilgisine. Ben sabit ve tek zamanlı kalibrasyonla ultrason ve iğne ucunu takip edebiliyorum. Bu şekilde üç boyutlu dünyada iğne vücudunuzda dahi olsa ben işaretçiyi gördüğüm zaman kesin lokasyonu takip edebiliyorum. Görüntüde işaretçilerin nasıl göründüğünden, matematiksel hatalardan, ışık değişiminden kamera kalibrasyonundan ve diğer çeşitli hatalardan dolayı problemler ve ani değişimler oluşacaktır. Bunun için Kalman filtresi kullanmanızı tavsiye ederim.

Bu blogda öğrendiğiniz bilgilerle, ArUco işaretçileri ile işlem yapmanın temelini elde ettiğinizi söyleyebilirim. Bundan sonrası biraz hayal gücü ve bolca pratik. Çeşitli çalışmalara göz atarak onlar üzerinde de çalışabilirsiniz elbette. Bilgilerimi aktarıp size katkı sağlayabildiğimi umuyorum. İyi projeler, çalışmalar ve mutlu günler dilerim.

Kaynaklar:

--

--

Ali Yasin Eser
İyi Programlama

iOS Developer with Computer Vision and Embedded Systems background. Solo musician with 3 albums.