Paralel Programlama

PC tabanlı görüntü işleme uygulamalarında, paralel programlama teknikleri kullanmak çok radikal hız artışları sağlayabilir. Yazılımımız, gerçekten sahip olduğumuz donanımın hakkın veriyor mu? Günden güne hızlanan bilgisayarlar, çok çekirdekli işlemciler, devasa hafızalar… Bu kaynakları gerçekten etkin olarak kullanabiliyor muyuz?

Düzgün yönetilmememiş paralel programlama (Multi threaded programming) uygulamalarında çoğu kez olan yukarıdaki gibidir 🙂 Bilmem kaç çekirdekli cep telefonlarının neden bu kadar yavaş olduğu sorusunun da cevabı? Tamam çekirdek çok da, uygulama onları nasıl kullanıyor?

Paralel programlama derken tam olarak neyi kastediyoruz?

Paralel programlama, bilgisayar işlemcisinde gerçekleşen işlemlerin, birinin diğerini beklemediği, aynı anda bir çok işlemin çalıştığı uygulamalardır. Visual Studio .NET dilinden konuşursak, çok kanallı programlar (Multiple threads), parallel tasks, background worker v.b. yapılar ile çoğu programcının bir şekilde aşina olduğu yapılardır. Bu yapılar ile uğraşanlar iyi bilir, duruma göre tam bir başağrısıdırlar. Geliştirmesi zor, debug etmesi zor, sonuçların ekranda gösterilmesi bile ayrı bir teknik gerektirir. Lock objects ler, autoreset, manual reset eventler, mutexler, semaphore lar v.b. .NET yapıları, durduk yere hiç bir programcının severek bulaşacağı yapılar değildir, kabul edelim.


Eğer öyle ise, görüntü işleme uygulamam gerçekten paralel çalışmalı mı?
Bu  sorunun cevabı, eğer zaman sorunum varsa, ya da birim sürede çok daha fazla kontrol etmem gerekiyorsa EVET, aksi halde HAYIR dır.

Gerçek hayattan örnek vermek gerekirse, Derby traş bıçakları fabrikasında bir makinada kurulu olan sistemimiz, her 600 milisaniyede bir, üretilen traş bıçağını kontrol etmektedir. Böyle bir sistemde,

  • Kameradan Görüntünün Alınması (80 ms.)
  • Alınan Görüntünün İşlenmesi (60 ms)

sürmektedir. Özetle, tetik sinyali geldikten sonra, en geç 150 ms. sonra, OK ya da NOK cevabını sisteme bildirmekteyiz. Geri kalan 450 ms. içinde de sistem diğer ürünün gelmesini beklemektedir. Dolayısıyla, bir zaman sorunu yoktur, işlemleri paralel yapmak kimseye bir şey kazandırmayacaktır. Bu durumda, eski tip, ardışıl programlama (görüntü al, işle, dijital çıkış ver, bekle, başa dön..) en doğru seçenek olacaktır.

Peki ya sürekli ve çok hızlı kontrol etmem gerekirse, mesela araçlardaki şerit takip sistemi örneği gibi. Sistem sürekli ve olabildiğince hızlı görüntü almalı, işlemeli ve hiç beklemeden yeniden görüntü almalı, yeniden işlemeli. bu alma-işleme süreci ne kadar kısa olursa, sistem o kadar sağlıklı / gerçeğe yakın çalışacaktır.

Yine gerçek bir örnek verelim;

Halı Kesme makinası olarak kurulumunu yaptığımız sistemde 13 adet kamera vardır. 50 m/dk hızıyla üretilen halıları dikey olarak tam kesim çizgisinden kesmek istiyoruz. Bunun için 13 bıçağın, kameralar yardımıyla anlık olarak sağa-sola yönlendirilmesi ve tam çizgi üzerinden kesim yapılması sağlanmalıdır.

Halı, esnek olduğundan, kesim çizgisi sağa sola kayabilmekte ve ancak kamera yardımıyla çizgiyi görüp takip etmesi sağlanabilmektedir. Sorun şu ki, 50 m/dk. hızında üretim yapılırken, 120 ms. içinde halı 10 cm kaymaktadır. Dolayısıyla, bu projede, tipik olarak 1. kameradan görüntü al, işle, 2. ye geç al işle, sonra 3. ye… şeklinde bir yaklaşım izlenmiş olsa, algoritmalar ne kadar düzgün çalışırsa çalışsın, sonuç tam bir felaket olacaktır. Tek bir kameradan görüntü alınıp yine aynı kameraya sıra gelene kadar, halı 1 m. den fazla ilerleyecektir ve böyle bir sistem elbette kabul edilemez.

HALCON 12 ile Paralel Programlama

Visual Studio kullanarak geliştireceğimiz, çok kameralı tipik bir paralel programlama algoritması genel hatları ile şu şekildedir.

3 adet genel thread vardır.

  1. Grabbing Threads : Var olan kamera sayısı kadar thread açılır. Her bir thread sonsuz bir döngüde görüntü alır. Diyelim ki 4 kamera var. 4 ü de eş zamanlı olarak görüntü alır. Biri diğerini beklemez, her biri bağımsız olarak kendi görüntüsünü alır.
  2. Processing Thread : Yine kamera sayısı kadar thread açılır. Her bir thread, sonsuz bir döngü içinde, kendi kamerasından görüntü alınmışsa, bunu işler yine başa döner (yeni görüntü alınmasını bekler) görüntüyü işlemeye başladığı anda, grabbing thread yeniden resim alma işi ile meşgul olur. Diyelim ki, resim alma (grabbing) 60 ms, işleme ise 20 ms sürsün. bu durumda, tek bir kamera 60 ms içinde sonucu verecektir (80 değil) çünkü 20 ms. işleme sürerken, grabbing thread görüntü almaya başlamıştı ve işleme bittikten 40 ms. sonra (60 değil) yeni görüntü gelecektir.
  3. User Interface Thread : Benim kullanmadığım ama genel amacı, bulunan sonuçların ekranda gösterilmesi, label buton panel v.b. form kontrollerinin çizilmesi amacıyla kullanılır. Ben, HALCON fonksiyonlarına, DisplayHandle gibi bir değişken gönderiyorum ve ekran işlemlerini de HALCON içinden yaptırıyorum. Böylece, sonuçların toparlanması ekranlarda gösterilmesi gibi işleri C# tarafında değil, HALCON tarafında hallediyorum.

