5.25. Noktaları bulma¶
Eşikleme, yakalanan çerçeveyi ikili bir maskeye dönüştürdü: her piksel ya eşik testini geçer ya da geçmez. Bu, uygulamanın önemsediği renklerin sahnede görünüp görünmediği sorusunu yanıtlar, ancak nerede olduğunu değil – maske yalnızca 1’lerden ve 0’lardan oluşan bir denizdir. Bir sonraki adım nokta (blob) tespitidir: maskede gezinmek, geçen piksellerden oluşan bitişik bölgeleri bulmak ve her birini bir konum, bir boyut, bir yönelim ve bir uygulamanın üzerine işlem yapabileceği diğer özelliklere sahip bir nesne olarak döndürmek.
find_blobs(), bu adımın iş gücü metodudur ve image modülünün sonuç-nesnesi dünyasına en yaygın giriş noktasıdır. Renkli bir topu izlemek, zemine boyanmış bir çizgiyi takip etmek, bir termal sensörün gördüğü parlak nokta sayısını saymak, mavi bir LED’in açık mı kapalı mı olduğuna karar vermek – aynı çağrı bunların hepsini kapsar. Girdiler değişir (eşikler, aranan bölge, sonuca uygulanan filtreler), ancak çağrı deseni aynıdır.
5.25.1. Temel çağrı¶
find_blobs bir eşik listesi alır ve bir nokta sonuç nesneleri listesi döndürür:
thresholds = [(30, 100, 15, 127, 15, 127)] # LAB threshold for red
blobs = img.find_blobs(thresholds)
for b in blobs:
img.draw_rectangle(b.rect, color=(255, 0, 0))
img.draw_cross(b.cx, b.cy, color=(255, 0, 0))
Her eşik demeti, binary() metoduna geçirilen eşiklerle aynı biçime sahiptir – bir RGB565 görüntüsü için altı giriş (l_lo, l_hi, a_lo, a_hi, b_lo, b_hi) (sınırlar LAB cinsindendir), bir gri tonlama görüntüsü için iki giriş (lo, hi). Tek bir çağrıda en fazla 32 eşik sağlanabilir; bu da find_blobs() metodunu bu kadar esnek kılan şeydir: kırmızı, yeşil ve mavi işaretçiler eş zamanlı olarak izlenebilir, her biri döndürülen listeye kendi noktalarını katar ve her noktanın code özelliği hangi eşikle eşleştiğini belirtir.
Yukarıdaki draw_rectangle() ve draw_cross() çağrıları, yakalanan çerçeveyi IDE önizlemesi için işaretler. Nokta sonucu zaten b.rect (4’lü demet biçiminde sınırlayıcı kutu) ile b.cx / b.cy (tam sayı ağırlık merkezi) değerlerini taşır, dolayısıyla tespiti çerçeveye geri çizmek iki metot çağrısından ibarettir.
5.25.2. Sonucun içerdikleri¶
Her Blob, tespit edicinin bölge hakkında ölçtüğü her şeyi bir araya paketleyen bir öznitelik demetidir. Özellikler dört gruba ayrılır.
Sınırlayıcı kutu ve ağırlık merkezi grubu – x, y, w, h, rect, cx, cy, cxf, cyf – noktanın konumunu tanımlar. rect, çizim metotlarının beklediği (x, y, w, h) 4’lü demetidir; cx ve cy ağırlık merkezini tam sayı piksel koordinatlarında verir; cxf ve cyf ise ağırlık merkezini alt-piksel kayan nokta koordinatlarında verir; bu da bir üst kaynaklı kalibrasyonun kesirli konumları önemsediği durumlarda kullanışlıdır.
Biçim tanımlayıcıları – pixels, area, density, perimeter, roundness, elongation, compactness, rotation – noktanın neye benzediğini tanımlar. pixels, geçen piksellerin sayısıdır; area, eksene hizalı sınırlayıcı kutunun alanıdır (w * h); density ise bu ikisinin oranıdır ve katı bir dikdörtgen için 1.0‘a yaklaşır, ince bir çapraz çizgi için 0.0‘a doğru düşer. roundness ve compactness, noktanın ne kadar yuvarlak olduğunu farklı geometrik bakış açılarından puanlar (roundness ikinci dereceden momentlerden, compactness çevre-alan oranından); elongation, kolaylık için 1.0 - roundness değeridir. rotation, ana eksenin radyan cinsinden yönelimidir ve uzamış noktalarda en doğrudur, neredeyse yuvarlak olanlarda ise gürültülü hale gelir (belirsiz bir eksenin iyi tanımlanmış bir yönü yoktur).
Eşik ve birleştirme meta verileri – code, count – hangi eşiğin eşleştiğini ve döndürülene kaç kaynak noktanın birleştirildiğini belirtir. code, eşleşen her eşik için bir biti ayarlanmış 32 bitlik bir bit eşlemidir (tek eşik code == 1 verir; birleştirilmiş çok renkli bir nokta birden fazla bite sahip olabilir); count, merge=True birden fazla tespiti bir araya getirmediği sürece 1‘dir.
Köşeler grubu – corners, min_corners – noktanın döndürülmüş geometrisini verir. corners, noktanın konturundan çekilen (x, y) uç noktalarının, sol üstten saat yönünde sıralanmış 4’lü demetidir; min_corners, noktayı çevreleyen en küçük alanlı döndürülmüş dikdörtgenin köşelerinin 4’lü demetidir. En küçük alanlı dikdörtgen sıkı uyumdur; eksene hizalı rect ise piksel ızgarasına hizalanmış gevşek uyumdur. Her ikisi de, bir alt aşamanın yönelimli bir kutuya mı yoksa düz bir kutuya mı ihtiyaç duyduğuna bağlı olarak kullanışlıdır.
Bir nokta; eksene hizalı sınırlayıcı kutuyu (rect, x, y, w, h), ağırlık merkezini (cx, cy veya alt-piksel cxf, cyf), en küçük alanlı döndürülmüş dikdörtgeni (min_corners artı rotation) ve aşağıdaki modül düzeyindeki yardımcılar tarafından hesaplanan isteğe bağlı ana / yan eksen çizgilerini taşır.¶
5.25.3. Aramayı filtreleme¶
Yakalanan bir çerçeve, genellikle uygulamanın önemsediği nesne dışındaki nedenlerle eşikle eşleşen pikseller içerir: aynasal parlamalar, uzaktaki arka plan nesneleri, tesadüfen LAB aralığına düşen görüntü gürültüsü pikselleri. find_blobs() metoduna verilen anahtar sözcük argümanları ilk savunma hattıdır.
roi, aramayı çerçevenin bir bölgesiyle sınırlar; tıpkı diğer her image-modülü metodunun yaptığı gibi. Nesnenin yalnızca görüş alanının alt yarısında görünebileceğini bilen bir uygulama roi=(0, h//2, w, h//2) geçirir ve yukarıdaki her şeyi yok sayar; kazanılan zaman çerçeve hızına geri döner.
area_threshold ve pixels_threshold her ikisi de önemsenemeyecek kadar küçük noktaları filtreler. area_threshold, sınırlayıcı kutusu o sayıdan daha az piksel alanına sahip noktaları eler (dağınık gürültüyü filtrelemek için iyidir); pixels_threshold ise o sayıdan daha az geçen piksele sahip noktaları eler (büyük ama seyrek noktaları, örneğin orada burada bir iki pikseli eşleşen eşiklenmiş bir noktalama desenini filtrelemek için iyidir). Her ikisinin de varsayılanı 10‘dur; birkaç santimetre genişliğinde bir ön plan hedefi için bunları yüzlere çıkarmak, küçük gürültünün her zerresini atar.
x_stride ve y_stride, tarayıcının izini sürmeye başlayacak bir nokta ararken attığı piksel adımını ayarlar. Adım, iz çözünürlüğü değildir – iz her zaman gerçek nokta sınırını tek piksel ayrıntısında takip eder – ancak taramanın bir başlangıç pikselini ne kadar hızlı bulacağını denetler. Noktaların büyük olduğu bilindiğinde (kameradan bir ayak uzaklıkta, kolayca yüz piksel genişliğinde yumruk büyüklüğünde renkli bir hedef), x_stride=4, y_stride=4 tarama süresini, tespitte pratik bir kayıp olmadan on altıda bire indirir. Noktalar küçük olduğunda (birkaç piksel genişliğinde uzaktaki bir LED işaretçi), bunların üzerinden tamamen atlamamak için adımların 1‘de kalması gerekir. invert, eşik testini tersine çevirir: eşleşme eşleşmeme haline gelir ve rutin, geçen piksellerin yerine geçmeyen piksellerin noktalarını döndürür.
threshold_cb, eşiklemeden sonra ancak nihai sonuç listesi oluşturulmadan önce her nokta üzerinde çağrılan bir Python geri çağırmasıdır (callback). Geri çağırma noktayı alır ve onu tutmak için True, atmak için False döndürür. Burası, anahtar sözcük argümanlarının doğrudan açığa çıkarmadığı özellikler üzerinde – minimum bir yoğunluk, belirli bir dönme aralığı, birleştirmeden sonra özel bir kod-bit kombinasyonu gibi – keyfi Python düzeyinde filtreler uygulanacak yerdir. Anahtar sözcük argümanları yerel kod içindeki filtrelerdir ve hızlı çalışır; geri çağırma Python’da çalışır ve daha yavaştır ancak ifade edebildikleri konusunda sınırsızdır.
5.25.4. Örtüşen noktaları birleştirme¶
merge=True, sınırlayıcı dikdörtgenleri örtüşen noktaları bir araya getirmek için sonuç listesini son işleme tabi tutar. Doğal kullanımı, kameranın rengini aynasal parlamalar, gölge çizgileri veya nesne üzerindeki eşleşmeyen aydınlatma nedeniyle birden fazla eşiklenmiş bölge olarak gördüğü bir hedefi tespit etmektir: tek bir kırmızı top, birlikte ele alındığında topun izini çizen üç ya da dört küçük kırmızı nokta olarak geri dönebilir. merge=True ile üç nokta tek bir büyük nokta haline gelir, rect birleşimi kapsar, code birleştirilen noktaların kodlarının bit düzeyinde OR işlemidir (böylece çok renkli bir birleştirme hangi renklerin katkıda bulunduğunu belirtir) ve count kaç kaynak noktanın birleştirildiğini bildirir.
margin, örtüşme testinden önce sınırlayıcı dikdörtgenleri büyütür veya küçültür. margin=2 ile sınırlayıcı dikdörtgenleri birbirinin 2 piksel yakınına gelen noktalar yine de birleşir; margin=-2 ile yalnızca sınırlayıcı dikdörtgenleri en az 2 piksel örtüşen noktalar birleşir. Doğal ayarlama: eşiğin bitişik parçalara böldüğü noktaları ele almak için pozitif kenar boşluğu; sıkıca gruplanmış ayrı nesneleri ayrı tutmak için negatif kenar boşluğu.
merge_cb, birleştirme gerçekleşmeden önce her aday çift üzerinde çalışır. Geri çağırma iki noktayı alır ve birleştirmeye izin vermek için True, engellemek için False döndürür. Bu, geometrik kuralın kaçırdığı birleştirmeleri çapraz denetlemek için doğru araçtır – örneğin, rotation açıları bir eşikten fazla uyuşmayan iki noktayı birleştirmeyi reddetmek ya da küçük olan yalnızca beneklenme ise küçük bir noktayı çok daha büyük bir noktayla birleştirmeyi reddetmek.
5.25.5. İzdüşüm histogramları¶
x_hist_bins_max ve y_hist_bins_max, her noktaya isteğe bağlı izdüşüm histogramları ekler. Bir izdüşüm histogramı, bir eksen boyunca geçen piksellerin sayısıdır: X ekseni histogramı, noktanın sınırlayıcı kutusu içinde sütun başına geçen pikselleri toplar ve Y ekseni histogramı satır başına toplar. Her ikisinin de varsayılanı sıfırdır – sıfır olmayan bir max sağlanmadıkça histogramlar hesaplanmaz, aksi takdirde her tespite iş yükü ekleyeceklerdir.
Hesaplandıklarında histogramlar, bir uygulamanın üzerinde daha fazla analiz yürütebileceği ucuz bir 1 boyutlu sinyal sağlar: noktanın içindeki dikey bir şeridin konumunu tespit etmek, iki renkli bir hedefin kırılma noktasını bulmak, uzun eksen boyunca kaç boşluk göründüğünü saymak. Bunlar, her Blob üzerinde x_hist_bins ve y_hist_bins özellikleri olarak doldurulur.
5.25.6. Ek geometrik yardımcılar¶
Bir noktayı alıp istenen ölçümü döndüren birkaç ek geometrik ölçü, modül düzeyindeki işlevler olarak bulunur:
image.get_solidity(), noktanın katılığını döndürür – pikseller, dışbükey örtünün alanına bölünür. Katı, dolu bir bölge1.0‘a yakındır; içbükeyliklere sahip bir nokta (bir at nalı, parmakları açılmış bir el) bunun çok altına düşer.image.get_convexity(), dışbükeyliği döndürür – dışbükey örtü çevresinin, noktanın çevresine bölümü. Mükemmel dışbükey bir nokta1.0‘dır; pürüzlü veya çentikli noktalar daha düşüktür.image.get_major_axis_line()veimage.get_minor_axis_line(), döndürülmüş en küçük alanlı dikdörtgenden türetilen, noktanın ana ve yan eksenleri boyuncaLinenesneleri döndürür.image.get_enclosing_circle(), noktayı çevreleyen birCircledöndürür – bir alt aşama çizmek veya karşılaştırmak için bir daire istediğinde kullanışlıdır.image.get_enclosed_ellipse(), noktanın en küçük alanlı dikdörtgenine yazılmış bir elips için(cx, cy, rx, ry, rotation)5’li demetini döndürür. Değerler doğrudandraw_ellipse()metoduna beslenir.
5.25.7. Bir eşiği otomatik öğrenme¶
Bir nokta tespit edicisi, ancak çalıştırıldığı eşikler kadar iyidir ve bir hedef renk için doğru eşiği bulma işi başlı başına bir sorundur. İki yaygın desen bu işi azaltır.
Birincisi IDE’de etkileşimli seçimdir: bir çerçeve yakalayın, hedef rengin bir örneğinin etrafına bir dikdörtgen sürükleyin ve IDE’nin eşik düzenleyicisinin gördüğü LAB sınırlarını bildirmesine izin verin. Bu sınırlar betiğe find_blobs() eşikleri olarak düşer ve tespit edici hazırdır.
İkincisi programatik otomatik öğrenmedir: kamerada çalışan bir kalibrasyon rutini bir çerçeve yakalar, hedefin bulunduğu bilinen bir yamanın histogramını alır (roi= ile get_histogram()) ve yamanın değer aralığını histogramdan get_percentile() ile okur. 5. yüzdelik dilim her kanalın alt sınırını, 95. ise üst sınırını ayarlar ve her iki uçtaki başıboş aykırı pikselleri yok sayar. Bir RGB565 görüntüsünde tek bir yüzdelik dilim çağrısı üç LAB kanalının tümünü bir kerede bildirir, dolayısıyla iki çağrı find_blobs() metodunun beklediği altı sayıyı üretir:
h = img.get_histogram(roi=patch)
lo = h.get_percentile(0.05)
hi = h.get_percentile(0.95)
threshold = (lo.l_value, hi.l_value,
lo.a_value, hi.a_value,
lo.b_value, hi.b_value)