Bu yapı, kendi içinde gayet hızlı çalışacak ve CPU kullanımı tüm çekirdeklerde %100 e vuracaktır. bu iyiye işarettir, tek bir cpu birimini boşa harcamaya gerek yoktur ve uygulamamız resmen donanımın hakkını veriyor demektir.

Ayrıca, bellek kullanımına dikkat edin, sonsuz döngüde çalışan thread (kanal) yapıları, nesneleri hafızadan atamıyorsa, çok çabuk hafıza dolabilir. İdealde hafızanın sabit kalması gerekmektedir.

HALCON 12 ile Paralel Programlama

Visual Studio ile, paralel programlama tekniklerini etkin bir şekilde kullanarak, çok kameralı sistemde, tüm görüntü alma ve işleme kanallarını paralel çalıştırarak, çok büyük bir hız avantajı sağladık. Şimdi HALCON ile bu yapıyı daha da geliştirmek mümkün.

Öncelikle HALCON, tecrübeli olmayan programcılar ya da .NET çok kanallı yapılarını sevmeyen tercih etmeyen kullanıcılar için bir çok yenilik barındırmaktadır. Artık tüm paralel programlama işlemlerini HALCON kendisi yerine getirebilmektedir. HALCON12, yazdığınız kod parçalarını (HDevelop procedure) tek bir tıklama ile paralel olarak çalıştırabilmektedir. (Bizim C# ile tabir yerinde ise, o kadar kastırarak yaptığımız dümenlerin hepsi boşa mı gitti şimdi 🙁 )

Ve hala daha da fazlasını sunmaktadır. O da şu :

diyelim ki, her bir kameradan alınan görüntüde, tek bir işlem değil de, birden fazla işlem yapmak durumundayım. Mesela alınan görüntüde hem barkod, hem karekod, hem de OCR yapmak durumundayım diyelim.

Barkod bulma 40 ms, OCR 90 ms, karekod okuma ise 70 ms. civarı sürsün.

HDevelop içinde bu işi yapan 3 güzel procedure yazdığımı varsayalım. HALCON 12, bu 3 procedure ü paralel olarak başlatabilmekte (par_start komutu ile) Buraya kadar olan, zaten tecrübeli C# kullanıcılarının daha önceden yaptığına denk gelen kısım. HALCON, par_join komutu ile, bu 3 procedure ü de aynı anda çalıştırmakta, en son hangisi biterse, diğerleri onu beklemekte, ve tek bir yapı çalıştırmışım gibi sonlanmakta. Dolayısıyla, bu yapıları paralel çalıştır diyorum, sanki hepsi tam da aynı anda çalışıp aynı anda bitmiş gibi, bir alt satırda da hepsinin sonuçlarını toplayabiliyorum. Bizim örneğimizde, 90 ms. sonunda barkod, karekod ve OCR işlemim bitmiş, elimde hazır sonuçlar olmuş oluyor.

Bu güçlü yapıyı, C# daki özgün multi thread yapım ile birleştirdim. Ortaya, C# tarafında, tüm kameralardan görüntü alma ve işleme işlemlerinin paralel koşturulduğu, HALCON tarafında da bir çok procedure (alt programı) aynı anda çalıştırıldığı, hibrit bir yapı çıktı. Sistemi 13 kamera için çalıştırdığımda, cpu fanı hemen devreye girmekte CPU maksimum performansa zorlanmakta. (Bu aşamada i7 gibi işlemcilerin gerçek farkını ve hızını hissedebilmek de bir programcı olarak ayrı bir mutluluk kaynağı oluyor.)

Peki, neden aynı anda bir çok procedure start edilir. Ya da ne gibi uygulamalar buna ihtiyaç duyar.

Açıkçası bu çok sık karşılaşılan bir yapı veya ihtiyaç değildir.

Bizim halı kesme makinasında, siztem kesim çizgisini aramaktadır. Yazdığım algoritmalarda bazen var_threshold ile sonuca gitmiş, bazen de binary_threshold işe yaramıştı. Bazı durumlarda median_rect filtresi güzel sonuçlar vermiş, bazen ise label_to_region işe yaramıştı. Bazen GMM classification imdada yetişmiş, bazen resmi decompose edip hsv kanallarına bakmam gerekmişti?

İyi ama, bunların hangisini kullanmam en doğrusuydu? Apaçık ki, hiç biri tek başına yeterli değil. Hepsini tek tek denesem, bu sefer çok uzun sürebilir. İşte tam da bu anda, yazdığım tüm alt programları (ki aslında hepsinin derdi aynı, hepsi de çizgi arıyor) aynı anda start ediyorum. Resmi grab etmem (kameradan almam) ortalama 60 ms. kadar sürüyor (bendeki pixel clock, exposure değerleri ile inebildiğim minimum değer) ve bir sonraki resim gelene kadar, tüm yapıları HALCON aynı anda start ediyor. bunlardan bir veya daha fazlası sonucu zaten buluyor ve bulduğum sonucu işliyorum.

Sonuç?

Eğer bu kadar fazla multitasking sonucu yazdığınız kodlar halıya çıkmadıysa, iyi yoldasınız demektir.

Yazının Özeti :

HALCON 12 güçlü bir multithreading (paralel programlama) desteği sunmaktadır. par_start, par_join, mutex, message queue yapılarını inceleyin, örneklere bakın, dokümanları okuyun, çok yardımcı olacaktır. Buna rağmen danışmanız gereken bir yer olursa, buradan ya da info@mavis.com.tr ile bana istediğiniz zaman ulaşabilirsiniz.

kolay Gelsin 😉

3D Görüntü İşleme Teknikleri – 1

3D uygulamaları son zamanlarda hızla yaygınlaşmaktadır. Bu makalemizde, mevcut 3D modellerini ve uygulama alanlarını göreceğiz. Burada kastedilen 3D, görüntü işlemede kullanılan 3D dir. Standart kameralar (monocular) X-Y düzleminde görüntüler verir. Biz, aynı zamanda derinlik (Z) bilgisini de içeren, X-Y-Z bilgisi verebilen teknolojilere hızlıca değineceğiz.

Günümüzde yaygın olarak kullanılan 3D yapay görme teknolojileri şunlardır.

1. Laser Triangulation
Bu modelde, genellikle bir çizgi lazer kaynağı ve kalibre edilmiş bir kamera kullanılır. Genellikle çizgi lazer ve kamera, birlikte tek bir kutu içinde yer alır. Sistemin çalışabilmesi için, 3 boyutlu olarak algılanmak istenen nesnenin kontrollü bir şekilde hareket etmesi gerekmektedir. (Bir encoder yardımıyla nesnenin ne kadar gittiği hesaplanabilir) sistem sürekli fotoğraf çekerek lazer çizgisindeki profil değişikliğinden faydalanarak, 3 boyutlu nesnenin profilini çıkartır. Piyasada farklı alternatifler vardır, daha önceden LPS 36 isimli bir modeli incelemiş, HALCON ile çeşitli uygulamalar geliştirmiştim. Ülkemizde bu veya benzer ürünleri kolaylıkla temin etmek mümkündür.

2. Time Of Flight Kameralar

Kişisel olarak, geleceklerinin iyi olduğunu düşündüğüm 3D kamera teknolojisidir. Daha önce şu makalede detaylı olarak bu kameraları anlatmıştım. Çalışma prensipleri (özetle) 3D olarak belirlenmek istenen nesnenin fotoğrafı alınırken, aynı zamanda infrared (veya başka bir dalga) göndermek ve gelen dalganın ne kadar geciktiğini ölçerek (bir nevi radar), her noktada mesafeyi hesaplamak mantığına dayanır. Gerçekte zaman ölçümü Frekans Kaydırma (Frequency shift) modülasyonu ile gerçekleştirilir. Yine piyasada (nadir olmakla birlikte) TOF kameralar mevcuttur.

3. Stereovision

En yaygın olarak kullanılan 3D teknolojisidir. İnsan gözü modelinde olduğu gibi, 2 kamera kullanılır. Kameraların arasındaki mesafe ve merkez doğrultu açıları net olarak bilindiğinden, her bir noktanın, her iki kameradaki izdüşümü, basit geometrik hesaplamalar ile bulunabilmektedir. (İleride çalışma prensibi daha detaylı anlatılacaktır)

 

4. Fringe Projection

Bu teknolojide, algılanacak 3 boyutlu nesne üzerine bir projektör yardımıyla özel bir desen (genelde çizgiler vb) düşürülür. Kamera bu çizgileri algılar. Çizgilerdeki değişim, 3D profili verir. Laser Triangulation tekniğinde, nesne hareketli idi, bu teknikte nesne sabit olup, üzerine tek bir lazer çizgi yerine, pek çok çizgi aynı anda düşürülmektedir. Çalışma prensibi aynıdır.

 

5. Kinect (PrimeSense) Grubu

Oyun konsollarının (XBox, PS v.b.) yaygınlaşması ile birlikte genellikle PrimeSense firmasının sensörlerinin kullandığı, stereovision tekniğidir. Aslında farklı bir teknik olmamakla birlikte, çok yaygın bir grup olduğu için ayrı bir başlık olarak ele alınabilir. Burada, projektör, bilinen pattern’e sahip görüntüyü nesne üzerine yollar. Kamera bu patterni algılar. Orijinal pattern ile olan değişimden yola çıkarak, 3 boyut oluşturmaya çalışır.

6. Active Stereo Vision

Bu teknikte, stereovision modeli biraz geliştirilerek, araya bir projektör eklenmiştir. Projektör rastlantısal bir pattern oluşturup nesnenin üzerine gönderir. Stereo kameralar bu patterni yakalayıp, 3 boyut bilgisini çıkartır. Normal stereo Vision da, projektör yoktu. Kameralar, gerçek cismin görüntüsünden yola çıkarak 3 boyut bilgisini çıkartmaya çalışıyordu. Cismin üzerinde texture (şekil, yazı, desen vb.) yoksa, böyle bir durumda stereo vision başarılı olamıyordu. Çünkü her pixel kendi komşu pixelleri ile aynı bilgiyi taşıyor farklılık yaratmıyordu. Bu modelde, projektör cisim üzerine yeterli karmaşıklıkta desen varmış gibi pattern yollar. Kendi gönderdiği patterni arar ve 3 boyut bilgisini çıkartır. En sağlıklı 3D yöntemi de, günümüzde budur. (Firmamız, Active Stereo Vision ürünü olan Ensenso cihazlarının Türkiye distribütörüdür.)

Tüm teknikleri artı ve eksileri ile karşılaştıran aşağıdaki gibi bir tablo yaptım.

 

 

Buradaki Multi-View stereo, aynı nesneye birden fazla yerden (ön, arka, sağ, sol v.b.) bakmak gerektiği durumları ifade eder. Örneğin 3-4 Kinect cihazını farklı açılardan birbirine bağlayıp daha iyi bir görüntü elde edemezsiniz. (Kinect böyle bir teknolojiyi sunmamaktadır, tek ve bağımsız çalışmaktadır gibi.)

Bu konuya kaldığımız yerden devam edeceğiz. Önce Stereo Vision teknolojisine daha detaylı giriş yapıp, işin tekniğini kavrayacak, sonra HALCON ile stereo vision uygulaması nasıl geliştiririz buna bakacağız.

Bir sonraki bölüm için tıklayınız…

 

Kameralı Hız Belirleme

Kamera ile hız belirlemek (bir tür radar) konusunda öğrenciler ya da meraklılar için basit bir HALCON kodu ile yardımcı olmak istedim. Kameralı hız belirleme konusunda bir çok yaklaşım olabilir. En sık kullanılan yaklaşım, ardışıl olarak alınan 2 görüntü arasında, farklılıkları belirlemek, (bu farklılıklar genellikle yer değiştiren nesneler, yani araçlardır) ve bu farklılıktan kaynaklanan yer değiştirme mesafesini bulup, arada geçen zamana bölmek suretiyle hızın elde edilmesidir.

Örnek olması açısından, şirketimizin balkonundan cep telefonumla sokaktan geçen araçlarn resimlerini çektim. (Normalde, kullanılan endüstriye kameralar, resim ile birlikte resmin alındığı hassas zaman bilgisini de verirler. Konuyla ciddi ilgilenenler o tür kameralar bulmalıdır. örneğin iDS imaging ürünleri)  Ben cep telefonumla çektiğim için, ortalama 2 sn bekledim. (Yani, umarım) Tabii elim sabit olmadığı için kamera biraz titredi 🙂 Yine de tüm bunlar, yoldan geçen güzelim twingonun hızını iyi kötü belirlemem için engel teşkil etmedi.

İşte aldığım resimler ve işte bunları işleyen HALCON kodu.

Aslında buradan rar dosyasını da indirebilirsiniz.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Programın çalıştırılması ile oluşan ekran görüntüsü ise

 

 

 

 

 

 

 

 

Programın çalışma şekli.

Program aslında thresholding ile, lacivert renkli nesneleri arar. Görüntü renkli kamera ile alındığı için, önce RGB kanallarına ayırıyor resmi. Sonra HSV değerlerini buluyor. Threshold işlemlerini HSV kanallarında yapıyor.

Bir kere aracı bulduktan sonra, gerisi zaten 4 işlem. Anlatmaya gerek yok.

İdealde, bunun gibi sadece özel bir renge göre radar yapılmaz tabii 🙂

İdealde olması gereken, iki resmin karşılaştırılıp, aradaki farkı oluşturan noktalardan araçlar bulunup hız belirleme yapılmasıdır. check_difference isimli HALCON örneği incelemeye değer güzel bir çalışmadır mesela.

Konuyla ilgilenenlere kolay gelsin diyorum. İlgi alaka olursa, daha profesyonel olarak konuya yaklaşımları da irdeleyebiliriz.

Kirli İşler için Classifier Kullanın

Görüntü işleme uygulamalarında, bazen göze çok basit görünen işler, içinden çıkılmaz hale gelebilir. Threshold seçimi bunların başında gelir. Uygun bir threshold seçersiniz Diyelim ki var_threshold. 3-5 örnekte mükemmel çalışır, 1-2 örnekte teklemeye başlar, sonunda -öyle resimler çıkar ki- hiç çalışmaz 🙁 Neyse ki, HALCON var, moral bozmaya gerek yok. “Bir çok alternatif thresholding yöntemi sunuyor ne de olsa” özgüveniyle, hemen başka bir threshold seçilir. Mesela dynamic threshold. Sonuçlar baştan kontrol edilir. Eh, biraz daha iyi. Ama hala yakalanamayan örnekler var. İşin kötüsü, bazı resimlerde var_threshold iyi sonuç verirken, bazen de dyn_yhreshold iyi sonuç veriyor. Hangi durumda hangisini kullanalım? İkisinin sonucunu union yapıp denesek, bu kez de bazı istenmeyen durumlar çıkıyor. İstenmeyen durumları opening_circle vb. fonksiyonlarla elesek, sonra dilate etsek… derken bir bakmışsınız, yüzlerce satır HALCON kodu ile boğuşuyorsunuz.

Bu durum hemen hemen tüm görüntü işlemecilerin başına sık sık gelmektedir. Böyle bir durumla karşılaştıysanız, yanlış yoldasınız demektir, en iyisi önce bir mola verip şu klibi izleyin.

http://www.youtube.com/watch?v=y14_nLOi7YU

“Dirty deeds done dirt cheap”. Demek istediğimiz tam da bu. Kirli işler öyle kastırarak değil, (bizde) ucuz ve kolay yoldan halledilir.

Classifier Kullanımı :

Classifier belirgin 1 ya da 1 den fazla ortak özelliği bulunan nesneleri, bu ortak özelliklerine göre sınıflayarak seçmek için kullanılır. Örneğin bir resimdeki nesneleri, renklerine göre sınıflamak isteyebiliriz. HALCON a, bana bu resimdeki yeşilleri, mavileri, sarıları ver diyebilirim. Aksi halde, tek tek, farklı renklerin farklı threshold değerleri ile ilgilenmek zorunda kalacaktım. Ve bence işin en güzel yanı, bir örnek resim üzerinde, nesneleri tek tek göstrerek, mavi bu, yeşil bu, sarı bu, hadi bunları öğren, ve diğer resimleri verdiğimde, bana bu renkleri bu diyebilme kolaylığı.

Özetle, classifier yaygın olarak kullanılmalıdır. Çok düzgün ve güvenilir sonuçlar verir. Hızlı çalışır, iyi optimize edilmiştir. Sonuçlar kaydedilebilir / okunabilir vs.

 

Threshold seçimi ile uğraşıp 100 lerce satır HALCON kodunu silip, classifier kullanarak 3-5 satırla halledebileceğinizi görünce, ofisin içinde baştan sona Angus Young yürüyüşü yapacağınıza eminim. (yukarıdaki klibin ilk saniyelerinde. Angus Young yürüyüşü yapmayı bilmiyorsanız, buradan öğrenebilirsiniz. http://www.youtube.com/watch?v=MPBSKl9TpO8 (hayatımda böyle saçma video görmedim) )

Şimdi GMM classifier kullanan bir örnek verelim.

Bronz renkli metal plakanın üzerindeki kırmızı renkli çizgileri yakalayan bir görüntü işleme programı yazmamız isteniyor.
Klasik thresholding yöntemlerine göre elde ettiğimiz sonuçlar :

Yukarıdaki örnekte, yakalamak istediğimiz kırmızı çizgiler gayet başarıyla yakalanmış. (Etrafı yeşil ile çizilerek gösterilmiş). Fakat, kırmızı çizginin kalınlığı azaldıkça, kırmızı boyanın etkisi de azalmakta ve threshold kırmızıyı yakalamakta biraz zorlanmaktadır.

Yukarıdaki örnekte, uygulamamızın kırmızı çizgiyi kısmen yakaladığını ama tam istediğimiz gibi olmadığını görüyoruz.

Sonuçta, yukarıdaki gibi bazı örnekler için ise, kırmızı çizginin hiç yakalanamadığını görüyoruz. Kırmızı çizginin bazen yakalanıp, bazen yakalanamaması,

  • plaka yüzeyinde ışık şiddetinin değişken olması (sağ ve sol iyi aydınlanıyor, orta taraf iyi aydınlanmıyor)
  • Çizgi kalınlığının değişken olması (dolayısıyla ince çizgilerde kırmızı rengin belirsizleşmesi)
  • Zeminde lekeler açık koyu bölgeler olması
  • Bronz zeminin kendi içinde kırmızılık içermesi

gibi sebeplerden olabilir.

 

 

 

 

 

 

 

 

Yukarıdaki resim, yanlış threshold denemeleri ile boğuşurken, farketmeden hızlıca artmış HALCON kodlamasını gösteriyor.

GMM classifier kullanılarak yazılan aşağıdaki kod ise, tüm durumlarda %100 çalışarak istenen sonucu almamızı sağlamıştır.

 

set_display_font (3600, 16, 'mono', 'true', 'false')

list_files ('C:/Projects/Bronz/R', ['files','follow_links'], ImageFiles)
* list_files ('C:/Projects/SahinMotor/deneme 2/çapraz ışık/nok', ['files','follow_links'], ImageFiles)
tuple_regexp_select (ImageFiles, ['\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima)$','ignore_case'], ImageFiles)

* Red Region seçimi
read_image (Image, 'Reddic.jpg')
gen_rectangle1 (ROI_0, 198.172, 226.049, 485.801, 901.164)
reduce_domain(Image, ROI_0, ImageReduced)
decompose3(ImageReduced, R, G, B)
bin_threshold(G, RedRegion)
*

create_class_gmm (3, 1, 1, 'full', 'none', 3, 42, GMMHandle)
add_samples_image_class_gmm (Image, RedRegion, GMMHandle, 0)
train_class_gmm (GMMHandle, 100, 0.001, 'training', 0.001, Centers, Iter)
create_class_lut_gmm (GMMHandle, ['bit_depth','rejection_threshold'], [6,0.03], ClassLUTHandle)
clear_class_gmm (GMMHandle)

dev_set_color('blue')
for Index := 0 to |ImageFiles| - 1 by 1
    read_image (Image, ImageFiles[Index])
    reduce_domain(Image, ROI_0, ImageReduced)
    classify_image_class_lut (ImageReduced, ClassRegions, ClassLUTHandle)
    closing_circle(ClassRegions, RegionClosing, 3.5)
    area_center(RegionClosing, Area, Row, Column)
    if (Area > 500)
        disp_message(3600, 'KIRMIZI', 'image', 12, 12, 'red', 'true')
    endif
    stop()
endfor

Photometric Stereo yöntemi

Görüntü işleme uygulamalarında genellikle kamera ve ışık sabit bir açıda durmaktadır. Oysa, sabit bir açıdan bakıldığında her zaman istediğimiz sonucu elde edemeyebiliriz. Örneğin bir cep telefonu ekranında çizik olup olmadığını anlamak için, telefon yüzeyini elimizde farklı açılar ile çevirir, farklı ışık yansımaları altında bakar ve ona göre karar veririz. Belirli bir açıdan bakıldığında yüzey temiz görünürken, farklı bir açıda çizikler belirgin hale gelebilir. Çiziklerin belirginleşmesi, tam çizik üzerine düşen ışınların gözümüze değil de başka yerlere yanıması sonucu, çiziğin koyu görülmesinden dolayıdır. Photometric Stereo, işte bu ve benzeri amaçlar için geliştirilmiş, hayli ileri bir görüntü işleme tekniğidir. Kamera sabit tutularak, ışık farklı açılardan verilir ve alınan tüm görüntülere bakılarak karar verilir. Genellikle yüzey kontrollerinde (surface inspecton) yaygın olarak kullanılır.

Çalışma Prensibi :

İnceleyeceğimiz nesneye, farklı açılardan ışık vererek, her bir ışık açısı altında görüntü alıp, alınan tüm görüntüleri değerlendirip tek bir görüntü elde etmek esasına dayanır.

Aşağıdaki resim, şampuan kutusu etiketindeki bozukluğun photometric stereo yöntemi ile bulunmasını göstermektedir.

Mavis olarak geliştirdiğimiz yapay görme uygulamaları, daha çok otomotiv ve otomotiv yan sanayi çözümleridir. Metal pul üzerinde yüzey kontrolü yapılarak, çizik, ezik, leke gibi hataların yakalanıp ayıklanması projesinde, photometric stereo kullandık.

İlk olarak o çiziği belirgin hale getirebilecek(içinin parlatılması veya gölge düşürülmesi) bir açıdan ışık vermemiz gerekiyor. Fakat bu verilen ışık, farklı yerlerdeki veya farklı yönlerdeki çizikleri belirgin hale getiremeyebilir.

45 er derece açıyla yerleştirilmiş, 4 ışık kaynağı ile 4 farklı görüntü alarak, bu görüntüleri photometric stereo işlemine tabi tutarak yüzeydeki bozuklukları yakaladık. (Photometric stereo için, kamera kalibrasyon işlemi gereklidir. Bunun için kamera kalibrasyonu makalemizi okuyabilirsiniz)

 

 

 

 

 

Bu görüntüler photometric stereo yöntemi ile birleştirilirse aşağıdaki görüntü elde edilir. Bu görüntünün işlenmesi ile hata net olarak yakalanır.

 

 

 

 

 

 

HALCON kodu :

read_image (Images, 'duz/1/'+[1:4])
for I := 1 to 4 by 1
    Message := 'Acquire image ' + I + ' of 4'
    select_obj (Images, ObjectSelected, I)
    dev_display (ObjectSelected)
    disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
    wait_seconds (0.5)
endfor
* Apply photometric stereo to determine the albedo
* and the surface gradient.
Slants := [39.4,40.5,39.5,38.4]
Tilts := [-6.0,83.7,172.9,-98.2]
ResultType := ['gradient','albedo']
photometric_stereo (Images, HeightField, Gradient, Albedo, Slants, Tilts, ResultType, 'poisson', [], [])
* Display the albedo image
dev_display (Albedo)

Uygun Threshold Seçimi

Kameralı kontrol uygulaması kurulum aşamasında, kameralardan alınan görüntü kalitesi tüm projenin kalitesini etkileyecği için son derece titiz çalışılmalıdır. Gerek fokus, gerek pozlama / diyafram ayarları hiç acele edilmeden, en optimal şekilde yapılmalıdır. Gerekirse alınan görüntüler, basit bir ön incelemeye tabi tutulmalı, var olan ayarlar (varsa) farklı modeller için de denenmeli ve öyle karar verilmelidir. Projenin kurulum aşamasında geçirilecek vakit ne kadar çok olursa olsun, asla ilerleyen aşamalarda istenen sonuçların elde edilemeyip yeniden başa dönülmesi ile kaybedilen zamanla kıyaslanamaz. Başlangıçta, herşeyden emin olup iyice tatmin olunduysa, ancak o zaman kod yazımına geçilmelidir. Var olan ayarlara göre bir yerlerden başlayalım, nasıl olsa ileride değiştiririz yaklaşımı (varsa) derhal terk edilmelidir. Bazen uygun açı ve görüntü kalitesini yakalamak için yapılan çalışmalar, müşteri tarafında (ya da 3. bir göz) henüz bir ilerleme sağlanamadı şeklinde yorumlanabilir. Müşteri, “Ekip günlerce gidip geliyor ama henüz ortada bir şey yok” şeklinde yakınıyorsa, o ekibin işini profesyonelce yapmaya çalıştığını düşünebiliriz. (Diğer ihtimal varsa da, biz düşünmek istemiyoruz 🙂 )

(Not : Pozlama/exposure, yazılım ile, diyafram ise lens üzerinden ayarlanır)

Pozlama/diyafram ya da uygun threshold seçiminde, projeden projeye değişebilmekle birlikte, genel doğrular şu şekilde özetlenebilir.

  1. Alınacak görüntüdeki açık-koyu arasında ortalama 100 birim fark olmalıdır. (Gray scale, 8 bit kamera ile çalıştığımız varsayılmıştır. Yani Beyaz = 255, Siyah = 0 ise)
  2. Açık renk, 255 e çok yakın olmamalıdır. 170-220 bandında gezinebilir mesela. 255 e çok yakın olması (ya da tam 255) olması durumunda, çevre ışık şartlarının biraz daha artması, bilgi kaybına sebep olacaktır. Keza, aslında açık olmayan renkler, fazla ışık şiddetinden dolayı açıkmış gibi hatalı algılamalara sebep olabilir.
  3. Koyu renk 0 a çok yakın olmamalıdır.Yukarıdakine benzer nedenlerden dolayı.
  4. Çoğu kez, göze iyi görünen açık-koyu net kontrastlar, yapay görme uygulaması açısından çok tercih edilmeyebilir. Göz – beyin yorum yapma yeteneğine sahiptir ama kamera/yazılım değildir. Özellikle barkod / karekod okuma gibi işlemlerde gözle görünenin aksine, karanlık kontrastlarda çalışmak daha iyi sonuçlar verecektir. (Aydınlık / fazla ışık, kontrolsüz şekilde ışık patlamalarına / yansımalara yol açabilir. Kural basit, Işık yoksa, yansıma da yok. Tabi, yok dediysek, hiç yok anlamında değil. Gereksiz parlaklık yok anlamında)
  5. Kamera yazılımı Gri renk dağılım histogramı veriyor ise, mutlaka incelenmelidir.

iDS ueye Cockpit programı, alınan görüntüde yatay ve dikey gri renk dağolım profilini bize vermektedir. Her iki profili de açarak, alınan görüntünün hem yatay, hem dikey eksende, yukarıda belirttiğim kurallara uygunluğu hemen görülebilir.

uEye Cockpit programında, yatay ve dikey eksende gri renk dağılımını açmaya yarayan butonlar.

Aşağıda, ideal threshold değerleri ile alınmış resmi görüyorsunuz. (Açık ve koyu arası 100 birimden fazla, açık, 255 e çok yaklaşmamış, koyu ise 0 a çok yaklaşmamış.)

 

Göze daha iyi görünmekle birlikte, yapay görme uygulaması açısından daha kötü sonuçlar verecek olan, yanlış pozlama değerleri (fazla pozlama – over exposure) ile alınmış aynı nesneye ilişkin görüntü ise aşağıdaki gibidir. (Parlak renklerin 255 ile kırpıldığına dikkat edin. Histogram bizi uyarıyor.)

resmi (fazla exposure ile alınmış olan) kaydedip HALCON ile açılıp, threshold değerlerini incelersek, demek istediğim daha net anlaşılacaktır.

Görüldüğü gibi, standart (global) thresholding ile açık rengi seçmek zorlaşmaktadır. (Elbette variable threshold, dynamic threshold vb. yöntemler daha iyi sonuçlar verebilir)

Özetle : Kurulum aşamasında, son derece özenle davranılıp, alınan her görüntü incelenmeli ve iyice tatmin olunmuşsa yazılım uyarlanmasına başlanmalıdır. Aksi halde tekrar tekrar ayar yapıp, yazılımın yeniden güncellenmesini gerektiren çok daha zahmetli yollara girmek gerekebilir.

Kalibrasyon

Özellikle ölçüm, robotik gibi hassas uygulamalarda mutlaka kamera kalibrasyonu yapılmak zorundadır. Hayli zahmetli olduğu için genellikle ihmal edilir. İyi kalibre edilmiş kamera ile 1 mikron hassasiyetli değerlerde ölçüm yapabilmek, 3D modelleme, robotik koordinat sistemleri, gerçek dünya koordinat sistemleri, pixel – mm. tarzı dönüşümler mümkün olabilmektedir. En önemlisi, lens distorsiyonları giderilmekte, balık gözü efekti, (lens küresel  olduğu için oluşan) merkezde ve kenarda ölçüm farklılıkları gibi istenmeyen etkenler giderilmektedir.

HALCON kamera kalibrasyonu için geniş kapsamlı bir modül ve sihirbaz içermektedir. Kamera kalibrasyonu yapabilmek için, öncelikle son derece hassas olarak üretilmiş kalibrasyon plakalarına ihtiyaç vardır. MVTec, farklı ihtiyaçlar için farklı ölçülerde kalibrasyon plakaları üretmiştir. Seramik, metal, şeffaf vb. olabilen kalibrasyon plakaları MAVIS ten temin edilebilir.

HALCON, kullanılan kalibrasyon plakasına bağlı olarak, kalibrasyon plakasının özelliklerini içeren bir description dosyası yüklemeye izin verir. (Kalibrasyon plakası ile birlikte, bir de data dosyası gelmektedir.) Son derece hassas olduğu için pahalı da olan kalibrasyon plakalarından, farklı uygulamalara göre farklı boyutlarda bulundurmak gerekecektir. Böylesine atıl bir stoğu bulundurmak mantıklı olmayacağı için kalibrasyon plakası uygulamanın ihtiyaçları doğrultusunda satın alınmalıdır. Yurt dışından getirmenin zaman alması ya da diğer zorluklardan dolayı MAVIS kendi kalibrasyon plakalarını geliştirmiştir. Farklı boyutlardaki plakalar, 1 mm. kalınlığında özel kağıtlara yüksek hassasiyetli baskı merkezlerinde print edilerek çıkartılmış, her biri için postscript (.ps) ve HALCON description dosyası hazırlanmıştır.

Ölçüm ya da robotik gibi uygulamalar ile uğraşan HALCON kullanıcıları, MAVIS ile iletişime geçerek, uygun fiyatlarda kalibrasyon plakalarına sahip olabilir ve gerçek ölçüm, robotik, 3D uygulamalarını geliştirebilirler.

 

 

HALCON ile Video Processing

Image Processing (Görüntü İşleme) tekniklerinin video dosyalarına uygulanması işlemi HALCON ile mümkündür. Video, her biri işlenebilir bir görüntü içeren ardışıl frame lerden meydana gelmektedir. Dolayısıyla, tek tek bu frame lere erişmek mümkün ise, istenen “video processing” HALCON komutları ile gerçekleştirilebilir.

Video işleme neden gerekli olabilir?

  • Görüntü alınırken, işlemek için yeterli süre yoksa
  • Tüm senaryonun kaydedilip, en sonunda karar verilmesi gerekiyorsa
  • Tek tek Frame olarak görüntü alınamıyorsa
  • Kamera çıktısı video formatında ise
  • Real Time / (Canlı) işleme gerekiyorsa

vb. sebepler sayılabilir.

Sürpriz yumurtadan çıkan motosikletin, arka tekerleğini çıkartıp kamera altında fırıldak gibi döndürdüm. Tekerlek, kendi ekseni üzerinde kamera altında fırıldak gibi dönerken, görüntüyü avi formatında kaydettim. Tekerlek, yüzeyde hangi noktalardan geçti? gibi bir soru aklıma geldi. Tüm görüntü kaydetme işi bittikten sonra, bu avi formatındaki videoyu HALCON da işledim ve cevabı buldum 🙂

Fırıldak gibi dönen tekerleğe ait avi formatlı video (tıklanarak indirilebilir)

HALCON içinde video processing işlemi için, öncelikle video dosyasının open_frame_grabber ile açılması gerekir. Grabber adı olarak “DirectFile” en uygun seçenektir. CameraType değişkeni olarak avi dosyasının adı seçilmelidir. DirectFile için HALCON sürücü dosyasının versiyonu 5.1 olmalıdır. Eski versiyonlar bazı avi dosyalarını iyi tanımayabilir. (HALCON 11 ile 5.0 gelmektedir. MVTec web sitesinden indirilip, 5.1 e yükseltilmelidir)

Tekerleğe ait video içinden ayıklanmış tek bir frame

 

 

 

 

 

 

 

 

 

Tekerleğin geçtiği tüm yollarin deviation_n komutu ile çıkartılmış hali.

 

 

 

 

 

 

 

 

 

şimdi basit bir threshold ile, tekerleğin taradığı tüm alanları belirleyebiliriz.

 

 

 

 

 

 

 

 

 

ve ağırlıklı olarak tekerleğin taradığı alanları belirlemek için, distnace_transform komutundan yararlanabiliriz.

 

 

 

 

 

 

 

 

 

Bütün programın HALCON kodu

gName := 'C:/Users/Mustafa/Desktop/don4.avi'
open_framegrabber ('DirectFile', 1, 1, 0, 0, 0, 0, 'default', 8, 'default', -1, 'false', gName, 'default', 0, -1, AcqHandle)
gen_empty_obj(Images)
for i := 1 to 132 by 1
    grab_image(Image, AcqHandle)
    concat_obj(Images, Image, Images)
endfor
close_framegrabber (AcqHandle)

channels_to_image (Images, MultiChannelImage)
deviation_n (MultiChannelImage, ImageDeviation)
threshold(ImageDeviation, Region, 28, 255)
distance_transform (Region, DistanceImage, 'euclidean', 'true', 1280, 1024)

Plastik parçalar üzerindeki yüzüklerin kontrolü

Otomotiv sektöründe hizmet veren bir firma için yüzük kontrol sistemini devreye aldık. Sistemde 3 farklı ürün bulunmaktadır. Her bir üründe yüzüğün takılacağı yerler ve renkler farklılık göstermektedir. Bu ürünler modellenerek kontrol edilmesi istenen ürünlerin doğru veya hatalı olarak ayrıştırılması sağlanmıştır.

Operatör tarafından kullanıcı girişi yapılabilen, kontrol edilecek modelin listeden seçilebileceği ve sistemin çalıştırılması veya durdurulması gibi işlemleri içeren bir arayüz tasarlanmıştır.

Sistem, konveyör sistemi üzerinde bölmelere ayrılmış bir bandın ilerlerken mekanik sensör yardımıyla adım adım durdurulması, fotoğraf çekilmesi, bu fotoğrafın bilgisayar üzerindeki yazılım ile işlenerek ürünlerin doğru veya hatalı olarak tespit edilmesi, bu bilgilerin ekranda gösterilmesi ve farklı kovalara atılması işlemlerinden oluşmaktadır.

Kontrol edilecek ürünler farklı pozisyonlarda geleceği için bu ürünlerin ve yüzüklerin aranacağı bölgelerin modellenen ürünlere göre döndürülmesi gerekmektedir. Bu işlemi sağlayan HALCON kodu:

// Kontrol edilecek ürünün fotoğrafının okunması
read_image (Image, 'C:/Projects/M1_175740.bmp')
// Matching(Eşleştirme) için kullanılacak modelin okunması
read_shape_model ('C:/Projects/P1-N.shm', ModelId)
//  Matching(Eşleştirme) işlemi
find_shape_model (Image, ModelId, rad(0), rad(360), 0.5, 1, 0.5,['least_squares','max_deformation 2'], [7,1],0.75,ModelRow, ModelColumn, ModelAngle,ModelScore)
    if (ModelScore > 0.75)
        get_shape_model_contours (ModelContours, ModelId, 1)
        hom_mat2d_identity (HomMat)
        hom_mat2d_rotate (HomMat, ModelAngle, 0, 0, HomMat)
        hom_mat2d_translate (HomMat, ModelRow, ModelColumn, HomMat)
        affine_trans_contour_xld (ModelContours, TransContours, HomMat)
        gen_rectangle1 (ModelRegion, 396.643, 361.944, 816.643, 1134.52)
        area_center (ModelRegion, ModelRegionArea, RectificationRow, RectificationCol)
        hom_mat2d_identity (Rectification)
        hom_mat2d_translate (Rectification, RectificationRow-ModelRow, RectificationCol-ModelColumn, Rectification)
        // Ürünün döndürülmesi
        hom_mat2d_rotate (Rectification, -ModelAngle, RectificationRow, RectificationCol,Rectification)
        affine_trans_image (Image, RectifiedImage, Rectification, 'constant', 'false')
    endif

Doğru ve hatalı olarak tespit edilen ürünlerin ekran görüntüleri :

HImage Bitmap, Bitmap HImage dönüşümleri

HALCON içinde resim tipi dosyaların iconic değişken olarak eşdeğeri HImage dir. grab_image, read_image gibi fonksiyonlar direk olarak HImage tipi değişken döndürür. Bazı durumlarda (genelde windows ile programlama yaparken) HALCON HImage nesnesini Bitmap olarak dönüştürmeye ya da Windows Bitmap nesnesini HImage olarak dönüştürmeye ihtiyacımız olabilir.

HALCON içinden grab işlemi yukarıdaki şemaya göredir.

Eğer HALCON image acquisition interface yerine, kameradan Bitmap olarak görüntü almak ve bunu proses etmek gibi işlemlere gereksinim varsa Bitmap to HImage türü fonksiyona ihtiyacımız olabilir. HALCON .net kütüphanesindeki HImage in overload edilmiş yöntemlerinden biri, tam da bu iş için geliştirilmiştir.

            Bitmap bmp = new Bitmap("C:\\Projects\\1.bmp");
            IntPtr pval = IntPtr.Zero;
            BitmapData bd = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
            pval=  bd.Scan0;
            HImage img = new HImage("byte", bmp.Width, bmp.Height, pval);
bmp.Unlock...

gibi bir kodlama, bitmap nesnemizden direk olarak HImage üretmeye yarar.

Projeyi daha derli toplu hale getirmek için ise;

            Bitmap bImage, bImage32;
            System.Drawing.Imaging.BitmapData bmData = null;
            Rectangle rect;
            IntPtr pBitmap;
            IntPtr pPixels;

            HImage hi_Image = new HImage();

            bImage = new Bitmap("C:\\Users\\Public\\Documents\\MVTec\\HALCON-11.0\\examples\\images\\mreut.png");
            pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
            pictureBox1.Image = bImage;

            // Convert 24 bit bitmap to 32 bit bitmap in order to ensure
            // that the bit width of the image (the Stride) is divisible by four.
            // Otherwise, one might obtain skewed conversions.
            bImage32 = new Bitmap(bImage.Width, bImage.Height, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
            Graphics g = Graphics.FromImage(bImage32);
            g.DrawImage(bImage, new Point(0, 0));
            g.Dispose();

            // Obtain the image pointer.
            rect = new Rectangle(0, 0, bImage.Width, bImage.Height);
            bmData = bImage32.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
            pBitmap = bmData.Scan0;
            pPixels = pBitmap;
            unsafe
            {
                // Create HALCON image from the pointer.
                hi_Image.GenImageInterleaved(pPixels, "bgrx", bImage.Width, bImage.Height, -1, "byte", bImage.Width, bImage.Height, 0, 0, -1, 0);
            }
            // Don't forget to unlock the bits again. 😉
            bImage32.UnlockBits(bmData);
            hWindowControl1.HalconWindow.SetPart(0, 0, bImage.Height - 1, bImage.Width - 1);
            hi_Image.DispObj(hWindowControl1.HalconWindow);

gibi daha güvenli bir kod geliştirilebilir. C# formu üzerine koyduğum HWindowControl ve PictureBox bileşenleri ile birlikte, tam çözüm halindeki C#.NET uygulaması ise buradan indirilebilir. Bu çalışan Visual Studio 2008 uygulamasında hem Bitmap ten HImage dönüşümü, hem de HImage den Bitmap dönüşümü kodlanmıştır.

Daha fazla bilgi veya destek için info@mavis.com.tr adresi ile iletişime geçebilirsiniz.